PySMT 0.9.7.dev452__tar.gz → 0.9.7.dev461__tar.gz

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.
Files changed (164) hide show
  1. {pysmt-0.9.7.dev452/PySMT.egg-info → pysmt-0.9.7.dev461}/PKG-INFO +1 -1
  2. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461/PySMT.egg-info}/PKG-INFO +1 -1
  3. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/README.rst +19 -19
  4. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/__init__.py +1 -1
  5. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/exceptions.py +10 -0
  6. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/factory.py +13 -2
  7. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/formula.py +3 -2
  8. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/parsing.py +5 -1
  9. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/msat.py +60 -13
  10. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/solver.py +23 -0
  11. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/z3.py +9 -4
  12. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/examples.py +4 -4
  13. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_env.py +12 -0
  14. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_nlira.py +28 -32
  15. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_regressions.py +61 -1
  16. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_solving.py +0 -1
  17. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/LICENSE +0 -0
  18. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/MANIFEST.in +0 -0
  19. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/NOTICE +0 -0
  20. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/PySMT.egg-info/SOURCES.txt +0 -0
  21. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/PySMT.egg-info/dependency_links.txt +0 -0
  22. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/PySMT.egg-info/entry_points.txt +0 -0
  23. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/PySMT.egg-info/top_level.txt +0 -0
  24. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/docs/CHANGES.rst +0 -0
  25. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/docs/api_ref.rst +0 -0
  26. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/docs/development.rst +0 -0
  27. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/docs/getting_started.rst +0 -0
  28. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/docs/index.rst +0 -0
  29. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/docs/tutorials/boolean_logic.rst +0 -0
  30. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/docs/tutorials.rst +0 -0
  31. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/__main__.py +0 -0
  32. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/__init__.py +0 -0
  33. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/check_version.py +0 -0
  34. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/install.py +0 -0
  35. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/__init__.py +0 -0
  36. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/base.py +0 -0
  37. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/bdd.py +0 -0
  38. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/btor.py +0 -0
  39. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/cvcfive.py +0 -0
  40. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/cvcfour.py +0 -0
  41. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/msat.py +0 -0
  42. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/optimsat.py +0 -0
  43. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/pico.py +0 -0
  44. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/yices.py +0 -0
  45. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/installers/z3.py +0 -0
  46. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/cmd/shell.py +0 -0
  47. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/configuration.py +0 -0
  48. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/constants.py +0 -0
  49. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/decorators.py +0 -0
  50. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/environment.py +0 -0
  51. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/fnode.py +0 -0
  52. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/logics.py +0 -0
  53. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/operators.py +0 -0
  54. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/optimization/__init__.py +0 -0
  55. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/optimization/goal.py +0 -0
  56. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/optimization/msat.py +0 -0
  57. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/optimization/optimizer.py +0 -0
  58. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/optimization/optimsat.py +0 -0
  59. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/optimization/yices.py +0 -0
  60. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/optimization/z3.py +0 -0
  61. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/oracles.py +0 -0
  62. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/printers.py +0 -0
  63. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/rewritings.py +0 -0
  64. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/shortcuts.py +0 -0
  65. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/simplifier.py +0 -0
  66. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/__init__.py +0 -0
  67. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/annotations.py +0 -0
  68. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/commands.py +0 -0
  69. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/parser/__init__.py +0 -0
  70. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/parser/parser.py +0 -0
  71. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/printers.py +0 -0
  72. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/script.py +0 -0
  73. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/solver.py +0 -0
  74. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/smtlib/utils.py +0 -0
  75. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/__init__.py +0 -0
  76. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/bdd.py +0 -0
  77. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/btor.py +0 -0
  78. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/cvcfive.py +0 -0
  79. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/cvcfour.py +0 -0
  80. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/dynmsat.py +0 -0
  81. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/eager.py +0 -0
  82. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/interpolation.py +0 -0
  83. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/options.py +0 -0
  84. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/pico.py +0 -0
  85. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/portfolio.py +0 -0
  86. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/qelim.py +0 -0
  87. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/smtlib.py +0 -0
  88. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/solvers/yices.py +0 -0
  89. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/substituter.py +0 -0
  90. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/__init__.py +0 -0
  91. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/configs/config1.ini +0 -0
  92. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/configs/config_bad.ini +0 -0
  93. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/omt_examples.py +0 -0
  94. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/optimization_utils.py +0 -0
  95. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/__init__.py +0 -0
  96. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/parser_utils.py +0 -0
  97. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_annotations.py +0 -0
  98. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_fuzzed.py +0 -0
  99. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_generic_wrapper.py +0 -0
  100. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_griggio.py +0 -0
  101. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_model_validation.py +0 -0
  102. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_omt_lib_solver.py +0 -0
  103. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_examples.py +0 -0
  104. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_extensibility.py +0 -0
  105. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_lra.py +0 -0
  106. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_omt.py +0 -0
  107. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_arrays.py +0 -0
  108. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_lia.py +0 -0
  109. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_lira.py +0 -0
  110. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_lra.py +0 -0
  111. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_nia.py +0 -0
  112. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_nra.py +0 -0
  113. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_uf.py +0 -0
  114. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_qf_ufbv.py +0 -0
  115. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_parser_type_error.py +0 -0
  116. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/smtlib/test_smtlibscript.py +0 -0
  117. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_array.py +0 -0
  118. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_back.py +0 -0
  119. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_bdd.py +0 -0
  120. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_bv.py +0 -0
  121. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_bv_simplification.py +0 -0
  122. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_cnf.py +0 -0
  123. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_configuration.py +0 -0
  124. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_constants.py +0 -0
  125. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_cvc_quantifiers.py +0 -0
  126. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_dwf.py +0 -0
  127. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_eager_model.py +0 -0
  128. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_euf.py +0 -0
  129. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_formula.py +0 -0
  130. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_hr_parsing.py +0 -0
  131. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_imports.py +0 -0
  132. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_int.py +0 -0
  133. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_interpolation.py +0 -0
  134. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_lira.py +0 -0
  135. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_logics.py +0 -0
  136. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_models.py +0 -0
  137. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_native_qe.py +0 -0
  138. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_nia.py +0 -0
  139. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_optimization.py +0 -0
  140. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_optimizing.py +0 -0
  141. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_oracles.py +0 -0
  142. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_portfolio.py +0 -0
  143. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_printing.py +0 -0
  144. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_qe.py +0 -0
  145. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_rewritings.py +0 -0
  146. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_shannon_expansion.py +0 -0
  147. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_simplify.py +0 -0
  148. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_size.py +0 -0
  149. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_sorts.py +0 -0
  150. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_string.py +0 -0
  151. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_typechecker.py +0 -0
  152. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_unsat_cores.py +0 -0
  153. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_walker_ext.py +0 -0
  154. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/test/test_walkers.py +0 -0
  155. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/type_checker.py +0 -0
  156. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/typing.py +0 -0
  157. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/utils.py +0 -0
  158. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/walkers/__init__.py +0 -0
  159. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/walkers/dag.py +0 -0
  160. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/walkers/generic.py +0 -0
  161. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/walkers/identitydag.py +0 -0
  162. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/pysmt/walkers/tree.py +0 -0
  163. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/setup.cfg +0 -0
  164. {pysmt-0.9.7.dev452 → pysmt-0.9.7.dev461}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PySMT
