PySMT 0.9.7.dev477__tar.gz → 0.9.7.dev485__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.
- {pysmt-0.9.7.dev477/PySMT.egg-info → pysmt-0.9.7.dev485}/PKG-INFO +1 -1
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485/PySMT.egg-info}/PKG-INFO +1 -1
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/PySMT.egg-info/SOURCES.txt +1 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/docs/CHANGES.rst +7 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/docs/getting_started.rst +86 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/docs/tutorials.rst +11 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/__init__.py +1 -1
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/install.py +1 -1
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/optimization/z3.py +25 -29
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/msat.py +18 -4
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/z3.py +11 -3
- pysmt-0.9.7.dev485/pysmt/test/test_doc_snippets.py +75 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_unsat_cores.py +20 -1
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/LICENSE +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/MANIFEST.in +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/NOTICE +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/PySMT.egg-info/dependency_links.txt +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/PySMT.egg-info/entry_points.txt +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/PySMT.egg-info/top_level.txt +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/README.rst +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/docs/api_ref.rst +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/docs/development.rst +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/docs/index.rst +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/docs/tutorials/boolean_logic.rst +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/__main__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/check_version.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/base.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/bdd.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/btor.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/cvcfive.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/cvcfour.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/msat.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/optimsat.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/pico.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/yices.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/installers/z3.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/cmd/shell.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/configuration.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/constants.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/decorators.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/environment.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/exceptions.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/factory.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/fnode.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/formula.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/logics.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/operators.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/optimization/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/optimization/goal.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/optimization/msat.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/optimization/optimizer.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/optimization/optimsat.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/optimization/yices.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/oracles.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/parsing.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/printers.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/rewritings.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/shortcuts.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/simplifier.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/annotations.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/commands.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/parser/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/parser/parser.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/printers.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/script.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/solver.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/smtlib/utils.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/bdd.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/btor.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/cvcfive.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/cvcfour.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/dynmsat.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/eager.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/interpolation.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/options.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/pico.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/portfolio.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/qelim.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/smtlib.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/solver.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/solvers/yices.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/substituter.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/configs/config1.ini +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/configs/config_bad.ini +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/examples.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/omt_examples.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/optimization_utils.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/parser_utils.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_annotations.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_fuzzed.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_generic_wrapper.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_griggio.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_model_validation.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_omt_lib_solver.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_examples.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_extensibility.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_lra.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_omt.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_arrays.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_lia.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_lira.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_lra.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_nia.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_nra.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_uf.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_qf_ufbv.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_parser_type_error.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/smtlib/test_smtlibscript.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_array.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_back.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_bdd.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_bv.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_bv_simplification.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_cnf.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_configuration.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_constants.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_cvc_quantifiers.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_dwf.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_eager_model.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_env.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_euf.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_formula.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_hr_parsing.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_imports.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_int.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_interpolation.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_lira.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_logics.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_models.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_native_qe.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_nia.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_nlira.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_optimization.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_optimizing.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_oracles.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_portfolio.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_printing.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_qe.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_regressions.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_rewritings.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_shannon_expansion.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_simplify.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_size.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_solving.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_sorts.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_string.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_typechecker.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_walker_ext.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/test/test_walkers.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/type_checker.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/typing.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/utils.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/walkers/__init__.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/walkers/dag.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/walkers/generic.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/walkers/identitydag.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/pysmt/walkers/tree.py +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/setup.cfg +0 -0
- {pysmt-0.9.7.dev477 → pysmt-0.9.7.dev485}/setup.py +0 -0
|
@@ -4,6 +4,13 @@ Change Log
|
|
|
4
4
|
(unreleased)
|
|
5
5
|
------------
|
|
6
6
|
|
|
7
|
+
* Fixed: MathSAT segfaulted in ``get_unsat_core()`` after solving under
|
|
8
|
+
a non-literal assumption, because reading the core popped the
|
|
9
|
+
assumption level and left MathSAT's core with dangling terms. Z3 did
|
|
10
|
+
not crash but reported an internal symbol in place of the assumption,
|
|
11
|
+
and raised on a second core request. Both now report the assumption
|
|
12
|
+
itself.
|
|
13
|
+
|
|
7
14
|
* Fixed: The assumptions passed to ``solve()`` were missing from the
|
|
8
15
|
unsat core. ``get_unsat_core()`` now reports them alongside the
|
|
9
16
|
assertions, in both the "all" and the "named" unsat cores mode
|
|
@@ -222,6 +222,88 @@ Here is the complete example for reference using the logic QF_LIA:
|
|
|
222
222
|
.. literalinclude:: code_snippets/hello_world_qf_lia.py
|
|
223
223
|
|
|
224
224
|
|
|
225
|
+
.. _gs-unsat-core:
|
|
226
|
+
|
|
227
|
+
Unsat Cores
|
|
228
|
+
-----------
|
|
229
|
+
|
|
230
|
+
When a set of formulae is unsatisfiable, not all of them are usually
|
|
231
|
+
responsible for the unsatisfiability. An *unsat core* of the asserted
|
|
232
|
+
formulae is a subset of them whose conjunction is still
|
|
233
|
+
unsatisfiable. UNSAT cores are a handy debugging tool because they
|
|
234
|
+
narrow down which assertions of your problem are in conflict. The
|
|
235
|
+
core returned by the solver is not guaranteed to be minimal: removing
|
|
236
|
+
a formula from it may leave it unsatisfiable.
|
|
237
|
+
|
|
238
|
+
pySMT exposes two ways to obtain an unsat core, both provided by the
|
|
239
|
+
:py:class:`~pysmt.solvers.solver.UnsatCoreSolver` class:
|
|
240
|
+
|
|
241
|
+
* ``get_unsat_core()`` returns the core as a set of formulae (this is
|
|
242
|
+
also what the :py:func:`~pysmt.shortcuts.get_unsat_core` shortcut
|
|
243
|
+
uses);
|
|
244
|
+
* ``get_named_unsat_core()`` returns the core as a dictionary mapping
|
|
245
|
+
assertion names to formulae.
|
|
246
|
+
|
|
247
|
+
Named cores are useful when the assertions come from different
|
|
248
|
+
sources (e.g. different rules of a constraint, different parts of the
|
|
249
|
+
input), because the names allow you to map the core back to the
|
|
250
|
+
structure of your original problem.
|
|
251
|
+
|
|
252
|
+
Core extraction must be enabled when the solver is created, through
|
|
253
|
+
the ``unsat_cores_mode`` option of
|
|
254
|
+
:py:func:`~pysmt.shortcuts.UnsatCoreSolver`:
|
|
255
|
+
|
|
256
|
+
* ``"all"`` (the default of the shortcut): every assertion is a
|
|
257
|
+
candidate for the core. Use it when you only need the formulae.
|
|
258
|
+
* ``"named"``: only the assertions added with
|
|
259
|
+
``add_assertion(f, named="...")`` are candidates, and
|
|
260
|
+
``get_named_unsat_core()`` reports them under the given names. Use it
|
|
261
|
+
when you need to map the core back to your problem, or when only
|
|
262
|
+
some of the assertions should be tracked.
|
|
263
|
+
|
|
264
|
+
.. note::
|
|
265
|
+
|
|
266
|
+
Not every solver supports unsat-core extraction. You can list the
|
|
267
|
+
installed solvers that do by looking at the result of
|
|
268
|
+
``Factory.all_unsat_core_solvers()`` (see
|
|
269
|
+
:py:meth:`pysmt.factory.Factory.all_unsat_core_solvers`); as of this
|
|
270
|
+
writing the supported solvers are z3, MathSAT/OptiMathSAT and
|
|
271
|
+
Boolector, while cvc5 and Yices do not.
|
|
272
|
+
``UnsatCoreSolver(...)`` raises
|
|
273
|
+
:py:class:`~pysmt.exceptions.NoSolverAvailableError` if no installed
|
|
274
|
+
solver supports unsat cores for the requested logic.
|
|
275
|
+
|
|
276
|
+
Minimal example
|
|
277
|
+
"""""""""""""""
|
|
278
|
+
|
|
279
|
+
.. literalinclude:: code_snippets/unsat_core.py
|
|
280
|
+
|
|
281
|
+
Named cores
|
|
282
|
+
"""""""""""
|
|
283
|
+
|
|
284
|
+
.. literalinclude:: code_snippets/unsat_core_named.py
|
|
285
|
+
|
|
286
|
+
.. note::
|
|
287
|
+
|
|
288
|
+
Named cores are meaningful only when the solver is created with
|
|
289
|
+
``unsat_cores_mode="named"``. In the other modes, some solvers
|
|
290
|
+
(e.g. z3) keep the names that were given to the assertions while
|
|
291
|
+
others (e.g. MathSAT, Boolector) replace them with generated,
|
|
292
|
+
meaningless names; only ``unsat_cores_mode="named"`` is therefore
|
|
293
|
+
portable if you rely on the names.
|
|
294
|
+
|
|
295
|
+
Cores under assumptions
|
|
296
|
+
"""""""""""""""""""""""
|
|
297
|
+
|
|
298
|
+
Assumptions are extra constraints that apply only to a particular call
|
|
299
|
+
of ``solve()``, not to the solver's theory. The following snippet
|
|
300
|
+
shows that ``get_unsat_core()`` reports the assumptions that belong to
|
|
301
|
+
the core (in both unsat cores modes), while ``get_named_unsat_core()``
|
|
302
|
+
never does, since assumptions carry no name.
|
|
303
|
+
|
|
304
|
+
.. literalinclude:: code_snippets/unsat_core_assumptions.py
|
|
305
|
+
|
|
306
|
+
|
|
225
307
|
What's Next?
|
|
226
308
|
------------
|
|
227
309
|
|
|
@@ -232,3 +314,7 @@ there with a simple to use interface.
|
|
|
232
314
|
|
|
233
315
|
To understand more about other functionalities of pySMT, you can take
|
|
234
316
|
a look at the `examples/ folder <https://github.com/pysmt/pysmt/blob/master/examples/README.rst>`_ .
|
|
317
|
+
|
|
318
|
+
If a problem you are trying to solve is unsatisfiable, you can
|
|
319
|
+
use unsat-core extraction to debug it: see the :ref:`gs-unsat-core`
|
|
320
|
+
section above for an introduction.
|
|
@@ -62,6 +62,17 @@ Demonstrates how to perform SMT-LIB parsing, dumping and extension
|
|
|
62
62
|
------------------------------------------------------------------
|
|
63
63
|
.. literalinclude:: ../examples/smtlib.py
|
|
64
64
|
|
|
65
|
+
Unsat Cores
|
|
66
|
+
-----------
|
|
67
|
+
|
|
68
|
+
pySMT can extract an *unsat core* of an unsatisfiable set of
|
|
69
|
+
formulae: a subset of the asserted formulae whose conjunction is
|
|
70
|
+
still unsatisfiable. This is a handy debugging tool to find out
|
|
71
|
+
which assertions of your problem are in conflict. See the
|
|
72
|
+
:ref:`gs-unsat-core` section of the getting started guide for a
|
|
73
|
+
full walkthrough, and note that the example below (``examples/einstein.py``)
|
|
74
|
+
already uses UNSAT cores.
|
|
75
|
+
|
|
65
76
|
Shows the use of UNSAT Core as debugging tools
|
|
66
77
|
----------------------------------------------
|
|
67
78
|
.. literalinclude:: ../examples/einstein.py
|
|
@@ -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",
|
|
22
|
+
VERSION: Union[Tuple[int, int, int], Tuple[int, int, int, str, int]] = (0, 9, 7, "dev", 485)
|
|
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
|
|
@@ -36,7 +36,7 @@ INSTALLERS = [
|
|
|
36
36
|
Installer(CVC5Installer, "1.3.3", {}),
|
|
37
37
|
Installer(CVC4Installer, "1.7-prerelease",
|
|
38
38
|
{"git_version" : "391ab9df6c3fd9a3771864900c1718534c1e4666"}),
|
|
39
|
-
Installer(Z3Installer, "
|
|
39
|
+
Installer(Z3Installer, "5.1.0", {}),
|
|
40
40
|
Installer(YicesInstaller, "2.6.4", {"yices_api_version": "1.1.5"}),
|
|
41
41
|
Installer(BtorInstaller, "3.2.3", {}),
|
|
42
42
|
Installer(PicoSATInstaller, "965",
|
|
@@ -18,8 +18,6 @@
|
|
|
18
18
|
|
|
19
19
|
from __future__ import absolute_import
|
|
20
20
|
|
|
21
|
-
from warnings import warn
|
|
22
|
-
|
|
23
21
|
from pysmt.decorators import clear_pending_pop
|
|
24
22
|
from pysmt.solvers.solver import Model
|
|
25
23
|
from pysmt.solvers.z3 import Z3Solver, Z3Model
|
|
@@ -127,33 +125,31 @@ class Z3NativeOptimizer(Optimizer, Z3Solver):
|
|
|
127
125
|
|
|
128
126
|
@clear_pending_pop
|
|
129
127
|
def boxed_optimize(self, goals: Sequence[Goal]) -> Optional[Dict[Goal, Tuple[Model, FNode]]]:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
models[g] = r
|
|
156
|
-
return models
|
|
128
|
+
self.push()
|
|
129
|
+
try:
|
|
130
|
+
self.z3.set(priority='box')
|
|
131
|
+
handles = [self._assert_z3_goal(goal, goal_id)
|
|
132
|
+
for goal_id, goal in enumerate(goals)]
|
|
133
|
+
# In box mode, each call to check() yields the optimal model
|
|
134
|
+
# of the next objective, in the order they were asserted
|
|
135
|
+
models: Dict[Goal, Tuple[Model, FNode]] = {}
|
|
136
|
+
for goal, h in zip(goals, handles):
|
|
137
|
+
if self.z3.check() != z3.sat:
|
|
138
|
+
return None
|
|
139
|
+
try:
|
|
140
|
+
model = Z3Model(self.environment, self.z3.model())
|
|
141
|
+
if goal.is_maxsmt_goal():
|
|
142
|
+
models[goal] = (model, self._compute_max_smt_cost(model, goal))
|
|
143
|
+
else:
|
|
144
|
+
self.converter.back(self.z3.lower(h))
|
|
145
|
+
models[goal] = (model, model.get_value(goal.term()))
|
|
146
|
+
except PysmtInfinityError:
|
|
147
|
+
raise PysmtUnboundedOptimizationError("The optimal value is unbounded")
|
|
148
|
+
except PysmtInfinitesimalError:
|
|
149
|
+
raise PysmtInfinitesimalError("The optimal value is infinitesimal")
|
|
150
|
+
return models
|
|
151
|
+
finally:
|
|
152
|
+
self.pop()
|
|
157
153
|
|
|
158
154
|
@clear_pending_pop
|
|
159
155
|
def lexicographic_optimize(self, goals: Sequence[Goal]) -> Optional[Tuple[Model, List[FNode]]]:
|
|
@@ -232,6 +232,7 @@ class MathSAT5Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolv
|
|
|
232
232
|
self.intType = self._msat_lib.msat_get_integer_type(self.msat_env())
|
|
233
233
|
self.boolType = self._msat_lib.msat_get_bool_type(self.msat_env())
|
|
234
234
|
self.mgr = environment.formula_manager
|
|
235
|
+
self._assumption_keys: Dict[FNode, FNode] = {}
|
|
235
236
|
|
|
236
237
|
@clear_pending_pop
|
|
237
238
|
def _reset_assertions(self):
|
|
@@ -269,7 +270,9 @@ class MathSAT5Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolv
|
|
|
269
270
|
|
|
270
271
|
def _named_assertions_map(self):
|
|
271
272
|
if self.options.unsat_cores_mode == "named":
|
|
272
|
-
|
|
273
|
+
# not self.assertions: popping the assumptions level would
|
|
274
|
+
# invalidate the unsat core in MathSAT (dangling terms, segfault)
|
|
275
|
+
return dict((t[0], (t[1],t[2])) for t in self._assertion_stack)
|
|
273
276
|
return None
|
|
274
277
|
|
|
275
278
|
@clear_pending_pop
|
|
@@ -277,6 +280,8 @@ class MathSAT5Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolv
|
|
|
277
280
|
res = None
|
|
278
281
|
bool_ass = []
|
|
279
282
|
other_ass = []
|
|
283
|
+
# maps the fresh literal standing for each non-literal assumption to it
|
|
284
|
+
self._assumption_keys = {}
|
|
280
285
|
for x in assumptions if assumptions is not None else []:
|
|
281
286
|
if x.is_literal():
|
|
282
287
|
bool_ass.append(self.converter.convert(x))
|
|
@@ -284,8 +289,14 @@ class MathSAT5Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolv
|
|
|
284
289
|
other_ass.append(x)
|
|
285
290
|
if len(other_ass) > 0:
|
|
286
291
|
self.push()
|
|
287
|
-
|
|
288
|
-
|
|
292
|
+
for x in other_ass:
|
|
293
|
+
key = self.mgr.FreshSymbol(template="_assumption_%d")
|
|
294
|
+
self._assumption_keys[key] = x
|
|
295
|
+
term = self.converter.convert(self.mgr.Implies(key, x))
|
|
296
|
+
if self._msat_lib.msat_assert_formula(self.msat_env(), term) != 0:
|
|
297
|
+
raise InternalSolverError(
|
|
298
|
+
self._msat_lib.msat_last_error_message(self.msat_env()))
|
|
299
|
+
bool_ass.append(self.converter.convert(key))
|
|
289
300
|
|
|
290
301
|
n_ass = self._named_assertions()
|
|
291
302
|
if n_ass is not None and len(n_ass) > 0:
|
|
@@ -319,6 +330,9 @@ class MathSAT5Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolv
|
|
|
319
330
|
raise InternalSolverError(
|
|
320
331
|
self._msat_lib.msat_last_error_message(self.msat_env()))
|
|
321
332
|
res = set(self.converter.back(t) for t in terms)
|
|
333
|
+
# drop the Implies(key, x) encoding of non-literal assumptions
|
|
334
|
+
res = set(f for f in res
|
|
335
|
+
if not f.get_free_variables() & self._assumption_keys.keys())
|
|
322
336
|
return res | self._unsat_assumptions()
|
|
323
337
|
else:
|
|
324
338
|
return set(self.get_named_unsat_core().values()) | \
|
|
@@ -334,7 +348,7 @@ class MathSAT5Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolv
|
|
|
334
348
|
if n_ass_map is not None:
|
|
335
349
|
# in named mode the named assertions are passed as assumptions too
|
|
336
350
|
res -= set(n_ass_map)
|
|
337
|
-
return res
|
|
351
|
+
return set(self._assumption_keys.get(f, f) for f in res)
|
|
338
352
|
|
|
339
353
|
def get_named_unsat_core(self):
|
|
340
354
|
"""After a call to solve() yielding UNSAT, returns the unsat core as a
|
|
@@ -177,6 +177,7 @@ class Z3Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolver):
|
|
|
177
177
|
self.mgr = environment.formula_manager
|
|
178
178
|
|
|
179
179
|
self._name_cnt = 0
|
|
180
|
+
self._assumption_keys: Dict[FNode, FNode] = {}
|
|
180
181
|
return
|
|
181
182
|
|
|
182
183
|
@clear_pending_pop
|
|
@@ -218,9 +219,15 @@ class Z3Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolver):
|
|
|
218
219
|
else:
|
|
219
220
|
other_ass.append(x)
|
|
220
221
|
|
|
222
|
+
# maps the fresh literal standing for each non-literal assumption to it
|
|
223
|
+
self._assumption_keys = {}
|
|
221
224
|
if len(other_ass) > 0:
|
|
222
225
|
self.push()
|
|
223
|
-
|
|
226
|
+
for x in other_ass:
|
|
227
|
+
key = self.mgr.FreshSymbol(template="_assumption_%d")
|
|
228
|
+
self._assumption_keys[key] = x
|
|
229
|
+
self.z3.add(self.converter.convert(self.mgr.Implies(key, x)))
|
|
230
|
+
bool_ass.append(self.converter.convert(key))
|
|
224
231
|
self.pending_pop = True
|
|
225
232
|
res = self.z3.check(*bool_ass)
|
|
226
233
|
else:
|
|
@@ -240,7 +247,8 @@ class Z3Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolver):
|
|
|
240
247
|
|
|
241
248
|
def _named_assertions_map(self):
|
|
242
249
|
if self.options.unsat_cores_mode is not None:
|
|
243
|
-
|
|
250
|
+
# not self.assertions: that would pop the assumptions level
|
|
251
|
+
return dict((t[0], (t[1],t[2])) for t in self._assertion_stack)
|
|
244
252
|
return None
|
|
245
253
|
|
|
246
254
|
def get_named_unsat_core(self):
|
|
@@ -279,7 +287,7 @@ class Z3Solver(IncrementalTrackingSolver, UnsatCoreSolver, SmtLibBasicSolver):
|
|
|
279
287
|
cnt += 1
|
|
280
288
|
res[name] = formula
|
|
281
289
|
else:
|
|
282
|
-
core_assumptions.add(key)
|
|
290
|
+
core_assumptions.add(self._assumption_keys.get(key, key))
|
|
283
291
|
return res, core_assumptions
|
|
284
292
|
|
|
285
293
|
@clear_pending_pop
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#
|
|
2
|
+
# This file is part of pySMT.
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2014 Andrea Micheli and Marco Gario
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
import os
|
|
19
|
+
import runpy
|
|
20
|
+
import unittest
|
|
21
|
+
|
|
22
|
+
from pysmt.test import (TestCase, skipIfSolverNotAvailable,
|
|
23
|
+
skipIfNoSolverForLogic,
|
|
24
|
+
skipIfNoUnsatCoreSolverForLogic, main)
|
|
25
|
+
from pysmt.logics import QF_LIA
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
SNIPPETS_DIR = os.path.join(os.path.dirname(__file__),
|
|
29
|
+
"..", "..", "docs", "code_snippets")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# The docs are not shipped with the package, so skip when run from an install.
|
|
33
|
+
@unittest.skipIf(not os.path.isdir(SNIPPETS_DIR), "docs/ not available")
|
|
34
|
+
class TestDocSnippets(TestCase):
|
|
35
|
+
|
|
36
|
+
def setUp(self):
|
|
37
|
+
super().setUp()
|
|
38
|
+
# Match the default environment a reader gets from pysmt.shortcuts.
|
|
39
|
+
self.env.enable_infix_notation = True
|
|
40
|
+
|
|
41
|
+
def run_snippets(self, *names):
|
|
42
|
+
for name in names:
|
|
43
|
+
with self.subTest(snippet=name):
|
|
44
|
+
runpy.run_path(os.path.join(SNIPPETS_DIR, name + ".py"),
|
|
45
|
+
run_name="__main__")
|
|
46
|
+
|
|
47
|
+
def test_no_solver(self):
|
|
48
|
+
self.run_snippets("hello_world_opening", "hello_world_infix")
|
|
49
|
+
|
|
50
|
+
@skipIfNoSolverForLogic(QF_LIA)
|
|
51
|
+
def test_qf_lia(self):
|
|
52
|
+
self.run_snippets("hello_world_is_sat", "hello_world_get_model",
|
|
53
|
+
"hello_world_qf_lia")
|
|
54
|
+
|
|
55
|
+
@skipIfSolverNotAvailable("z3")
|
|
56
|
+
def test_z3(self):
|
|
57
|
+
self.run_snippets("hello_world")
|
|
58
|
+
|
|
59
|
+
@skipIfNoUnsatCoreSolverForLogic(QF_LIA)
|
|
60
|
+
def test_unsat_cores(self):
|
|
61
|
+
self.run_snippets("unsat_core", "unsat_core_named",
|
|
62
|
+
"unsat_core_assumptions")
|
|
63
|
+
|
|
64
|
+
def test_all_snippets_are_tested(self):
|
|
65
|
+
tested = {"hello_world_opening", "hello_world_infix",
|
|
66
|
+
"hello_world_is_sat", "hello_world_get_model",
|
|
67
|
+
"hello_world_qf_lia", "hello_world", "unsat_core",
|
|
68
|
+
"unsat_core_named", "unsat_core_assumptions"}
|
|
69
|
+
found = {f[:-3] for f in os.listdir(SNIPPETS_DIR) if f.endswith(".py")}
|
|
70
|
+
self.assertEqual(found, tested,
|
|
71
|
+
"Add new docs/code_snippets files to this test")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if __name__ == '__main__':
|
|
75
|
+
main()
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
from pysmt.test import (TestCase, skipIfSolverNotAvailable,
|
|
19
19
|
skipIfNoUnsatCoreSolverForLogic, main)
|
|
20
20
|
from pysmt.shortcuts import (get_unsat_core, And, Or, Not, Symbol, UnsatCoreSolver,
|
|
21
|
-
Solver, is_unsat, Int, GT, get_env)
|
|
21
|
+
Solver, is_unsat, Int, GT, GE, LE, get_env)
|
|
22
22
|
from pysmt.typing import INT
|
|
23
23
|
from pysmt.logics import QF_BOOL, QF_BV, QF_LIA
|
|
24
24
|
from pysmt.exceptions import (SolverStatusError, SolverReturnedUnknownResultError,
|
|
@@ -214,6 +214,25 @@ class TestUnsatCores(TestCase):
|
|
|
214
214
|
{"n1": Or(x, y)}, name)
|
|
215
215
|
|
|
216
216
|
|
|
217
|
+
@skipIfNoUnsatCoreSolverForLogic(QF_LIA)
|
|
218
|
+
def test_non_literal_assumptions_in_unsat_core(self):
|
|
219
|
+
a = Symbol("a", INT)
|
|
220
|
+
pos, neg = GE(a, Int(1)), LE(a, Int(0))
|
|
221
|
+
for name in get_env().factory.all_unsat_core_solvers(logic=QF_LIA):
|
|
222
|
+
for mode in ["all", "named"]:
|
|
223
|
+
with UnsatCoreSolver(name=name, logic=QF_LIA,
|
|
224
|
+
unsat_cores_mode=mode) as s:
|
|
225
|
+
s.add_assertion(pos, named="pos")
|
|
226
|
+
self.assertFalse(s.solve([neg]))
|
|
227
|
+
# twice: reading the core must not pop the assumptions level
|
|
228
|
+
for _ in range(2):
|
|
229
|
+
self.assertEqual(s.get_unsat_core(), {pos, neg},
|
|
230
|
+
(name, mode))
|
|
231
|
+
if mode == "named":
|
|
232
|
+
self.assertEqual(s.get_named_unsat_core(),
|
|
233
|
+
{"pos": pos}, (name, mode))
|
|
234
|
+
|
|
235
|
+
|
|
217
236
|
@skipIfNoUnsatCoreSolverForLogic(QF_BOOL)
|
|
218
237
|
def test_assumptions_as_iterator(self):
|
|
219
238
|
x, y = Symbol("x"), Symbol("y")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|