GithubHelp home page GithubHelp logo

stanford-centaur / smt-switch Goto Github PK

View Code? Open in Web Editor NEW
102.0 8.0 40.0 1.79 MB

A generic C++ API for SMT solving. It provides abstract classes which can be implemented by different SMT solvers.

License: Other

C++ 85.01% Makefile 0.08% Shell 1.71% C 0.61% CMake 2.69% Python 4.95% Yacc 0.89% Lex 0.41% SMT 0.48% Cython 3.17% sed 0.01%

smt-switch's Introduction

Smt-Switch

A generic C++ API for SMT solving. It provides abstract classes which can be implemented by different SMT solvers.

Quick Start

$ git clone [email protected]:stanford-centaur/smt-switch.git
$ cd smt-switch 
$ ./contrib/setup-<solver>.sh
$ ./configure.sh --<solver>
$ cd build 
$ make 
$ make test

More details are in the Solvers section of this README.

For an example of how to link and use smt-switch, please see the examples directory.

Architecture Overview

There are three abstract classes:

  • AbsSmtSolver
  • AbsSort
  • AbsTerm

Each of them has a using statement that names a smart pointer of that type, e.g. using Term = shared_ptr<AbsTerm>;. The key thing to remember when using this library is that all solver-specific objects are pointers to the abstract base class. SmtSolver, Sort, and Term are all smart pointers. Note: there are many convenience functions which operate on these pointers, so they may not look like pointers. Additionally, the library also includes using statements for commonly used data structures, for example, TermVec is a vector of shared pointers to AbsTerms.

The function names are based on SMT-LIB. The general rule is that functions/methods in this library can be obtained syntactically from SMT-LIB commands by replacing dashes with underscores. There are a few exceptions, for example assert is assert_formula in this library to avoid clashing with the assert macro. Operator names are also based on SMT-LIB operators, and can be obtained syntactically from an SMT-LIB operator by capitalizing the first letter and any letter after an underscore. The only exception is bv which is always capitalized to BV and does not count towards the capitalization of the first letter. Some examples include:

  • And
  • BVAnd
  • Zero_Extend
  • BVAshr

Please see this extended abstract for more documentation or the tests directory for some example usage.

Creating a Smt-Switch Solver