3
- Version: 0.9.7.dev452
3
+ Version: 0.9.7.dev461
4
4
  Summary: A solver-agnostic library for SMT Formulae manipulation and solving
5
5
  Home-page: http://www.pysmt.org
6
6
  Author: PySMT Team
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PySMT
3
- Version: 0.9.7.dev452
3
+ Version: 0.9.7.dev461
4
4
  Summary: A solver-agnostic library for SMT Formulae manipulation and solving
5
5
  Home-page: http://www.pysmt.org
6
6
  Author: PySMT Team
@@ -232,25 +232,25 @@ Solvers Support
232
232
  The following table summarizes the features supported via pySMT for
233
233
  each of the available solvers.
234
234
 
235
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
236
- | Solver | pySMT name| Supported Theories | Quantifiers | Quantifier Elimination | Unsat Core | Interpolation|
237
- +==================+===========+================================+=============+========================+============+==============+
238
- | MathSAT | msat | UF, LIA, LRA, BV, AX | No | msat-fm, msat-lw | Yes | Yes |
239
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
240
- | Z3 | z3 | UF, LIA, LRA, BV, AX, NRA, NIA | Yes | z3 | Yes | No |
241
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
242
- | cvc5 | cvc5 | UF, LIA, LRA, BV, AX, S | Yes | No | No | No |
243
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
244
- | Yices | yices | UF, LIA, LRA, BV | No | No | No | No |
245
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
246
- | Boolector | btor | UF, BV, AX | No | No | No | No |
247
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
248
- | SMT-Lib Interface| <custom> | UF, LIA, LRA, BV, AX | Yes | No | No | No |
249
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
250
- | PicoSAT | picosat | [None] | No | [No] | No | No |
251
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
252
- | BDD (CUDD) | bdd | [None] | Yes | bdd | No | No |
253
- +------------------+-----------+--------------------------------+-------------+------------------------+------------+--------------+
235
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
236
+ | Solver | pySMT name| Supported Theories | Quantifiers | Quantifier Elimination | Unsat Core | Interpolation|
237
+ +==================+===========+===================================+=============+========================+============+==============+
238
+ | MathSAT | msat | UF, LIA, LRA, BV, AX, NRA, NIA | No | msat-fm, msat-lw | Yes | Yes |
239
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
240
+ | Z3 | z3 | UF, LIA, LRA, BV, AX, NRA, NIA | Yes | z3 | Yes | No |
241
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
242
+ | cvc5 | cvc5 | UF, LIA, LRA, BV, AX, S, NRA, NIA | Yes | No | No | No |
243
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
244
+ | Yices | yices | UF, LIA, LRA, BV | No | No | No | No |
245
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
246
+ | Boolector | btor | UF, BV, AX | No | No | No | No |
247
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
248
+ | SMT-Lib Interface| <custom> | UF, LIA, LRA, BV, AX | Yes | No | No | No |
249
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
250
+ | PicoSAT | picosat | [None] | No | [No] | No | No |
251
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
252
+ | BDD (CUDD) | bdd | [None] | Yes | bdd | No | No |
253
+ +------------------+-----------+-----------------------------------+-------------+------------------------+------------+--------------+
254
254
 
255
255
 
256
256
 
@@ -19,7 +19,7 @@
19
19
  from typing import Tuple, Union
20
20
 
21
21
 
22
- VERSION: Union[Tuple[int, int, int], Tuple[int, int, int, str, int]] = (0, 9, 7, "dev", 452)
22
+ VERSION: Union[Tuple[int, int, int], Tuple[int, int, int, str, int]] = (0, 9, 7, "dev", 461)
23
23
 
24
24
  # Try to provide human-readable version of latest commit for dev versions
25
25
  # E.g. v0.5.1-4-g49a49f2-wip
@@ -131,6 +131,16 @@ class PysmtImportError(PysmtException, ImportError):
131
131
  class PysmtValueError(PysmtException, ValueError):
132
132
  pass
133
133
 
134
+ class PysmtEmptySymbolNameError(PysmtValueError):
135
+ """A symbol with the empty name was built, but they are not enabled."""
136
+
137
+ def __init__(self):
138
+ PysmtValueError.__init__(
139
+ self,
140
+ "The empty string is not a valid symbol name. SMT-LIB allows it "
141
+ "(as `||`), but not every solver does, so pySMT requires it to be "
142
+ "enabled explicitly by setting `env.allow_empty_var_names = True`.")
143
+
134
144
  class PysmtTypeError(PysmtException, TypeError):
135
145
  pass
136
146
 
@@ -190,13 +190,15 @@ class Factory(object):
190
190
 
191
191
  if logic is None:
192
192
  logic = default_logic
193
+ assert isinstance(logic, Logic)
193
194
 
194
195
  solvers = self._filter_solvers(solver_list, logic=logic)
195
196
 
196
197
  if solvers is not None and len(solvers) > 0:
197
198
  # Pick the first solver based on preference list
198
199
  preference_list = self.preferences[solver_type]
199
- SolverClass = self._pick_favorite(preference_list, solver_list, solvers)
200
+ SolverClass = self._pick_favorite(preference_list, solver_list,
201
+ solvers, logic)
200
202
  closer_logic = get_closer_logic(SolverClass.LOGICS, logic)
201
203
  return SolverClass, closer_logic
202
204
 
@@ -205,7 +207,16 @@ class Factory(object):
205
207
  (solver_type, logic))
206
208
 
207
209
 
208
- def _pick_favorite(self, preference_list: List[str], solver_list: Dict[str, Any], solvers: Dict[str, Any]) -> Type[Solver]:
210
+ def _pick_favorite(self, preference_list: List[str], solver_list: Dict[str, Any],
211
+ solvers: Dict[str, Any], logic: Logic) -> Type[Solver]:
212
+ if not logic.theory.linear:
213
+ # The MathSAT family solves nonlinear problems by incremental
214
+ # linearization, which may not terminate on satisfiable instances
215
+ # whose solutions are all irrational (see the note on
216
+ # MathSAT5Solver.LOGICS). Prefer any other capable solver, but keep
217
+ # them as a fallback when nothing else supports the logic.
218
+ preference_list = sorted(preference_list,
219
+ key=lambda n: n.startswith(("msat", "optimsat")))
209
220
  for candidate in preference_list:
210
221
  if candidate in solvers:
211
222
  return solver_list[candidate]
@@ -45,7 +45,8 @@ import pysmt.operators as op
45
45
  from pysmt.fnode import FNode
46
46
  from pysmt.typing import PySMTType
47
47
  from pysmt.fnode import FNode, FNodeContent
48
- from pysmt.exceptions import UndefinedSymbolError, PysmtValueError,PysmtTypeError
48
+ from pysmt.exceptions import (UndefinedSymbolError, PysmtValueError,
49
+ PysmtTypeError, PysmtEmptySymbolNameError)
49
50
  from pysmt.walkers.identitydag import IdentityDagWalker
50
51
  from pysmt.constants import Fraction, Numeral
