PySMT 0.9.7.dev433__tar.gz → 0.9.7.dev436__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.dev433/PySMT.egg-info → pysmt-0.9.7.dev436}/PKG-INFO +1 -1
  2. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436/PySMT.egg-info}/PKG-INFO +1 -1
  3. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/__init__.py +1 -1
  4. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/parser/parser.py +53 -15
  5. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_examples.py +128 -1
  6. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/LICENSE +0 -0
  7. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/MANIFEST.in +0 -0
  8. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/NOTICE +0 -0
  9. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/PySMT.egg-info/SOURCES.txt +0 -0
  10. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/PySMT.egg-info/dependency_links.txt +0 -0
  11. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/PySMT.egg-info/entry_points.txt +0 -0
  12. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/PySMT.egg-info/top_level.txt +0 -0
  13. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/README.rst +0 -0
  14. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/docs/CHANGES.rst +0 -0
  15. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/docs/api_ref.rst +0 -0
  16. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/docs/development.rst +0 -0
  17. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/docs/getting_started.rst +0 -0
  18. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/docs/index.rst +0 -0
  19. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/docs/tutorials/boolean_logic.rst +0 -0
  20. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/docs/tutorials.rst +0 -0
  21. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/__main__.py +0 -0
  22. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/__init__.py +0 -0
  23. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/check_version.py +0 -0
  24. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/install.py +0 -0
  25. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/__init__.py +0 -0
  26. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/base.py +0 -0
  27. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/bdd.py +0 -0
  28. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/btor.py +0 -0
  29. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/cvcfive.py +0 -0
  30. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/cvcfour.py +0 -0
  31. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/msat.py +0 -0
  32. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/optimsat.py +0 -0
  33. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/pico.py +0 -0
  34. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/yices.py +0 -0
  35. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/installers/z3.py +0 -0
  36. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/cmd/shell.py +0 -0
  37. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/configuration.py +0 -0
  38. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/constants.py +0 -0
  39. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/decorators.py +0 -0
  40. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/environment.py +0 -0
  41. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/exceptions.py +0 -0
  42. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/factory.py +0 -0
  43. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/fnode.py +0 -0
  44. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/formula.py +0 -0
  45. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/logics.py +0 -0
  46. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/operators.py +0 -0
  47. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/optimization/__init__.py +0 -0
  48. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/optimization/goal.py +0 -0
  49. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/optimization/msat.py +0 -0
  50. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/optimization/optimizer.py +0 -0
  51. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/optimization/optimsat.py +0 -0
  52. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/optimization/yices.py +0 -0
  53. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/optimization/z3.py +0 -0
  54. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/oracles.py +0 -0
  55. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/parsing.py +0 -0
  56. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/printers.py +0 -0
  57. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/rewritings.py +0 -0
  58. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/shortcuts.py +0 -0
  59. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/simplifier.py +0 -0
  60. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/__init__.py +0 -0
  61. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/annotations.py +0 -0
  62. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/commands.py +0 -0
  63. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/parser/__init__.py +0 -0
  64. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/printers.py +0 -0
  65. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/script.py +0 -0
  66. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/solver.py +0 -0
  67. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/smtlib/utils.py +0 -0
  68. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/__init__.py +0 -0
  69. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/bdd.py +0 -0
  70. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/btor.py +0 -0
  71. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/cvcfive.py +0 -0
  72. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/cvcfour.py +0 -0
  73. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/dynmsat.py +0 -0
  74. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/eager.py +0 -0
  75. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/interpolation.py +0 -0
  76. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/msat.py +0 -0
  77. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/options.py +0 -0
  78. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/pico.py +0 -0
  79. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/portfolio.py +0 -0
  80. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/qelim.py +0 -0
  81. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/smtlib.py +0 -0
  82. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/solver.py +0 -0
  83. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/yices.py +0 -0
  84. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/solvers/z3.py +0 -0
  85. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/substituter.py +0 -0
  86. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/__init__.py +0 -0
  87. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/configs/config1.ini +0 -0
  88. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/configs/config_bad.ini +0 -0
  89. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/examples.py +0 -0
  90. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/omt_examples.py +0 -0
  91. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/optimization_utils.py +0 -0
  92. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/__init__.py +0 -0
  93. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/parser_utils.py +0 -0
  94. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_annotations.py +0 -0
  95. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_fuzzed.py +0 -0
  96. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_generic_wrapper.py +0 -0
  97. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_griggio.py +0 -0
  98. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_model_validation.py +0 -0
  99. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_omt_lib_solver.py +0 -0
  100. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_extensibility.py +0 -0
  101. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_lra.py +0 -0
  102. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_omt.py +0 -0
  103. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_arrays.py +0 -0
  104. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_lia.py +0 -0
  105. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_lira.py +0 -0
  106. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_lra.py +0 -0
  107. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_nia.py +0 -0
  108. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_nra.py +0 -0
  109. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_uf.py +0 -0
  110. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_qf_ufbv.py +0 -0
  111. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_parser_type_error.py +0 -0
  112. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/smtlib/test_smtlibscript.py +0 -0
  113. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_array.py +0 -0
  114. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_back.py +0 -0
  115. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_bdd.py +0 -0
  116. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_bv.py +0 -0
  117. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_bv_simplification.py +0 -0
  118. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_cnf.py +0 -0
  119. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_configuration.py +0 -0
  120. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_constants.py +0 -0
  121. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_cvc_quantifiers.py +0 -0
  122. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_dwf.py +0 -0
  123. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_eager_model.py +0 -0
  124. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_env.py +0 -0
  125. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_euf.py +0 -0
  126. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_formula.py +0 -0
  127. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_hr_parsing.py +0 -0
  128. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_imports.py +0 -0
  129. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_int.py +0 -0
  130. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_interpolation.py +0 -0
  131. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_lira.py +0 -0
  132. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_logics.py +0 -0
  133. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_models.py +0 -0
  134. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_native_qe.py +0 -0
  135. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_nia.py +0 -0
  136. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_nlira.py +0 -0
  137. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_optimization.py +0 -0
  138. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_optimizing.py +0 -0
  139. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_oracles.py +0 -0
  140. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_portfolio.py +0 -0
  141. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_printing.py +0 -0
  142. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_qe.py +0 -0
  143. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_regressions.py +0 -0
  144. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_rewritings.py +0 -0
  145. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_shannon_expansion.py +0 -0
  146. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_simplify.py +0 -0
  147. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_size.py +0 -0
  148. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_solving.py +0 -0
  149. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_sorts.py +0 -0
  150. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_string.py +0 -0
  151. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_typechecker.py +0 -0
  152. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_unsat_cores.py +0 -0
  153. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_walker_ext.py +0 -0
  154. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/test/test_walkers.py +0 -0
  155. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/type_checker.py +0 -0
  156. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/typing.py +0 -0
  157. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/utils.py +0 -0
  158. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/walkers/__init__.py +0 -0
  159. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/walkers/dag.py +0 -0
  160. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/walkers/generic.py +0 -0
  161. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/walkers/identitydag.py +0 -0
  162. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/pysmt/walkers/tree.py +0 -0
  163. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/setup.cfg +0 -0
  164. {pysmt-0.9.7.dev433 → pysmt-0.9.7.dev436}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PySMT