To create a Smt-Switch solver through the API, first include the relevant factory header and then use the static create method. It takes a single boolean parameter which configures term logging. If passed false, the created SmtSolver relies on the underlying solver for term traversal and querying a term for the Sort or Op. If passed true, it instantiates a LoggingSolver wrapper which keeps track of the Op, Sort and children of terms as they are created. A LoggingSolver wraps all the terms and sorts created through the API. Thus, a LoggingSolver always returns a LoggingTerm. However, this is invisible to the user and all the objects can be used in the expected way. The logging feature is useful for solvers that alias sorts (for example don't distinguish between booleans and bitvectors of size one) or perform on-the-fly rewriting. The LoggingSolver wrapper ensures that the built term has the expected Op, Sort and children. In other words, the created term is exactly what was built through the API -- it cannot be rewritten or alias the sort. This drastically simplifies transferring between solvers and can be more intuitive than on-the-fly rewriting. Note: the rewriting still happens in the underlying solver, but this is hidden at the Smt-Switch level. Some solvers, such as Yices2, rely on the LoggingSolver for term traversal. E.g. creating a Yices2 SmtSolver without term logging would not allow term traversal.

Here is an example that creates a solver interface to cvc5:

#include "smt-switch/cvc5_factory.h"

int main()
{
  // create a Cvc5Solver without logging
  smt::SmtSolver s = smt::Cvc5SolverFactory::create(false);
  return 0;
}

Dependencies

Smt-Switch depends on the following libraries. Dependencies needed only for certain backends and/or optional features are marked ["optional" : reason].

  • CMake >= 3.1
  • C compiler
  • C++ compiler supporting C++11
  • git
  • curl [optional : setup scripts in contrib]
  • Solver libraries
    • Bitwuzla (has setup script in contrib)
    • cvc5 (has setup script in contrib)
    • MathSAT (must be obtained independently; user responsible for meeting license conditions)
    • Yices2 (must be obtained independently; user responsible for meeting license conditions)
  • pthread [optional: Bitwuzla]
  • gmp [optional: cvc5, MathSAT, Yices2]
  • autoconf [optional: Yices2 setup script]
  • Java [optional: cvc5 ANTLR]
  • Flex >= 2.6.4 [optional: SMT-LIB parser]
  • Bison >= 3.7 [optional: SMT-LIB parser]
  • Python [optional: Python bindings]
  • Cython >= 0.29 [optional: Python bindings]
  • scikit-build [optional: Python bindings]

Operating Systems

Our cmake build system is currently only tested on Ubuntu Bionic and Mac OSX with XCode 12 but should work for other sufficiently modern (e.g. has C++11 support and CMake >= 3.1) Unix-based operating systems. Please file a GitHub issue if you have any problems!

Solvers

To setup and install different solvers, first run the ./contrib/setup-<solver>.sh script which builds position-independent static libraries in the <solver> directory. Then you can configure your cmake build with the configure.sh script. Enable a solver with ./configure.sh --<solver>. By default only libsmt-switch.so is built without any solvers.

Some of the backend solvers have non-BSD compatible licenses. There are no provided setup scripts for these solvers. However, there are instructions for setting up these solvers in ./contrib. Should you choose to link against these solver libraries, you assume all responsibility for meeting the license requirements of those libraries.

Once you've configured the build system, simply enter the build directory (./build by default) and run make. Each solver you add produces a libsmt-switch-<solver>.so shared object file. Running make install installs these libraries and the public header files into the configured prefix (/usr/local by default). Note that the header files are put in a directory, e.g. /usr/local/include/smt-switch.

Currently Supported Solvers

BSD compatible

  • Bitwuzla
  • Bitwuzla
  • cvc5
  • Z3

Non-BSD compatible

  • MathSAT
  • Yices2

Custom Solver Location

If you'd like to try your own version of a solver, you can use the configure.sh script to point to your custom location with --<solver>-home. You will need to build static libraries (.a) and have them be accessible in the standard location for that solver. For example, you would point to a custom location of cvc5 like so: ./configure.sh --prefix=<your desired install location> --cvc5-home ./custom-cvc5

where ./custom-cvc5/build/src/libcvc5.a and ./custom-cvc5/build/src/parser/libcvc5parser.a already exist. build is the default build directory for cvc5, and thus that's where cmake is configured to look.

Building Tests

You can run all tests for the currently built solvers with make test from the build directory. To run a single test, run the binary ./tests/<test name>. After you have a full installation, you can build the tests yourself by updating the includes to include the smt-switch directory. For example: #include "cvc5_factory.h" -> #include "smt-switch/cvc5_factory.h".

Debug

The tests currently use C-style assertions which are compiled out in Release mode (the default). To build tests with assertions, please add the --debug flag when using ./configure.sh.

Python bindings

It is highly recommended to use a Python virtual environment or Conda environment when building Python bindings. Note: only Python3 is supported.

First, install the required Python modules:

python3 -m pip install scikit-build Cython pytest

If you're building the python bindings in a setting where you don't care too much about runtime speed (e.g. for CI), you can add the option --install-option="--no-cython-compile" to the end of the Cython installation command to install it faster.

Then, to compile python bindings, use the --python flag of configure.sh. After configuring with python bindings, run make in the build directory as usual. The Python extension module will be build/python/smt_switch/smt_switch*.so. To install this in your python environment, you can run python3 -m pip install -e ./python from the build directory.

After installing the bindings, you can test them from the top-level of the repository with:

pytest ./tests/

PySMT front end

Optionally, smt-switch can be used with a pySMT front-end . To install the pySMT front-end install smt-switch with the pysmt extra (python3 -m install -e ./python[pysmt]). Note, some shells, notable zsh, require brackets be escaped or the path to be quoted, i.e., ./python\[pysmt\] or "./python[pysmt]".

A pySMT solver for each switch back-end can be instantiated directly or using the helper function Solver:

from smt_switch import pysmt_frontend

# direct instantiation must pass an enviroment and a logic
solver = pysmt_frontend.SwitchCvc5(ENV, LOGIC)

# with the helper function will try to use a general logic
solver = pysmt_frontend.Solver("cvc5")

# with the helper function will use the specified logic
solver = pysmt_frontend.Solver("cvc5", LOGIC)

# Note a solver can be used as a context manager:
with pysmt_frontend.Solver("cvc5") as solver: ...

Please refer to the pySMT docs for further information.

Testing python bindings

Python bindings are tested with pytest. This can be installed using pip or automatically by installing the python bindings with the test extra (python3 -m install -e ./python[test]). To run all tests, simply run pytest ./tests from the top-level directory. Note, running pytest alone might unnecessarily run tests in dependencies located in subdirectories. To run a particular test, use the -k test_name[parameter1-...-parameter_n] format, e.g. pytest -k test_bvadd[create_btor_solver]. The tests for the pySMT front-end will only be run if it is installed. Note, multiple extras may be installed by passing them as a comma separated list:python3 -m install -e ./python[test,pysmt].

Current Limitations and Gotchas

While we try to guarantee that all solver backends are fully compliant with the abstract interface, and exhibit the exact same behavior given the same API calls, we are not able to do this in every case (yet). Below are some known, current limitations along with recommended usage.

  • Undefined behavior. Sharing terms between different solver instances will result in undefined behavior. This is because we use a static cast to recover the backend solver implementation from an abstract object. To move terms between solver instances, you can use a TermTranslator which will rebuild the term in another solver. A given TermTranslator object can only translate terms from one solver to one new one. If some symbols have already been created in the new solver, you can populate the TermTranslator's cache so that it knows which symbols correspond to each other
  • Bitwuzla's substitute implementation does not work for formulas containing uninterpreted functions. To get around this, you can use a LoggingSolver. See below.
  • Bitwuzla does not support reset_assertions yet. You can however simulate this by setting the option "base-context-1" to "true". Under the hood, this will do all solving starting at context 1 instead of 0. This will allow you to call reset_assertions just like for any other solver.
  • The Z3 backend has not implemented term iteration (getting children) yet, but that should be added soon.
  • Datatypes are currently only supported in cvc5

Recommended usage

Logging solvers

A LoggingSolver is a wrapper around another SmtSolver that keeps track of Term DAGs at the smt-switch level. This guarantees that if you create a term and query it for its sort, op, and children, it will give you back the exact same objects you built it with. Without the LoggingSolver wrapper, this is not guaranteed for all solvers. This is because some solvers perform on-the-fly rewriting and/or alias sorts (e.g. treat BOOL and BV of size one equivalently). Below, we give some recommendations for when to use a LoggingSolver for different backends. To use a LoggingSolver, pass true to the create function when instantiating a solver.

  • Bitwuzla
    • Use a LoggingSolver when you want to avoid issues with sort aliasing between booleans and bit-vectors of size one and/or if you'd like to ensure that a term's children are exactly what were used to create it. Bitwuzla performs very smart on-the-fly rewriting. Additionally, use a LoggingSolver if you will need to use the substitute method on formulas that contain uninterpreted functions.
  • cvc5
    • cvc5 does not alias sorts or perform on-the-fly rewriting. Thus, there should never be any reason to use a LoggingSolver.
  • MathSAT
    • Use a LoggingSolver only if you want to guarantee that a term's Op and children are exactly what you used to create it. Without a LoggingSolver, MathSAT will perform very light rewriting.
  • Yices2
    • Use a LoggingSolver if you need term iteration
    • Yices2 has a different term representation under the hood which cannot easily be converted back to SMT-LIB. Thus, term traversal is currently only supported through a LoggingSolver.

Contributions

We welcome external contributions, please see CONTRIBUTING.md for more details. If you are interested in becoming a long-term contributor to smt-switch, please contact one of the primary authors in AUTHORS

smt-switch's People

Contributors

afnaanhashmi avatar ahmed-irfan avatar akgperson avatar amaleewilson avatar aytey avatar barrettcw avatar bartvhelvert avatar bhaskargupta22 avatar cdonovick avatar cterrill26 avatar cyanokobalamyne avatar farmerzhang1 avatar ffrohn avatar georgerennie avatar jack-melchert avatar kris-brown avatar kuree avatar lstuntz avatar makaimann avatar moorvan avatar ntsis avatar samanthaarcher0 avatar yoni206 avatar zhanghongce avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smt-switch's Issues

Use the new version z3

In the current version of z3 in use, a problem is encountered with "Overflow encountered when expanding vector" during solving, which can be seen: Z3Prover/z3#864

It seems fixed in new version of z3. However, when I changed to use the new version of z3 in smt-switch, I meet:

Undefined symbols for architecture arm64:
  "mk_implies(probe*, probe*)", referenced from:
      sexpr2probe(cmd_context&, sexpr*) in libsmt-switch-z3.a(tactic_cmds.o)
  "fatal_error(int)", referenced from:
      datalog::check_table::empty() const in libsmt-switch-z3.a(dl_check_table.o)
  "mk_size_probe()", referenced from:
      install_tactics(tactic_manager&) in libsmt-switch-z3.a(install_tactic.o)
  "mk_const_probe(double)", referenced from:
      sexpr2probe(cmd_context&, sexpr*) in libsmt-switch-z3.a(tactic_cmds.o)
      mk_auflia_tactic(ast_manager&, params_ref const&) in libsmt-switch-z3.a(quant_tactics.o)
      mk_qfbv_tactic(ast_manager&, params_ref const&) in libsmt-switch-z3.a(qfbv_tactic.o)
      mk_qfidl_tactic(ast_manager&, params_ref const&) in libsmt-switch-z3.a(qfidl_tactic.o)
      mk_qflia_tactic(ast_manager&, params_ref const&) in libsmt-switch-z3.a(qflia_tactic.o)
 .....

It seems that api does not match.

Look into slow substitute

Running substitute on a simple term, e.g. just updating a symbol (x -> y) can be much slower than caching. Although I would expect a cache look up to be faster, the massive difference in speed is surprising. See the review on stanford-centaur/pono#116. It might be out of our control if all the time is spent in the underlying solver, but it's worth looking into.

smt-switch is very tightly bound to a specific, old version of CVC5.

Here are a couple specific issues I encountered when trying to use a newer cvc5 (1.0.5+)


1:

return ((k == ::cvc5::CONST_BOOLEAN) || (k == ::cvc5::CONST_BITVECTOR)

is not a complete list of enum values e.g.

This causes is_value() to return sometimes erroneously return false, and cause crashes down the line.


2:
Several header paths (e.g. cvc5_sort.h, cvc5_kind.h, and api/cpp/..) have changed in newer versions of cvc5.


Ideally, multiple versions of each solver could be supported within one smt-switch build. Though they may not be able to be used simultaneously at runtime.

Avoid global state in Flex scanner

I noticed while working on #248, that the scanner uses global state. I was getting strange behavior when running the parser twice. The fix in that PR was to flush the buffer with YY_FLUSH_BUFFER in scan_begin. Ideally, we would not have global state at all.

Compilation problem 2

In contrib/setup-cvc4.sh, cvc4 is configured using

CXXFLAGS=-fPIC CFLAGS=-fPIC ./configure.sh --static

but cvc4 does not build in mode --static on MacOS X.
This seems to work:

CXXFLAGS=-fPIC CFLAGS=-fPIC ./configure.sh --static --no-static-binary

Enable sort construction in CVC4

Retrieving sort parameters appears to be broken in CVC4 (getUninterpretedSortParamSorts returns an empty vector). This needs to be fixed first, and then we can merge: #98

Use attributes for available solvers

Instead of creating a bunch of different vectors and solver maps, use attributes for the testing infrastructure to decide when to run tests on different solvers.

Boolector Backend Substitution Function

image
Currently, the subsitution function in boolector solver backend doesn't support the term-->term substitution as the Pysmt does. I would like to ask that if I want to use the term-to-term substitution, is there any potential method? And when will the boolector solver support this kind of subsititution? Thank you so much!

SMT-Lib parser is strict

SMT-Lib when reading LIRA / LRA formulas, the parser requires that reals have a "."
Many smt-lib formulas do not comply with this spec, would it be possible to enhance the parser so it can interpret integers as reals depending on context?

Support getters in parser

Add support for get-value/get-model/get-unsat-core to the SmtLibReader and flex/bison parse infrastructure.

Compilation with CVC5 fails on GCC >= 11

Compilation fails with the following error:

/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp: In member function ‘cvc5::Op smt::Cvc5Solver::make_cvc5_op(smt::Op) const’:
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:986:24: error: ‘numeric_limits’ is not a member of ‘std’
  986 |     if (op.idx0 > std::numeric_limits<uint32_t>::max())
      |                        ^~~~~~~~~~~~~~
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:986:47: error: expected primary-expression before ‘>’ token
  986 |     if (op.idx0 > std::numeric_limits<uint32_t>::max())
      |                                               ^
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:986:50: error: ‘::max’ has not been declared; did you mean ‘std::max’?
  986 |     if (op.idx0 > std::numeric_limits<uint32_t>::max())
      |                                                  ^~~
      |                                                  std::max
In file included from /usr/include/c++/12.2.0/functional:64,
                 from /mnt/data/git/smt-switch/../cvc5/src/api/cpp/cvc5.h:21,
                 from /mnt/data/git/smt-switch/cvc5/include/cvc5_solver.h:26,
                 from /mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:17:
/usr/include/c++/12.2.0/bits/stl_algo.h:5756:5: note: ‘std::max’ declared here
 5756 |     max(initializer_list<_Tp> __l, _Compare __comp)
      |     ^~~
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:996:24: error: ‘numeric_limits’ is not a member of ‘std’
  996 |     if (op.idx0 > std::numeric_limits<uint32_t>::max())
      |                        ^~~~~~~~~~~~~~
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:996:47: error: expected primary-expression before ‘>’ token
  996 |     if (op.idx0 > std::numeric_limits<uint32_t>::max())
      |                                               ^
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:996:50: error: ‘::max’ has not been declared; did you mean ‘std::max’?
  996 |     if (op.idx0 > std::numeric_limits<uint32_t>::max())
      |                                                  ^~~
      |                                                  std::max
/usr/include/c++/12.2.0/bits/stl_algo.h:5756:5: note: ‘std::max’ declared here
 5756 |     max(initializer_list<_Tp> __l, _Compare __comp)
      |     ^~~
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:1001:24: error: ‘numeric_limits’ is not a member of ‘std’
 1001 |     if (op.idx1 > std::numeric_limits<uint32_t>::max())
      |                        ^~~~~~~~~~~~~~
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:1001:47: error: expected primary-expression before ‘>’ token
 1001 |     if (op.idx1 > std::numeric_limits<uint32_t>::max())
      |                                               ^
/mnt/data/git/smt-switch/cvc5/src/cvc5_solver.cpp:1001:50: error: ‘::max’ has not been declared; did you mean ‘std::max’?
 1001 |     if (op.idx1 > std::numeric_limits<uint32_t>::max())
      |                                                  ^~~
      |                                                  std::max
/usr/include/c++/12.2.0/bits/stl_algo.h:5756:5: note: ‘std::max’ declared here
 5756 |     max(initializer_list<_Tp> __l, _Compare __comp)
      |     ^~~

This is due to https://www.gnu.org/software/gcc/gcc-11/porting_to.html#header-dep-changes. The limits library needs to be included everywhere it is used.

Installation issue: unwanted skbuild printout

When i import skbuild with python3 on my system I get the following printouts:

>>> import skbuild
Generating grammar tables from /usr/lib/python3.8/lib2to3/Grammar.txt
Generating grammar tables from /usr/lib/python3.8/lib2to3/PatternGrammar.txt

This causes issues in python/CMakeLists.txt since line 48 is not expecting this extra printout.

Locally, I have fixed this by replacing the import skbuild at line 39 of the script with import sys; temp = sys.stdout; sys.stdout = open(os.devnull,\"w\"); import skbuild; sys.stdout = temp to silence the output.

TermTranslator unhelpful rewrite.

When fed the CVC5 term:
(let ((_let_1 (f y))) (let ((_let_2 (f x))) (and (<= 0 _let_2) (<= 0 _let_1) (<= (+ _let_2 _let_1) 1) (not (p 0)) (p _let_1))))

The TermTranslator (to any solver), rewrites it as:
(let ((_let_1 (f y))) (let ((_let_2 (f x))) (and (= (ite (<= 0 _let_2) (_ bv1 1) (_ bv0 1)) (_ bv1 1)) (= (ite (<= 0 _let_1) (_ bv1 1) (_ bv0 1)) (_ bv1 1)) (= (ite (<= (+ _let_2 _let_1) 1) (_ bv1 1) (_ bv0 1)) (_ bv1 1)) (= (ite (not (p 0)) (_ bv1 1) (_ bv0 1)) (_ bv1 1)) (= (ite (p _let_1) (_ bv1 1) (_ bv0 1)) (_ bv1 1)))))

We would like the option to disable such a rewrite.

It appears this may be caused by two related bugs:

  1. Because the AND has more than two children, execution goes into the if-statement linked below. We think we would like an option to manually disable this check and/or make smt-switch allow for ANDs to support more than two children. The translated term should have as similar a structure to the original term as possible.
    https://github.com/stanford-centaur/smt-switch/blob/f2d7d3d6dfccc0b4d6b604563acd34629bac884d/src/term_translator.cpp#L269C12-L269C12
  2. It looks like cast_op and/or cast_term are being called twice upon themselves, leading to a Boolean-to-BV rewrite immediately followed by a BV-to-Boolean rewrite— which I do not think is the intended behavior, and we would also like to turn off.

Compilations problem

CVC4 does not install cleanly on MacOS X so ./contrib/setup-cvc4.sh fails.
The bug is in CVC4's contrib/get-antlr-3.4. It use realpath, but
there's no realpath on the Mac.

After fixing the previous problem, I got a compilation error for sort.cpp:

./src/sort.cpp:12:55: error: implicit instantiation of undefined template 'std::__1::array<std::__1::basic_string_view<char, std::__1::char_traits >, 6>'
constexpr std::array<std::string_view, NUM_SORT_CONS> generate_sortcon2str()

You need to add

include <array>

at the beginning of sort.cpp. That fixes the problem.

Parse a smt file into smt-switch terms

image
I'm parsing an smt file got from SyGuS and cvc5 above, and I would like to ask how I can obtain the smt::term formula shown in the red frame in the figure? (Just like the function behavior in PySMT --> TSSmtLibParser --> get_fs_fname) Thank you so much for your assistance!

smtlibparser.h header file missing

I am trying to include smtlib_reader.h header file in my project and when compiling, I get a compilation error that smtlibparser.h header file is missing. And indeed, I couldn't find it in the repo directory. What is the appropriate way to approach this? I have installed the needed dependencies for parser, "flex" and "bison". I ran the following command g++ -o my_program main.cpp -Ismt-switch/include -Lsmt-switch/build -lsmt-switch and got this error message:
Screenshot 2023-09-04 at 17 37 39

Why not `const Term&` for `get_value`

https://github.com/makaimann/smt-switch/blob/5aa3c6a9fdc6c9ed386a2261cf8d7613763a1772/include/solver.h#L65

Hi I have a question on the declaration of the get_value function. As I use smt::Term with some STL containers, I feel it is sometimes more convenient to have const smt::Term & there instead of smt::Term &.

I looked into the implementations of get_value for MathSat and Boolector, and it seems that you are not doing any alternation to that shared pointer (I mean making it point to somewhere else). So is there any other reason that it has to be a non-constant pointer?

To be clear, I'm not referring to having AbsTerm as constant (like std::shared_ptr<const AbsTerm> &). I'm talking about the pointer itself: const std::shared_ptr<AbsTerm> &

Thanks!

Question about make_term()

Hello. I am trying to use the make_term(). However, I find that there is some different when using this function. For example, when I use the ts_.make_term(And, prop, eq). Sometime program will synthesis the "bvand", and program will generate something like "ite" format to represent the equal value. However, when I trying to create a new solver, I found that I cannot get the same format, the program can only synthesis "and" and cannot synthesis "ite". I want to know why this will happen? Do I need to set other options to get the former format? The solver I am using is the Boolector.

Thank you very much!

455585c0582d2902e2d3dcfb4f1ef2d

4328b30946f92e761c5e6cf6821d4d4

Calling `to_int` on a bitvector of size 1 causes a crash

It seems like to_int assumes that the bitvector gets converted to a string of the form #bxxx, but for bitvectors of size 1 it is actually true or false (at least when using the bitwuzla solver). For example, the following code causes a crash in to_int:

SmtSolver solver = BitwuzlaSolverFactory::create(false);
solver->set_opt("produce-models", "true");
solver->set_opt("incremental", "true");

Sort sort = solver->make_sort(BV, 1);
Term x = solver->make_symbol("x", sort);
solver->check_sat();
uint64_t i = solver->get_value(x)->to_int();
std::cout << i << "\n";

I would instead expect to_int to return 0 or 1.

Consider adding infrastructure to check if term is from a solver

Could include the solver in every term which would allow term construction without a separate solver object. But this could be expensive. Another option is to just have an interface for asking a term if it belongs to a solver. Depending on underlying solver, could depend on its API instead of using smt switch objects

Failure to push in trivial unsat state -- Yices2 backend

This program throws an exception:

#include <iostream>

#include "smt-switch/yices2_factory.h"
#include "smt-switch/smt.h"

using namespace smt;
using namespace std;

int main(int argc, char * argv[])
{
  SmtSolver solver = Yices2SolverFactory::create(false);
  solver->set_opt("incremental", "true");
  Term f = solver->make_term(false);
  solver->assert_formula(f);
  solver->push();
  solver->pop();
  Sort boolsort = solver->make_sort(BOOL);
  return 0;
}

throws: InternalSolverException: the context state does not allow operation

compiled with: $(CXX) -g -std=c++11 -I./local/include -L./local/lib debug-yices2.cpp -o debug-yices2 -lsmt-switch-yices2 -lsmt-switch -lgmp

It appears that since the context is trivially unsatisfiable, it does not allow more operations. https://yices.csl.sri.com/doc/context-operations.html#assertions-and-satisfiability-checks

However, the yices_smt2 binary handles the SMT-LIB version of this fine, so there must be a work around.

(set-logic QF_BV)
(assert false)
(push 1)
(define-fun _78 () Bool true)
(exit)

Found by using ddSMT to reduce this benchmark.

Can this library also be used as a parser etc. for SMT problems?

Essentially, I would like to be able to parse an SMT problem and traverse the AST etc. Is this possible with this library? The documentation points to the /test dir which leads me to smtlib_reader.h. However, this only contains SmtLibReader which also requires a solver and it is also not entirely clear to me how to SmtLibReader to traverse the AST of an SMT lib parsed problem.

Potential secutiry vulnerability in the shared library which smt-switch depends on. Can you help upgrade to patch versions?

Hi, @makaimann , @yoni206 , I'd like to report a vulnerability issue in smt-switch_0.3.0.

Dependency Graph between Python and Shared Libraries

image

Issue Description

As shown in the above dependency graph, smt-switch_0.3.0 directly or transitively depends on 6 C libraries (.so). However, I noticed that some C libraries are vulnerable, containing the following CVEs:
libgmp-afec2dd4.so.10.2.0 and libgmpxx-25f6cf8d.so.4.4.0from C project gmp(version:6.1.0) exposed 1 vulnerabilities:
CVE-2021-43618

Suggested Vulnerability Patch Versions

No official patch version released, but gmp has fixed the vulnerability in patch.

Python build tools cannot report vulnerable C libraries, which may induce potential security issues to many downstream Python projects.
As a popular python package (smt-switch has 790 downloads per month), could you please upgrade the above shared libraries to their patch versions?

Thanks for your help~
Best regards,
Andy

Build scripts assume fixed paths for transitive dependencies

The CMake files for building the Boolector component assume that the dependencies for Boolector (Cadical and Btor2parser) are in the Boolector tree. This is not necessarily the case, e.g., if the dependencies were linked in from somewhere else, which the Boolector build scripts permit.

target_link_libraries(smt-switch-btor "${BTOR_HOME}/deps/cadical/build/libcadical.a")
target_link_libraries(smt-switch-btor "${BTOR_HOME}/deps/btor2tools/build/libbtor2parser.a")

ar -x "${BTOR_HOME}/deps/cadical/build/libcadical.a" &&
ar -x "${BTOR_HOME}/deps/btor2tools/build/libbtor2parser.a" && cd ../ &&

Performance Issue in LoggingTerm::compare

compare is defined recursively on a LoggingTerm because it needs to check that its operator is the same and all of it's children are the same. On large term DAGs this can easily blow up.

Consider changing check-sat-assuming interface

Some solvers require that assumptions to check-sat-assuming be propositional literals. This is based on the SMT-LIB documentation. However, in smt-lib you can use a define-fun rather than introducing a new constant. Thus it seems overly restrictive to require boolean literals in the API, rather than any boolean formula. Some solvers require boolean literals in the API, but we could consider hiding that from the user.

Portfolio mode

Add a convenience function for running several solvers in a portfolio.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.