51
52
  from pysmt.constants import (is_pysmt_fraction,
@@ -107,7 +108,7 @@ class FormulaManager(object):
107
108
 
108
109
  def _create_symbol(self, name: str, typename: PySMTType=types.BOOL) -> FNode:
109
110
  if len(name) == 0 and not self.env.allow_empty_var_names:
110
- raise PysmtValueError("Empty string is not a valid name")
111
+ raise PysmtEmptySymbolNameError()
111
112
  if not isinstance(typename, types.PySMTType):
112
113
  raise PysmtValueError("typename must be a PySMTType.")
113
114
  n = self.create_node(node_type=op.SYMBOL,
@@ -22,7 +22,8 @@ from typing import List, Optional
22
22
  import pysmt
23
23
  import pysmt.typing as types
24
24
  from pysmt.environment import get_env
25
- from pysmt.exceptions import PysmtSyntaxError, UndefinedSymbolError
25
+ from pysmt.exceptions import (PysmtSyntaxError, UndefinedSymbolError,
26
+ PysmtEmptySymbolNameError)
26
27
  from pysmt.constants import Fraction
27
28
 
28
29
 
@@ -332,6 +333,9 @@ class Constant(GrammarSymbol):
332
333
  class Identifier(GrammarSymbol):
333
334
  def __init__(self, name, env):
334
335
  GrammarSymbol.__init__(self)
336
+ if name == "" and not env.allow_empty_var_names:
337
+ # Otherwise this would be reported as an undefined symbol
338
+ raise PysmtEmptySymbolNameError()
335
339
  self.value = env.formula_manager.get_symbol(name)
336
340
  if self.value is None:
337
341
  raise UndefinedSymbolError(name)
@@ -35,7 +35,7 @@ from pysmt.utils import assert_not_none
35
35
  from pysmt.walkers import DagWalker
36
36
  from pysmt.exceptions import (SolverReturnedUnknownResultError,
37
37
  InternalSolverError,
38
- NonLinearError, PysmtValueError, PysmtTypeError,
38
+ PysmtValueError, PysmtTypeError,
39
39
  ConvertExpressionError)
40
40
  from pysmt.decorators import clear_pending_pop, catch_conversion_error
41
41
  from pysmt.solvers.qelim import QuantifierEliminator
@@ -180,9 +180,37 @@ class MathSAT5Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolv
180
180
 
181
181
  __lib_name__ = "mathsat"
182
182
 
183
+ # NOTE on nonlinear arithmetic (QF_NRA/QF_NIA, and OptiMathSAT, which
184
+ # inherits this LOGICS set).
185
+ #
186
+ # MathSAT solves nonlinear problems by incremental linearization: the
187
+ # nonlinear terms are abstracted away as free symbols and then
188
+ # progressively constrained with linear lemmas, until either the
189
+ # abstraction is refuted (UNSAT) or a model of the abstraction happens to
190
+ # be a model of the original formula (SAT). Every model MathSAT can build
191
+ # therefore assigns *rational* values only; irrational (algebraic) values
192
+ # are not representable.
193
+ #
194
+ # This is fine for UNSAT instances and for SAT instances that admit a
195
+ # rational solution, but not for SAT instances whose solutions are all
196
+ # irrational: on e.g. `x * x = 2` no finite set of linear lemmas refutes
197
+ # the abstraction, and no model of the abstraction ever satisfies the
198
+ # original constraint, so the refinement loop does not terminate. MathSAT
199
+ # diverges rather than returning `unknown`, and there is currently no
200
+ # option to bound the number of refinement rounds. The only available
201
+ # mitigation is a soft timeout installed with `msat_set_termination_test`,
202
+ # which pySMT does not expose, and which could only be wall-clock based
203
+ # (hence non-reproducible), since the internal statistics that would give a
204
+ # deterministic budget cannot be retrieved through the API.
205
+ # See the discussion in https://github.com/pysmt/pysmt/pull/844.
206
+ #
207
+ # Practical consequences:
208
+ # - formulas that need algebraic witnesses must be sent to a solver with a
209
+ # complete NRA decision procedure (z3, cvc5);
210
+ # - the nonlinear examples and tests run against MathSAT are kept
211
+ # rational on purpose (e.g. `r * r = 4.0` instead of `r * r = 2.0`).
183
212
  LOGICS: Iterable[Logic] = PYSMT_QF_LOGICS -\
184
- set(l for l in PYSMT_QF_LOGICS \
185
- if not l.theory.linear or l.theory.strings)
213
+ set(l for l in PYSMT_QF_LOGICS if l.theory.strings)
186
214
 
187
215
  OptionsClass = MathSATOptions
188
216
 
@@ -407,6 +435,7 @@ class MSatConverter(Converter, DagWalker):
407
435
  self._msat_lib.MSAT_TAG_LEQ: self._back_adapter(self.mgr.LE),
408
436
  self._msat_lib.MSAT_TAG_PLUS: self._back_adapter(self.mgr.Plus),
409
437
  self._msat_lib.MSAT_TAG_TIMES: self._back_adapter(self.mgr.Times),
438
+ self._msat_lib.MSAT_TAG_DIVIDE: self._back_adapter(self.mgr.Div),
410
439
  self._msat_lib.MSAT_TAG_BV_MUL: self._back_adapter(self.mgr.BVMul),
411
440
  self._msat_lib.MSAT_TAG_BV_ADD: self._back_adapter(self.mgr.BVAdd),
412
441
  self._msat_lib.MSAT_TAG_BV_UDIV: self._back_adapter(self.mgr.BVUDiv),
@@ -463,6 +492,7 @@ class MSatConverter(Converter, DagWalker):
463
492
  self._msat_lib.MSAT_TAG_LEQ: self._sig_most_generic_bool_binary,
464
493
  self._msat_lib.MSAT_TAG_PLUS: self._sig_most_generic_bool_binary,
465
494
  self._msat_lib.MSAT_TAG_TIMES: self._sig_most_generic_bool_binary,
495
+ self._msat_lib.MSAT_TAG_DIVIDE: self._sig_most_generic_bool_binary,
466
496
  self._msat_lib.MSAT_TAG_FLOOR: lambda term, args:\
467
497
  self.tm.FunctionType(types.INT, [types.REAL]),
468
498
  self._msat_lib.MSAT_TAG_BV_MUL: self._sig_binary,
@@ -700,7 +730,7 @@ class MSatConverter(Converter, DagWalker):
700
730
  val, width = map(int, str(term).split("_"))
701
731
  res = self.mgr.BV(val, width)
702
732
  elif self._msat_lib.msat_term_is_constant(self.msat_env(), term):
703
- rep = self._msat_lib.msat_term_repr(term)
733
+ rep = self._restore_empty(self._msat_lib.msat_term_repr(term))
704
734
  ty = self._msat_lib.msat_term_get_type(term)
705
735
  if self._msat_lib.msat_term_is_boolean_constant(self.msat_env(), term):
706
736
  res = self.mgr.Symbol(rep, types.BOOL)
@@ -987,16 +1017,33 @@ class MSatConverter(Converter, DagWalker):
987
1017
 
988
1018
  def walk_times(self, formula: FNode, args: List[Any], **kwargs) -> Any:
989
1019
  res = args[0]
990
- nl_count = 0 if self._msat_lib.msat_term_is_number(self.msat_env(), res) else 1
991
1020
  for x in args[1:]:
992
- if not self._msat_lib.msat_term_is_number(self.msat_env(), x):
993
- nl_count += 1
994
- if nl_count >= 2:
995
- raise NonLinearError(formula)
996
- else:
997
- res = self._msat_lib.msat_make_times(self.msat_env(), res, x)
1021
+ res = self._msat_lib.msat_make_times(self.msat_env(), res, x)
998
1022
  return res
999
1023
 
1024
+ def walk_pow(self, formula: FNode, args: List[Any], **kwargs) -> Any:
1025
+ # MathSAT rejects exponents it cannot handle by returning an error
1026
+ # term, which convert() turns into an InternalSolverError.
1027
+ return self._msat_lib.msat_make_pow(self.msat_env(), args[0], args[1])
1028
+
1029
+ def walk_div(self, formula: FNode, args: List[Any], **kwargs) -> Any:
1030
+ num, den = args
1031
+ if self.env.stc.get_type(formula).is_real_type():
1032
+ return self._msat_lib.msat_make_divide(self.msat_env(), num, den)
1033
+ # msat_make_divide is real division, while pySMT follows the SMT-LIB
1034
+ # semantics for integers: den >= 0 ? floor(num/den) : ceil(num/den).
1035
+ # ceil(a) is rewritten as -floor(-a).
1036
+ zero = self._msat_lib.msat_make_number(self.msat_env(), "0")
1037
+ neg = self._msat_lib.msat_make_number(self.msat_env(), "-1")
1038
+ cond = self._msat_lib.msat_make_leq(self.msat_env(), zero, den)
1039
+ div = self._msat_lib.msat_make_floor(self.msat_env(),
1040
+ self._msat_lib.msat_make_divide(self.msat_env(), num, den))
1041
+ n_den = self._msat_lib.msat_make_times(self.msat_env(), neg, den)
1042
+ n_div = self._msat_lib.msat_make_times(self.msat_env(), neg,
1043
+ self._msat_lib.msat_make_floor(self.msat_env(),
1044
+ self._msat_lib.msat_make_divide(self.msat_env(), num, n_den)))
1045
+ return self._msat_lib.msat_make_term_ite(self.msat_env(), cond, div, n_div)
1046
+
1000
1047
  def walk_function(self, formula: FNode, args: List[Any], **kwargs) -> Any:
1001
1048
  name = formula.function_name()
1002
1049
  if name not in self.symbol_to_decl:
@@ -1094,10 +1141,10 @@ class MSatConverter(Converter, DagWalker):
1094
1141
  if not var.is_symbol():
1095
1142
  raise PysmtTypeError("Trying to declare as a variable something "
1096
1143
  "that is not a symbol: %s" % var)
1097
- if var.symbol_name() not in self.symbol_to_decl:
1144
+ if var not in self.symbol_to_decl:
1098
1145
  tp = self._type_to_msat(var.symbol_type())
1099
1146
  decl = self._msat_lib.msat_declare_function(self.msat_env(),
1100
- var.symbol_name(),
1147
+ self._rename_empty(var.symbol_name()),
1101
1148
  tp)
1102
1149
  if self._msat_lib.MSAT_ERROR_DECL(decl):
1103
1150
  msat_msg = self._msat_lib.msat_last_error_message(self.msat_env())
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
  from fractions import Fraction
19
+ import pysmt.formula
19
20
  from pysmt.typing import BOOL
20
21
  from pysmt.solvers.options import SolverOptions
21
22
  from pysmt.decorators import clear_pending_pop
@@ -566,3 +567,25 @@ class Converter(object):
566
567
  def back(self, expr: Any, *args: Any, **kwargs: Any) -> FNode:
567
568
  """Convert an expression of the Solver into a PySMT term."""
568
569
  raise NotImplementedError
570
+
571
+ # SMT-LIB allows a symbol with the empty name (`||`), but some
572
+ # solvers refuse to declare it (MathSAT) or cannot print it back
573
+ # (Z3). Those converters rename it to a fresh, unused name on the
574
+ # way in and undo the renaming on the way out.
575
+ _empty_name_subst: Optional[str] = None
576
+ mgr: 'pysmt.formula.FormulaManager'
577
+
578
+ def _rename_empty(self, name: str) -> str:
579
+ """Map a pySMT symbol name to the name used by the solver."""
580
+ if name != "":
581
+ return name
582
+ if self._empty_name_subst is None:
583
+ i = 0
584
+ while ("__pysmt_empty_name_%d" % i) in self.mgr.symbols:
585
+ i += 1
586
+ self._empty_name_subst = "__pysmt_empty_name_%d" % i
587
+ return self._empty_name_subst
588
+
589
+ def _restore_empty(self, name: str) -> str:
590
+ """Inverse of _rename_empty()."""
591
+ return "" if name == self._empty_name_subst else name
@@ -573,7 +573,7 @@ class Z3Converter(Converter, DagWalker):
573
573
  else:
574
574
  # it must be a symbol
575
575
  try:
576
- return self.mgr.get_symbol(str(expr))
576
+ return self.mgr.get_symbol(self._restore_empty(str(expr)))
577
577
  except UndefinedSymbolError:
578
578
  import warnings
579
579
  symb_type = self._z3_to_type(expr.sort())
@@ -582,7 +582,7 @@ class Z3Converter(Converter, DagWalker):
582
582
  template="__z3_%d")
583
583
  elif z3.is_function(expr):
584
584
  # This needs to be after we try to convert regular Symbols
585
- fsymbol = self.mgr.get_symbol(expr.decl().name())
585
+ fsymbol = self.mgr.get_symbol(self._restore_empty(expr.decl().name()))
586
586
  return self.mgr.Function(fsymbol, args)
587
587
 
588
588
  # If we reach this point, we did not manage to translate the expression
@@ -622,6 +622,11 @@ class Z3Converter(Converter, DagWalker):
622
622
  expr.ast)