3
- Version: 0.9.7.dev433
3
+ Version: 0.9.7.dev436
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.dev433
3
+ Version: 0.9.7.dev436
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
@@ -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", 433)
22
+ VERSION: Union[Tuple[int, int, int], Tuple[int, int, int, str, int]] = (0, 9, 7, "dev", 436)
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
@@ -304,6 +304,40 @@ class Tokenizer(object):
304
304
  # EOC Tokenizer
305
305
 
306
306
 
307
+ #
308
+ # Helpers to expand the SMT-LIB n-ary applications of operators that pySMT
309
+ # only exposes as binary ones. The SMT-LIB standard attaches one of the
310
+ # attributes :left-assoc, :right-assoc, :chainable or :pairwise to every such
311
+ # operator; the three functions below implement the first three (:pairwise is
312
+ # already covered by mgr.AllDifferent).
313
+ #
314
+ # In all cases a single argument is accepted and behaves as the identity (or
315
+ # as `true` for the chainable operators, where the conjunction is empty).
316
+ # The standard requires at least two arguments, but pySMT has always been
317
+ # lenient about this for `and`, `or`, `+` and `*`, and we keep it uniform.
318
+ #
319
+
320
+ def _left_assoc(operator: Callable) -> Callable:
321
+ """(op a b c) is expanded to (op (op a b) c)"""
322
+ def res(*args):
323
+ return functools.reduce(operator, args)
324
+ return res
325
+
326
+
327
+ def _right_assoc(operator: Callable) -> Callable:
328
+ """(op a b c) is expanded to (op a (op b c))"""
329
+ def res(*args):
330
+ return functools.reduce(lambda acc, x: operator(x, acc), reversed(args))
331
+ return res
332
+
333
+
334
+ def _chainable(mgr: FormulaManager, operator: Callable) -> Callable:
335
+ """(op a b c) is expanded to (and (op a b) (op b c))"""
336
+ def res(*args):
337
+ return mgr.And([operator(l, r) for l, r in zip(args, args[1:])])
338
+ return res
339
+
340
+
307
341
  class SmtLibParser(object):