623
623
  stream_in = StringIO(s)
624
624
  r = parser.get_script(stream_in).get_last_formula(self.mgr)
625
+ if self._empty_name_subst is not None:
626
+ # Undo the renaming of the empty symbol name (see Converter)
627
+ src = self.mgr.get_symbol(self._empty_name_subst)
628
+ r = self.env.substituter.substitute(
629
+ r, {src: self.mgr.Symbol("", src.symbol_type())})
625
630
  key = (askey(expr), None)
626
631
  self._back_memoization[key] = r
627
632
  return r
@@ -642,7 +647,7 @@ class Z3Converter(Converter, DagWalker):
642
647
 
643
648
  def walk_symbol(self, formula: FNode, **kwargs) -> z3.Ast:
644
649
  symbol_type = formula.symbol_type()
645
- sname = formula.symbol_name()
650
+ sname = self._rename_empty(formula.symbol_name())
646
651
  z3_sname = z3.Z3_mk_string_symbol(self.ctx.ref(), sname)
647
652
  if symbol_type.is_bool_type():
648
653
  sort_ast = self.z3BoolSort.ast
@@ -756,7 +761,7 @@ class Z3Converter(Converter, DagWalker):
756
761
  z3dom[i] = self._type_to_z3(t).ast
757
762
  z3ret = self._type_to_z3(tp.return_type).ast
758
763
  z3name = z3.Z3_mk_string_symbol(self.ctx.ref(),
759
- func_name.symbol_name())
764
+ self._rename_empty(func_name.symbol_name()))
760
765
  z3func = z3.Z3_mk_func_decl(self.ctx.ref(), z3name,
761
766
  arity, z3dom, z3ret)
762
767
  self._z3_func_decl_cache[func_name] = z3func
@@ -925,8 +925,8 @@ def get_full_example_formulae(environment: Optional[Environment]=None) -> List[E
925
925
  logic=pysmt.logics.QF_NRA
926
926
  ),
927
927
 
928
- Example(hr="(2.0 = (r * r))",
929
- expr=Equals(Real(2), Times(r,r)),
928
+ Example(hr="(4.0 = (r * r))",
929
+ expr=Equals(Real(4), Times(r,r)),
930
930
  is_valid=False,
931
931
  is_sat=True,
932
932
  logic=pysmt.logics.QF_NRA
@@ -946,8 +946,8 @@ def get_full_example_formulae(environment: Optional[Environment]=None) -> List[E
946
946
  logic=pysmt.logics.QF_NRA
947
947
  ),
948
948
 
949
- Example(hr="((r * r * r) = 25.0)",
950
- expr=Equals(Times(r, r, r), Real(25)),
949
+ Example(hr="((r * r * r) = 27.0)",
950
+ expr=Equals(Times(r, r, r), Real(27)),
951
951
  is_valid=False,
952
952
  is_sat=True,
953
953
  logic=pysmt.logics.QF_NRA
@@ -203,5 +203,17 @@ class TestEnvironment(TestCase):
203
203
  factory.get_quantifier_eliminator()
204
204
 
205
205
 
206
+ def test_nonlinear_demotes_mathsat(self):
207
+ # The MathSAT family is the last resort on nonlinear logics, but still
208
+ # picked when it is the only capable solver.
209
+ pick = get_env().factory._pick_favorite
210
+ available = {'msat': 'MSAT', 'z3': 'Z3'}
211
+ prefs = ['msat', 'z3']
212
+ self.assertEqual(pick(prefs, available, available, logics.QF_NRA), 'Z3')
213
+ self.assertEqual(pick(prefs, available, available, logics.QF_LRA), 'MSAT')
214
+ only_msat = {'msat': 'MSAT'}
215
+ self.assertEqual(pick(prefs, only_msat, only_msat, logics.QF_NRA), 'MSAT')
216
+
217
+
206
218
  if __name__ == '__main__':
207
219
  main()
@@ -24,33 +24,33 @@ from pysmt.shortcuts import FreshSymbol, Times, Equals, Div, Real, Int, Pow
24
24
  from pysmt.shortcuts import Solver, Symbol, And, Not, is_sat
25
25
  from pysmt.typing import REAL, INT
26
26
  from pysmt.exceptions import (ConvertExpressionError,
27
- NonLinearError, InternalSolverError,
27
+ NonLinearError,
28
28
  SolverReturnedUnknownResultError)
29
- from pysmt.logics import QF_NRA
29
+ from pysmt.logics import QF_NRA, QF_NIA
30
30
  from pysmt.constants import Fraction
31
31
 
32
32
 
33
33
  class TestNonLinear(TestCase):
34
34
 
35
- @skipIfSolverNotAvailable("z3")
36
35
  def test_times(self):
37
36
  x = FreshSymbol(REAL)
38
37
  f = Equals(Times(x, x), x)
39
- with Solver(name="z3") as s:
40
- self.assertTrue(s.is_sat(f))
38
+ for sname in self.env.factory.all_solvers(logic=QF_NRA):
39
+ with Solver(name=sname, logic=QF_NRA) as s:
40
+ self.assertTrue(s.is_sat(f), sname)
41
41
 
42
- @skipIfSolverNotAvailable("z3")
43
42
  def test_div(self):
44
43
  x = FreshSymbol(REAL)
45
44
  f = Equals(Div(x, x), x)
46
- with Solver(name="z3") as s:
47
- self.assertTrue(s.is_sat(f))
45
+ for sname in self.env.factory.all_solvers(logic=QF_NRA):
46
+ with Solver(name=sname, logic=QF_NRA) as s:
47
+ self.assertTrue(s.is_sat(f), sname)
48
48
 
49
49
  @skipIfSolverNotAvailable("z3")
50
50
  def test_irrational(self):
51
51
  x = FreshSymbol(REAL)
52
52
  f = Equals(Times(x, x), Real(2))
53
- with Solver(name="z3") as s:
53
+ with Solver(name="z3", logic=QF_NRA) as s:
54
54
  self.assertTrue(s.is_sat(f))
55
55
  model = s.get_model()
56
56
  xval = model[x]
@@ -73,38 +73,34 @@ class TestNonLinear(TestCase):
73
73
 
74
74
  def test_unknownresult(self):
75
75
  x = FreshSymbol(REAL)
76
- f = Equals(Times(x, x), Real(2))
76
+ # 4.0 rather than 2.0: the point here is which solvers reject
77
+ # nonlinear arithmetic, not who can represent an algebraic number.
78
+ f = Equals(Times(x, x), Real(4))
77
79
  for sname in self.env.factory.all_solvers():
78
- with Solver(name=sname) as s:
79
- if sname in ["bdd", "picosat", "btor"]:
80
+ if sname in ["bdd", "picosat", "btor"]:
81
+ with Solver(name=sname) as s:
80
82
  with self.assertRaises(ConvertExpressionError):
81
83
  s.is_sat(f)
82
- elif sname in ["yices", "cvc4", "msat", "optimsat"]:
84
+ elif sname in ["yices", "cvc4"]:
85
+ with Solver(name=sname) as s:
83
86
  with self.assertRaises(NonLinearError):
84
87
  s.is_sat(f)
85
- elif sname in ["cvc5"]:
86
- with self.assertRaises(InternalSolverError):
87
- s.is_sat(f)
88
- else:
89
- res = s.is_sat(f)
90
- self.assertTrue(res, sname)
88
+ else:
89
+ with Solver(name=sname, logic=QF_NRA) as s:
90
+ self.assertTrue(s.is_sat(f), sname)
91
91
  self.assertIn(QF_NRA, s.LOGICS, sname)
92
92
 
93
- @skipIfSolverNotAvailable("z3")
94
93
  def test_integer(self):
95
94
  x = FreshSymbol(INT)
96
- f = Equals(Times(x, x), Int(2))
97
- with Solver(name="z3") as s:
98
- self.assertFalse(s.is_sat(f))
99
-
100
- # f = Equals(Times(Int(4), Pow(x, Int(-1))), Int(2))
101
- # self.assertTrue(is_sat(f, solver_name="z3"))
102
-
103
- # f = Equals(Div(Int(4), x), Int(2))
104
- # self.assertTrue(is_sat(f, solver_name="z3"))
105
-
106
- f = Equals(Times(x, x), Int(16))
107
- self.assertTrue(is_sat(f, solver_name="z3"))
95
+ f1 = Equals(Times(x, x), Int(2))
96
+ f2 = Equals(Times(x, x), Int(16))
97
+ for sname in self.env.factory.all_solvers(logic=QF_NIA):
98
+ for f, expected in ((f1, False), (f2, True)):
99
+ with Solver(name=sname, logic=QF_NIA) as s:
100
+ try:
101
+ self.assertEqual(expected, s.is_sat(f), (sname, f))
102
+ except SolverReturnedUnknownResultError:
103
+ pass
108
104
 
109
105
  @skipIfSolverNotAvailable("z3")
110
106
  def test_div_pow(self):
@@ -29,11 +29,13 @@ from pysmt.test import (TestCase, skipIfSolverNotAvailable, skipIfNoSolverForLog
29
29
  skipIfNoQEForLogic)
30
30
  from pysmt.test import main
31
31
  from pysmt.exceptions import (ConvertExpressionError, PysmtValueError,
32
- PysmtTypeError, InternalSolverError)
32
+ PysmtTypeError, InternalSolverError,
33
+ PysmtEmptySymbolNameError, UndefinedSymbolError)
33
34
  from pysmt.test.examples import get_example_formulae
34
35
  from pysmt.environment import Environment
35
36
  from pysmt.rewritings import cnf_as_set
36
37
  from pysmt.smtlib.parser import SmtLibParser
38
+ from pysmt.parsing import parse as hr_parse
37
39
  from pysmt.smtlib.commands import DECLARE_FUN
38
40
  from pysmt.smtlib.script import SmtLibCommand
39
41
  from pysmt.logics import get_closer_smtlib_logic
@@ -270,6 +272,64 @@ class TestRegressions(TestCase):
270
272
  def test_empty_string_symbol(self):
271
273
  with self.assertRaises(PysmtValueError):
272
274
  Symbol("")
275
+ # SMT-LIB allows `||` as a symbol name (see #587), but pySMT
276
+ # requires the user to opt-in explicitly.
277
+ self.env.allow_empty_var_names = True
278
+ self.assertNotEqual(Symbol(""), Symbol(" "))
279
+
280
+ def test_empty_string_symbol_error_message(self):
281
+ # Parsing a symbol with the empty name must point at the option
282
+ # to enable, not fail with an unrelated message.
283
+ smtlib = """(set-logic QF_BV)
284
+ (declare-fun || () (_ BitVec 4))
285
+ (assert (= || || ))
286
+ (check-sat)"""
287
+ with self.assertRaises(PysmtEmptySymbolNameError) as ctx:
288
+ SmtLibParser().get_script(StringIO(smtlib))
289
+ self.assertIn("allow_empty_var_names", str(ctx.exception))
290
+ with self.assertRaises(PysmtEmptySymbolNameError):
291
+ hr_parse("'' & x")
292
+ # Once enabled, the empty name is just an undeclared symbol
293
+ self.env.allow_empty_var_names = True
294
+ with self.assertRaises(UndefinedSymbolError):
295
+ hr_parse("'' & x")
296
+ Symbol("")
297
+ self.assertEqual(hr_parse("''"), Symbol(""))
298
+
299
+ @skipIfNoSolverForLogic(logics.QF_BV)
300
+ def test_empty_string_symbol_in_solvers(self):
301
+ self.env.allow_empty_var_names = True
302
+ empty = Symbol("", BVType(8))
303
+ other = Symbol("other", BVType(8))
304
+ f = Not(Equals(empty, other))
305
+ for sname in self.env.factory.all_solvers(logic=logics.QF_BV):
306
+ with Solver(name=sname, logic=logics.QF_BV) as s:
307
+ s.add_assertion(f)
308
+ self.assertTrue(s.solve(), sname)
309
+ self.assertTrue(s.get_value(empty).is_bv_constant(), sname)
310
+ # Round-trip, but only for converters that can back-convert
311
+ # a regular symbol in the first place.
312
+ try:
313
+ can_back = s.converter.back(s.converter.convert(other)) == other
314
+ except Exception:
315
+ can_back = False
316
+ if can_back:
317
+ self.assertEqual(s.converter.back(s.converter.convert(empty)),
318
+ empty, sname)
319
+
320
+ @skipIfNoSolverForLogic(logics.QF_BV)
321
+ def test_empty_string_symbol_smtlib(self):
322
+ # The benchmark reported in #587 declares `||` and `| |`.
323
+ self.env.allow_empty_var_names = True
324
+ txt = """(set-logic QF_BV)
325
+ (declare-fun || () (_ BitVec 4))
326
+ (declare-fun | | () (_ BitVec 4))
327
+ (assert (not (= || | |)))
328
+ (check-sat)"""
329
+ script = SmtLibParser().get_script(StringIO(txt))
330
+ self.assertEqual({s.symbol_name() for s in script.get_declared_symbols()},
331
+ {"", " "})
332
+ self.assertSat(script.get_last_formula())
273
333
 
274
334
  def test_smtlib_info_quoting(self):
275
335
  cmd = SmtLibCommand(smtcmd.SET_INFO, [":source", "This\nis\nmultiline!"])
@@ -198,7 +198,6 @@ class TestBasic(TestCase):
198
198
  def test_examples_msat(self):
199
199
  for (f, validity, satisfiability, logic) in get_example_formulae():
200
200
  if not logic.quantifier_free: continue
201
- if not logic.theory.linear: continue
202
201
  if logic.theory.strings: continue
203
202
 
204
203
  v = is_valid(f, solver_name='msat', logic=logic)
File without changes
File without changes
File without changes