308
342
  """Parse an SmtLib file and builds an SmtLibScript object.
309
343
  The main function is get_script (and its wrapper
@@ -373,22 +407,27 @@ class SmtLibParser(object):
373
407
  "!": self._enter_annotation,
374
408
  "exists": self._enter_quantifier,
375
409
  "forall": self._enter_quantifier,
410
+ # '+' and '*' are :left-assoc, but pySMT builds them n-ary
411
+ # natively; the other n-ary operators are folded, see the
412
+ # _left_assoc/_right_assoc/_chainable helpers above.
376
413
  '+': self._operator_adapter(self.Plus),
377
414
  '-': self._operator_adapter(self._minus_or_uminus),
378
415
  '*': self._operator_adapter(self.Times),
379
- '/': self._operator_adapter(self._division),
416
+ '/': self._operator_adapter(_left_assoc(self._division)),
417
+ 'div': self._operator_adapter(_left_assoc(mgr.Div)),
380
418
  'pow': self._operator_adapter(mgr.Pow),
381
- '>': self._operator_adapter(self.GT),
382
- '<': self._operator_adapter(self.LT),
383
- '>=': self._operator_adapter(self.GE),
384
- '<=': self._operator_adapter(self.LE),
385
- '=': self._operator_adapter(self._equals_or_iff),
419
+ '>': self._operator_adapter(_chainable(mgr, self.GT)),
420
+ '<': self._operator_adapter(_chainable(mgr, self.LT)),
421
+ '>=': self._operator_adapter(_chainable(mgr, self.GE)),
422
+ '<=': self._operator_adapter(_chainable(mgr, self.LE)),
423
+ '=': self._operator_adapter(_chainable(mgr, self._equals_or_iff)),
386
424
  'not': self._operator_adapter(mgr.Not),
387
425
  'and': self._operator_adapter(mgr.And),
388
426
  'or': self._operator_adapter(mgr.Or),
389
- 'xor': self._operator_adapter(mgr.Xor),
390
- '=>': self._operator_adapter(mgr.Implies),
391
- '<->': self._operator_adapter(mgr.Iff),
427
+ 'xor': self._operator_adapter(_left_assoc(mgr.Xor)),
428
+ '=>': self._operator_adapter(_right_assoc(mgr.Implies)),
429
+ # '<->' is a pySMT extension: treated as :left-assoc, like 'xor'
430
+ '<->': self._operator_adapter(_left_assoc(mgr.Iff)),
392
431
  'ite': self._operator_adapter(self.Ite),
393
432
  'distinct': self._operator_adapter(self.AllDifferent),
394
433
  'to_real': self._operator_adapter(mgr.ToReal),
@@ -407,12 +446,12 @@ class SmtLibParser(object):
407
446
  'bvlshr': self._operator_adapter(mgr.BVLShr),
408
447
  'bvsub': self._operator_adapter(mgr.BVSub),
409
448
  'bvult': self._operator_adapter(mgr.BVULT),
410
- 'bvxor': self._operator_adapter(mgr.BVXor),
449
+ 'bvxor': self._operator_adapter(_left_assoc(mgr.BVXor)),
411
450
  '_': self._smtlib_underscore,
412
451
  # Extended Functions
413
452
  'bvnand': self._operator_adapter(mgr.BVNand),
414
453
  'bvnor': self._operator_adapter(mgr.BVNor),
415
- 'bvxnor': self._operator_adapter(mgr.BVXnor),
454
+ 'bvxnor': self._operator_adapter(_left_assoc(mgr.BVXnor)),
416
455
  'bvcomp': self._operator_adapter(mgr.BVComp),
417
456
  'bvsdiv': self._operator_adapter(mgr.BVSDiv),
418
457
  'bvsrem': self._operator_adapter(mgr.BVSRem),
@@ -492,7 +531,7 @@ class SmtLibParser(object):
492
531
  self.cache.update({'false': mgr.FALSE(), 'true': mgr.TRUE()})
493
532
 
494
533
  def _minus_or_uminus(self, *args) -> FNode:
495
- """Utility function that handles both unary and binary minus"""
534
+ """Utility function that handles unary and n-ary minus"""
496
535
  mgr = self.env.formula_manager
497
536
  if len(args) == 1:
498
537
  lty = self.get_type(args[0])
@@ -506,9 +545,8 @@ class SmtLibParser(object):
506
545
  return mgr.Real(-1 * args[0].constant_value())
507
546
  mult = mgr.Real(-1)
508
547
  return mgr.Times(mult, args[0])
509
- else:
510
- assert len(args) == 2
511
- return self.Minus(args[0], args[1])
548
+ # '-' is :left-assoc: (- a b c) is (- (- a b) c)
549
+ return functools.reduce(self.Minus, args)
512
550
 
513
551
  def _enter_smtlib_as(self, stack: List[List[Union[Callable, FNode, Any]]], tokens: Tokenizer, key: str):
514
552
  """Utility function that handles 'as' that is a special function in SMTLIB"""
@@ -25,9 +25,12 @@ from pysmt.test import TestCase, skipIfNoSolverForLogic, main
25
25
  from pysmt.test.examples import get_example_formulae
26
26
  from pysmt.smtlib.parser import SmtLibParser, Tokenizer
27
27
  from pysmt.smtlib.script import smtlibscript_from_formula
28
- from pysmt.shortcuts import Iff
28
+ from pysmt.shortcuts import Iff, Symbol, And, Implies, Xor, LT, GE, Equals, \
29
+ Plus, Minus, Times, Div, AllDifferent, BVXor, BVConcat
29
30
  from pysmt.shortcuts import read_smtlib, write_smtlib, get_env
30
31
  from pysmt.exceptions import PysmtSyntaxError
32
+ from pysmt.smtlib.commands import ASSERT
33
+ from pysmt.typing import INT, REAL, BV8
31
34
 
32
35
 
33
36
  class TestSMTParseExamples(TestCase):
@@ -216,6 +219,130 @@ class TestSMTParseExamples(TestCase):
216
219
  for cmd in s:
217
220
  self.assertEqual(cmd.args[2], get_type(cmd.args[3]))
218
221
 
222
+ def test_nary_operators(self):
223
+ """All the SMT-LIB n-ary operators are expanded as the standard
224
+ prescribes: see https://github.com/pysmt/pysmt/issues/638"""
225
+ INT_DECLS = "(declare-fun a () Int)(declare-fun b () Int)" \
226
+ "(declare-fun c () Int)(declare-fun d () Int)"
227
+ BOOL_DECLS = "(declare-fun p () Bool)(declare-fun q () Bool)" \
228
+ "(declare-fun r () Bool)"
229
+ BV_DECLS = "(declare-fun x () (_ BitVec 8))(declare-fun y () (_ BitVec 8))" \
230
+ "(declare-fun z () (_ BitVec 8))"
231
+
232
+ # (declarations, n-ary application, expected expansion)
233
+ cases = [
234
+ # :right-assoc
235
+ (BOOL_DECLS, "(=> p q r)", "(=> p (=> q r))"),
236
+ (BOOL_DECLS, "(=> p q r p)", "(=> p (=> q (=> r p)))"),
237
+ # :left-assoc
238
+ (BOOL_DECLS, "(xor p q r)", "(xor (xor p q) r)"),
239
+ (BOOL_DECLS, "(<-> p q r)", "(<-> (<-> p q) r)"),
240
+ (INT_DECLS, "(- a b c)", "(- (- a b) c)"),
241
+ (INT_DECLS, "(- a b c d)", "(- (- (- a b) c) d)"),
242
+ (INT_DECLS, "(/ a b c)", "(/ (/ a b) c)"),
243
+ (INT_DECLS, "(div a b c)", "(div (div a b) c)"),
244
+ (BV_DECLS, "(bvxor x y z)", "(bvxor (bvxor x y) z)"),
245
+ (BV_DECLS, "(bvxnor x y z)", "(bvxnor (bvxnor x y) z)"),
246
+ # :chainable
247
+ (INT_DECLS, "(> a b c)", "(and (> a b) (> b c))"),
248
+ (INT_DECLS, "(>= a b c d)", "(and (>= a b) (>= b c) (>= c d))"),
249
+ (INT_DECLS, "(< a b c)", "(and (< a b) (< b c))"),
250
+ (INT_DECLS, "(<= a b c)", "(and (<= a b) (<= b c))"),
251
+ (INT_DECLS, "(= a b c)", "(and (= a b) (= b c))"),
252
+ (BOOL_DECLS, "(= p q r)", "(and (<-> p q) (<-> q r))"),
253
+ # unary applications: identity for the associative operators,
254
+ # vacuously true for the chainable ones
255
+ (BOOL_DECLS, "(=> p)", "p"),
256
+ (BOOL_DECLS, "(xor p)", "p"),
257
+ (INT_DECLS, "(/ a)", "a"),
258
+ (INT_DECLS, "(= a)", "true"),
259
+ (INT_DECLS, "(< a)", "true"),
260
+ ]
261
+ for decls, nary, expected in cases:
262
+ self.assertEqual(self._parse_assertion(decls, nary),
263
+ self._parse_assertion(decls, expected),
264
+ "wrong expansion of %s" % nary)
265
+
266
+ def test_nary_operators_end_to_end(self):
267
+ """Parse a whole SMT-LIB2 script using the n-ary operators and check
268
+ the resulting formulae against the ones built with the pySMT API"""
269
+ script = """
270
+ ; no set-logic: no pySMT logic covers BV + non-linear Int/Real at once
271
+ (declare-fun a () Int)
272
+ (declare-fun b () Int)
273
+ (declare-fun c () Int)
274
+ (declare-fun r () Real)
275
+ (declare-fun s () Real)
276
+ (declare-fun t () Real)
277
+ (declare-fun p () Bool)
278
+ (declare-fun q () Bool)
279
+ (declare-fun u () Bool)
280
+ (declare-fun x () (_ BitVec 8))
281
+ (declare-fun y () (_ BitVec 8))
282
+ (declare-fun z () (_ BitVec 8))
283
+ (assert (< a b c))
284
+ (assert (>= a b c))
285
+ (assert (= a b c))
286
+ (assert (= p q u))
287
+ (assert (= (- a b c) (+ a b c)))
288
+ (assert (= (div a b c) (* a b c)))
289
+ (assert (= (/ r s t) r))
290
+ (assert (=> p q u))
291
+ (assert (xor p q u))
292
+ (assert (distinct a b c))
293
+ (assert (= (bvxor x y z) x))
294
+ (assert (= (concat x y z) (concat z y x)))
295
+ (check-sat)
296
+ """
297
+ a, b, c = (Symbol(name, INT) for name in "abc")
298
+ r, s, t = (Symbol(name, REAL) for name in "rst")
299
+ p, q, u = (Symbol(name) for name in "pqu")
300
+ x, y, z = (Symbol(name, BV8) for name in "xyz")
301
+
302
+ expected = [
303
+ # :chainable
304
+ And(LT(a, b), LT(b, c)),
305
+ And(GE(a, b), GE(b, c)),
306
+ And(Equals(a, b), Equals(b, c)),
307
+ And(Iff(p, q), Iff(q, u)),
308
+ # :left-assoc ('+' and '*' stay flat n-ary)
309
+ Equals(Minus(Minus(a, b), c), Plus(a, b, c)),
310
+ Equals(Div(Div(a, b), c), Times(a, b, c)),
311
+ Equals(Div(Div(r, s), t), r),
312
+ # :right-assoc
313
+ Implies(p, Implies(q, u)),
314
+ # :left-assoc
315
+ Xor(Xor(p, q), u),
316
+ # :pairwise
317
+ AllDifferent(a, b, c),
318
+ # bit-vectors
319
+ Equals(BVXor(BVXor(x, y), z), x),
320
+ Equals(BVConcat(BVConcat(x, y), z), BVConcat(BVConcat(z, y), x)),
321
+ ]
322
+
323
+ parser = SmtLibParser()
324
+ parsed = [cmd.args[0] for cmd in
325
+ parser.get_script(StringIO(script)).filter_by_command_name(ASSERT)]
326
+
327
+ self.assertEqual(len(parsed), len(expected))
328
+ for got, exp in zip(parsed, expected):
329
+ self.assertEqual(got, exp)
330
+ # ...and the conjunction of all of them is what the script means
331
+ self.assertEqual(
332
+ SmtLibParser().get_script(StringIO(script)).get_last_formula(),
333
+ And(expected))
334
+
335
+ def test_nary_div_is_integer_division(self):
336
+ """'div' is the Ints division, so it must not be promoted to Real"""
337
+ f = self._parse_assertion("(declare-fun a () Int)", "(div a 2 3)")
338
+ self.assertEqual(get_env().stc.get_type(f), INT)
339
+
340
+ @staticmethod
341
+ def _parse_assertion(declarations, expression):
342
+ script = "%s (assert %s)" % (declarations, expression)
343
+ parser = SmtLibParser()
344
+ return parser.get_script(StringIO(script)).get_last_formula()
345
+
219
346
  def test_typing_define_fun(self):
220
347
  script = """
221
348
  (define-fun x () Int 8.2)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes