├── app ├── starexec_run_default └── main.cpp ├── tests ├── data │ ├── smtlib │ │ ├── hexNumeral.smt2 │ │ ├── binaryNumeral.smt2 │ │ ├── push.smt2 │ │ ├── push2Pop.smt2 │ │ ├── reset.smt2 │ │ ├── model1.smt2 │ │ ├── push2Pop2.smt2 │ │ ├── pushPush.smt2 │ │ ├── resetAssertions.smt2 │ │ ├── pushPushPop.smt2 │ │ ├── model2.smt2 │ │ └── model3.smt2 │ ├── falseAndFalse.smt2 │ ├── bvshl0.smt2 │ ├── unconstrainedMulConst.smt2 │ ├── bvurem_approx.smt2 │ ├── iteApprox.smt2 │ ├── unconstrainedMulVar.smt2 │ ├── smtcomp23 │ │ ├── minimal.smt2 │ │ ├── heapsort.i_0.smt2 │ │ ├── heapsort.i_3.smt2 │ │ ├── heapsort.i_9.smt2 │ │ └── heapsort.i_8.smt2 │ ├── preiner_bug_2020.smt2 │ ├── ARI118=1.smt2 │ ├── smtcomp18 │ │ ├── 01.smt2 │ │ └── 02.smt2 │ ├── check_bvsle_bvmul_8bit.smt2 │ ├── check_eq_bvconcat0_2_64bit.smt2 │ ├── check_bvsge_bvashr0_16bit.smt2 │ ├── AR-fixpoint-1.smt2 │ ├── check_bvsgt_bvudiv1_8bit.smt2 │ ├── check_bvsle_bvlshr0_4bit.smt2 │ ├── check_bvslt_bvashr0_4bit.smt2 │ ├── check_bvsle_bvashr0_4bit.smt2 │ ├── check_bvugt_bvshl0_4bit.smt2 │ ├── check_eq_bvshl0_32bit.smt2 │ ├── check_bvuge_bvudiv0_4bit.smt2 │ ├── audio_ac97_wavepcistream2.cpp.smt2 │ ├── check_bvuge_bvashr1_64bit.smt2 │ ├── Fibonacci01_true-unreach-call_true-no-overflow.c_905.smt2 │ ├── intersection-example-onelane.proof-node1469.smt2 │ ├── ETCS-essentials-node3023.smt2 │ ├── MADWiFi-encode_ie_ok_true-unreach-call.i_7.smt2 │ ├── accelerating-node2100.smt2 │ ├── jain_7_true-unreach-call_true-no-overflow.i_61.smt2 │ ├── magnetic_field-node118398.smt2 │ ├── binary_driver-2007-10-09-node11383.smt2 │ ├── 003.smt2 │ ├── sum02_true-unreach-call_true-no-overflow.i_375.smt2 │ ├── RND_3_14.smt2 │ ├── nlzbe008.smt2 │ ├── 002.smt2 │ ├── RND_6_4.smt2 │ └── RNDPRE_3_48.smt2 ├── testUnconstrained.cpp └── main.cpp ├── lib ├── BDDInterval.cpp ├── Approximated.cpp ├── SimplificationPass.h ├── Model.h ├── simplificationPasses │ ├── EqualityPropagator.h │ ├── PureLiteralEliminator.h │ ├── PureLiteralEliminator.cpp │ └── EqualityPropagator.cpp ├── Logger.h ├── Config.h ├── Approximated.h ├── Logger.cpp ├── VariableOrderer.h ├── UnionFind.cpp ├── Solver.h ├── TermConstIntroducer.h ├── HexHelper.h ├── HashUtils.h ├── SMTLIBInterpreter.h ├── maybeBdd │ ├── maybeBdd.cpp │ └── maybeBdd.h ├── Model.cpp ├── BDDInterval.h ├── ExprSimplifier.h ├── UnconstrainedVariableSimplifier.h ├── ExprToBDDTransformer.h ├── VariableOrderer.cpp └── TermConstIntroducer.cpp ├── .gitmodules ├── .gitignore ├── contrib └── get_deps.sh ├── NEWS.md ├── Dockerfile ├── LICENSE ├── .travis.yml ├── Readme.md ├── cmake ├── FindANTLR.cmake └── ExternalAntlr4Cpp.cmake └── CMakeLists.txt /app/starexec_run_default: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./q3b $1 4 | -------------------------------------------------------------------------------- /tests/data/smtlib/hexNumeral.smt2: -------------------------------------------------------------------------------- 1 | (assert (= #x01 (_ bv1 8))) 2 | (check-sat) 3 | -------------------------------------------------------------------------------- /tests/data/smtlib/binaryNumeral.smt2: -------------------------------------------------------------------------------- 1 | (assert (= #b00000001 (_ bv1 8))) 2 | (check-sat) 3 | -------------------------------------------------------------------------------- /tests/data/falseAndFalse.smt2: -------------------------------------------------------------------------------- 1 | (set-logic QF_BV) 2 | (assert false) 3 | (assert false) 4 | (check-sat) 5 | (exit) 6 | -------------------------------------------------------------------------------- /tests/data/smtlib/push.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-const x (_ BitVec 4)) 3 | (push) 4 | (assert (= x #b0000)) 5 | (check-sat) -------------------------------------------------------------------------------- /lib/BDDInterval.cpp: -------------------------------------------------------------------------------- 1 | #include "Solver.h" 2 | 3 | bool BDDInterval::isInterrupted() const 4 | { 5 | return Solver::resultComputed; 6 | } 7 | -------------------------------------------------------------------------------- /tests/data/smtlib/push2Pop.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-const x (_ BitVec 4)) 3 | (assert false) 4 | (push 2) 5 | (pop) 6 | (pop) 7 | (check-sat) -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "parser/smtlibv2-grammar"] 2 | path = parser/smtlibv2-grammar 3 | url = https://github.com/martinjonas/smtlibv2-grammar.git 4 | -------------------------------------------------------------------------------- /tests/data/smtlib/reset.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-const x (_ BitVec 4)) 3 | (assert false) 4 | (reset) 5 | (assert (= x #b0000)) 6 | (check-sat) -------------------------------------------------------------------------------- /tests/data/smtlib/model1.smt2: -------------------------------------------------------------------------------- 1 | (declare-const x (_ BitVec 4)) 2 | (set-option :produce-models true) 3 | (assert (= x #b0001)) 4 | (check-sat) 5 | (get-model) 6 | -------------------------------------------------------------------------------- /tests/data/smtlib/push2Pop2.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-const x (_ BitVec 4)) 3 | (push) 4 | (assert false) 5 | (push 2) 6 | (pop 2) 7 | (pop) 8 | (check-sat) -------------------------------------------------------------------------------- /tests/data/smtlib/pushPush.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-const x (_ BitVec 4)) 3 | (push) 4 | (assert (= x #b0000)) 5 | (push) 6 | (assert (= x #b0001)) 7 | (check-sat) -------------------------------------------------------------------------------- /tests/data/smtlib/resetAssertions.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-const x (_ BitVec 4)) 3 | (assert false) 4 | (reset-assertions) 5 | (assert (= x #b0000)) 6 | (check-sat) -------------------------------------------------------------------------------- /tests/data/bvshl0.smt2: -------------------------------------------------------------------------------- 1 | (set-logic QF_BV) 2 | (declare-fun x () (_ BitVec 1)) 3 | (declare-fun y () (_ BitVec 1)) 4 | (assert (= (bvshl x y) #b1)) 5 | (check-sat) 6 | (exit) 7 | -------------------------------------------------------------------------------- /tests/data/smtlib/pushPushPop.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-const x (_ BitVec 4)) 3 | (push) 4 | (assert (= x #b0000)) 5 | (push) 6 | (assert (= x #b0001)) 7 | (pop) 8 | (check-sat) -------------------------------------------------------------------------------- /lib/Approximated.cpp: -------------------------------------------------------------------------------- 1 | #include "Approximated.h" 2 | 3 | Precision operator && (const Precision &l, const Precision &r) 4 | { 5 | return l == PRECISE && r == PRECISE ? PRECISE : APPROXIMATED; 6 | } 7 | -------------------------------------------------------------------------------- /tests/data/unconstrainedMulConst.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :status sat) 4 | 5 | (declare-const x (_ BitVec 32)) 6 | 7 | (assert (bvugt (bvmul #x00000002 x) #x00000004)) 8 | (check-sat) -------------------------------------------------------------------------------- /tests/data/bvurem_approx.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | 4 | (assert (forall ((x (_ BitVec 32))) 5 | (bvsle (ite (= x #x00000000) #x8b4feb20 (bvurem #x8b4feb20 x)) #x45a421af)) 6 | ) 7 | 8 | (check-sat) 9 | (exit) 10 | -------------------------------------------------------------------------------- /tests/data/iteApprox.smt2: -------------------------------------------------------------------------------- 1 | (declare-const x (_ BitVec 32)) 2 | (declare-const y (_ BitVec 32)) 3 | 4 | (assert (= (ite (= (bvmul x y) x) 5 | #b0 6 | #b1) 7 | (ite (= (bvmul x y) y) 8 | #b1 9 | #b0))) 10 | (check-sat) 11 | -------------------------------------------------------------------------------- /tests/data/smtlib/model2.smt2: -------------------------------------------------------------------------------- 1 | (set-option :produce-models true) 2 | (declare-const x (_ BitVec 4)) 3 | (declare-const y (_ BitVec 4)) 4 | (declare-const z (_ BitVec 4)) 5 | (assert (= x #b0001)) 6 | (assert (= y #b0001)) 7 | (assert (= z (bvadd x y))) 8 | (check-sat) 9 | (get-model) 10 | -------------------------------------------------------------------------------- /tests/data/smtlib/model3.smt2: -------------------------------------------------------------------------------- 1 | (set-option :produce-models true) 2 | (declare-const x (_ BitVec 4)) 3 | (declare-const y (_ BitVec 4)) 4 | (declare-const z (_ BitVec 4)) 5 | (assert (= x #b0011)) 6 | (assert (= y #b0011)) 7 | (assert (= z (bvmul x y))) 8 | (check-sat) 9 | (get-model) 10 | -------------------------------------------------------------------------------- /lib/SimplificationPass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "z3++.h" 4 | #include "Model.h" 5 | 6 | struct SimplificationPass { 7 | //virtual z3::expr Apply(const z3::expr&) = 0; 8 | virtual void ReconstructModel(Model &model) = 0; 9 | 10 | virtual ~SimplificationPass() {}; 11 | }; 12 | -------------------------------------------------------------------------------- /tests/data/unconstrainedMulVar.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :status unsat) 4 | (declare-fun s () (_ BitVec 8)) 5 | (declare-fun t () (_ BitVec 8)) 6 | 7 | (assert (and (or (not (= s #x00)) (bvsle s t)) 8 | (forall ((x (_ BitVec 8))) (bvslt t (bvmul s x))))) 9 | (check-sat) 10 | (exit) 11 | -------------------------------------------------------------------------------- /lib/Model.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | using BitVector = std::vector; 11 | using Model = std::map>; 12 | 13 | z3::expr substituteModel(z3::expr e, const Model& model); 14 | std::variant vectorFromNumeral(z3::expr e); 15 | void printModel(const Model& model); 16 | -------------------------------------------------------------------------------- /tests/data/smtcomp23/minimal.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic QF_BV) 3 | (define-fun |c_ULTIMATE.start_main_~l~0#1| () (_ BitVec 32) #b01000011010010011111111010111110) 4 | (declare-fun |ULTIMATE.start_main_~n~0#1| () (_ BitVec 32)) 5 | (assert (and (and (= (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) |c_ULTIMATE.start_main_~l~0#1|) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32))) (bvsgt (bvadd |c_ULTIMATE.start_main_~l~0#1| (_ bv1 32)) (_ bv1 32)))) 6 | (check-sat) 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | QuantifiedBvecToBdd 30 | 31 | # User project files 32 | *.pro.* 33 | 34 | build 35 | build/* 36 | 37 | # Temporary files 38 | *~ 39 | -------------------------------------------------------------------------------- /tests/data/preiner_bug_2020.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | 3 | (declare-const s (_ BitVec 1)) 4 | (declare-const t (_ BitVec 1)) 5 | (declare-const y (_ BitVec 1)) 6 | (declare-const z (_ BitVec 1)) 7 | 8 | (assert (= (bvor (bvnot y) z) #b1)) 9 | 10 | (assert 11 | (distinct 12 | (and 13 | (= (bvand z s) s) 14 | (= (bvor y s) s) 15 | ) 16 | (exists ((x (_ BitVec 1))) 17 | (and 18 | (= (bvand z x) x) 19 | (= (bvor y x) x) 20 | (= x s) 21 | ) 22 | ) 23 | ) 24 | ) 25 | 26 | (check-sat) 27 | (exit) -------------------------------------------------------------------------------- /contrib/get_deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | pushd contrib 6 | 7 | git clone -b z3-4.11.2 https://github.com/Z3Prover/z3.git 8 | pushd z3 9 | cmake -S . -B build -DZ3_BUILD_LIBZ3_SHARED=False -DCMAKE_BUILD_TYPE=Release 10 | cmake --build build -j4 11 | popd 12 | 13 | git clone https://github.com/martinjonas/cudd.git 14 | pushd cudd 15 | ./configure --enable-silent-rules --enable-obj --enable-shared && make -j4 16 | popd 17 | 18 | mkdir antlr 19 | wget https://www.antlr.org/download/antlr-4.11.1-complete.jar -P antlr 20 | 21 | popd 22 | -------------------------------------------------------------------------------- /tests/data/ARI118=1.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source |These benchmarks are translations from the TPTP Library (Thousands of 4 | Problems for Theorem Provers), see http://www.cs.miami.edu/~tptp/ 5 | 6 | The TPTP is maintained by Geoff Sutcliffe, and he contributed this 7 | selection of benchmarks to SMT-LIB. 8 | 9 | Translated to BV by Mathias Preiner. 10 | |) 11 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 12 | (set-info :category "industrial") 13 | (set-info :status unknown) 14 | (assert (not (exists ((?X (_ BitVec 32)) (?Y (_ BitVec 32))) (= (bvmul ?X ?Y) ?X)))) 15 | (check-sat) 16 | (exit) 17 | -------------------------------------------------------------------------------- /lib/simplificationPasses/EqualityPropagator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "z3++.h" 6 | 7 | #include "../SimplificationPass.h" 8 | 9 | class EqualityPropagator : public SimplificationPass 10 | { 11 | public: 12 | EqualityPropagator(z3::context &ctx) : context(&ctx) { }; 13 | z3::expr Apply(const z3::expr&); //override; 14 | void ReconstructModel(Model &model) override; 15 | 16 | private: 17 | z3::context* context; 18 | 19 | bool getSubstitutableEquality(const z3::expr&, z3::expr*, z3::expr*); 20 | bool isVar(const z3::expr&) const; 21 | 22 | std::vector> appliedSubstitutions; 23 | }; 24 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # News 2 | 3 | ## 1.1 4 | 5 | – Fix unsoundness issues caused by variable polarities. 6 | – Fix abstractions for Boolean =. 7 | – Disable (incorrect) DAG counting in unconstrained variable simplifier. 8 | – Terminate threads during BDD operations using CUDD termination handler. 9 | – Add support for Boolean “distinct” operator. 10 | – Add support for n-ary bitwise connectives. 11 | – Several improvements to formula rewriting. 12 | – Update ANTLR version to v4.10. 13 | – Update Catch to v2.13.9. 14 | 15 | ## 1.0 (commit 9630b6ccf6c116d42f00da8a9c88086206d71d57) 16 | 17 | This is the version described in the CAV 2019 paper “Q3B: an efficient bdd-based 18 | SMT solver for quantified bit-vectors”. 19 | -------------------------------------------------------------------------------- /lib/Logger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | enum LogType 9 | { 10 | WARNING, 11 | INFO, 12 | ERROR 13 | }; 14 | 15 | class Logger 16 | { 17 | private: 18 | static int m_verbosityLevel; 19 | static std::mutex m; 20 | static std::chrono::time_point startTime; 21 | 22 | public: 23 | static void Log(const std::string&, const std::string&, const int, const LogType& type = LogType::INFO); 24 | static void SetVerbosity(const unsigned int verbosityLevel) 25 | { 26 | m_verbosityLevel = verbosityLevel; 27 | } 28 | 29 | static unsigned int GetVerbosity() 30 | { 31 | return m_verbosityLevel; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /lib/simplificationPasses/PureLiteralEliminator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "z3++.h" 7 | 8 | #include "../SimplificationPass.h" 9 | 10 | enum Polarity { POSITIVE, NEGATIVE, BOTH_POLARITIES }; 11 | 12 | class PureLiteralEliminator : public SimplificationPass 13 | { 14 | public: 15 | PureLiteralEliminator(z3::context &ctx) : context(&ctx) { }; 16 | z3::expr Apply(z3::expr&); //override; 17 | void ReconstructModel(Model &model) override; 18 | 19 | private: 20 | z3::context* context; 21 | 22 | std::set< std::tuple< const Z3_ast, bool > > processedPolaritiesCache; 23 | std::map< std::string, Polarity > variablePolarities; 24 | void getVariablePolarities(const z3::expr&, bool); 25 | 26 | std::vector> appliedSubstitutions; 27 | }; 28 | -------------------------------------------------------------------------------- /tests/data/smtcomp18/01.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-fun x4 () (_ BitVec 4)) 3 | (declare-fun x2 () (_ BitVec 4)) 4 | (define-fun x8 ((x3 (_ BitVec 4)) (x9 (_ BitVec 4))) (_ BitVec 4) (ite (= (_ bv0 4) x9) (bvnot (_ bv0 4)) (bvudiv x3 x9))) 5 | (define-fun x6 ((x3 (_ BitVec 4)) (x9 (_ BitVec 4))) (_ BitVec 4) (ite (= x9 (_ bv0 4)) x3 (bvurem x3 x9))) 6 | (define-fun x10 () (_ BitVec 4) (bvnot (bvlshr (bvnot (_ bv0 4)) (_ bv1 4)))) 7 | (define-fun x7 () (_ BitVec 4) (bvnot x10)) 8 | (define-fun x5 ((x4 (_ BitVec 4)) (x2 (_ BitVec 4))) Bool (and (=> (bvsge x4 (_ bv0 4)) (bvslt x2 x4)) (=> (bvsgt (_ bv0 4) x4) (bvsgt (bvlshr (bvsub x4 (_ bv1 4)) (_ bv1 4)) x2)))) 9 | (assert (not (and (=> (exists ((x1 (_ BitVec 4))) (bvslt x2 (x6 x4 x1))) (x5 x4 x2)) (=> (x5 x4 x2) (exists ((x1 (_ BitVec 4))) (bvslt x2 (x6 x4 x1))))))) 10 | (check-sat) 11 | (exit) 12 | -------------------------------------------------------------------------------- /lib/Config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum ApproximationMethod { NONE, VARIABLES, OPERATIONS, BOTH }; 4 | enum ReorderType { NO_REORDER, WIN2, WIN2_ITE, WIN3, WIN3_ITE, SIFT, SIFT_ITE }; 5 | enum Approximations { NO_APPROXIMATIONS, ONLY_UNDERAPPROXIMATIONS, ONLY_OVERAPPROXIMATIONS, ALL_APPROXIMATIONS}; 6 | 7 | struct Config 8 | { 9 | ApproximationMethod approximationMethod = BOTH; 10 | Approximations approximations = ALL_APPROXIMATIONS; 11 | int precision = 0; 12 | 13 | ReorderType reorderType = SIFT; 14 | 15 | bool propagateUnconstrained = true; 16 | bool goalUnconstrained = true; 17 | 18 | bool useDontCares = false; 19 | 20 | bool checkModels = true; 21 | bool addCongruences = true; 22 | 23 | bool flipUniversalQuantifier = false; 24 | bool propagateNecessaryBits = true; 25 | 26 | bool produceModels = false; 27 | bool validatingSolver = false; 28 | }; 29 | -------------------------------------------------------------------------------- /lib/Approximated.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum Precision { APPROXIMATED, PRECISE }; 6 | 7 | Precision operator && (const Precision &l, const Precision &r); 8 | 9 | template 10 | struct Approximated 11 | { 12 | T value; 13 | Precision operationPrecision; 14 | Precision variablePrecision; 15 | 16 | Precision isPrecise() const 17 | { 18 | return operationPrecision && variablePrecision; 19 | } 20 | 21 | template 22 | Approximated Apply(const std::function &f) 23 | { 24 | return {f(value), operationPrecision, variablePrecision}; 25 | } 26 | 27 | template 28 | Approximated Apply2(const Approximated &r, const std::function &f) 29 | { 30 | TRes res = f(value, r.value); 31 | return {res, operationPrecision && r.operationPrecision, variablePrecision && r.variablePrecision}; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /lib/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.h" 2 | 3 | int Logger::m_verbosityLevel = 0; 4 | std::mutex Logger::m; 5 | std::chrono::time_point Logger::startTime = std::chrono::high_resolution_clock::now(); 6 | 7 | std::string logTypeToStr(const LogType& type) 8 | { 9 | switch (type) 10 | { 11 | case LogType::WARNING: 12 | return "Warning"; 13 | case LogType::INFO: 14 | return "Info"; 15 | case LogType::ERROR: 16 | return "Error"; 17 | default: 18 | abort(); 19 | } 20 | } 21 | 22 | void Logger::Log(const std::string& module, const std::string& message, const int verbosity, const LogType& type) 23 | { 24 | if (verbosity <= m_verbosityLevel) 25 | { 26 | std::chrono::duration time = std::chrono::high_resolution_clock::now() - startTime; 27 | std::unique_lock lk(m); 28 | std::cout << "[" << logTypeToStr(type) << ", " << time.count() << "s] " << module << ": " << message << std::endl; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | RUN apt-get update 4 | RUN apt-get install -y g++ autotools-dev automake wget unzip git make cmake default-jre pkg-config 5 | RUN apt-get update 6 | RUN apt-get install uuid-dev 7 | 8 | RUN wget https://github.com/Z3Prover/z3/releases/download/z3-4.11.2/z3-4.11.2-x64-glibc-2.31.zip 9 | RUN unzip z3-4.11.2-x64-glibc-2.31.zip 10 | RUN cp z3-4.11.2-x64-glibc-2.31/bin/libz3.a /usr/lib 11 | RUN cp z3-4.11.2-x64-glibc-2.31/include/* /usr/include 12 | 13 | RUN git clone -b 3val https://github.com/martinjonas/cudd.git 14 | RUN cd cudd && ./configure --enable-silent-rules --enable-obj --enable-shared && make -j4 && make install 15 | 16 | RUN wget https://www.antlr.org/download/antlr-4.11.1-complete.jar -P /usr/share/java 17 | 18 | RUN mkdir Q3B 19 | COPY . Q3B 20 | WORKDIR Q3B 21 | RUN cmake -B build -DANTLR_EXECUTABLE=/usr/share/java/antlr-4.11.1-complete.jar 22 | RUN cmake --build build -j4 23 | RUN cd build && make test 24 | 25 | ENTRYPOINT bash 26 | -------------------------------------------------------------------------------- /tests/data/check_bvsle_bvmul_8bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 8)) 17 | (declare-fun t () (_ BitVec 8)) 18 | 19 | (assert 20 | (let ((a!1 (and (or (not (= s #x00)) (bvsle s t)) 21 | (forall ((x (_ BitVec 8))) (bvslt t (bvmul s x))))) 22 | (a!2 (and (exists ((x (_ BitVec 8))) (bvsle (bvmul s x) t)) 23 | (= s #x00) 24 | (bvslt t s)))) 25 | (or a!1 a!2)) 26 | ) 27 | 28 | 29 | (check-sat) 30 | (exit) 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Martin Jonáš 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/data/check_eq_bvconcat0_2_64bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 64)) 17 | (declare-fun tx () (_ BitVec 2)) 18 | (declare-fun ts () (_ BitVec 64)) 19 | 20 | (define-fun min () (_ BitVec 2) 21 | (bvnot (bvlshr (bvnot (_ bv0 2)) (_ bv1 2))) 22 | ) 23 | (define-fun max () (_ BitVec 2) 24 | (bvnot min) 25 | ) 26 | 27 | (define-fun SC () Bool 28 | (= s ts) 29 | ) 30 | 31 | (assert 32 | (not 33 | (and 34 | (=> SC (exists ((x (_ BitVec 2))) (= (concat x s) (concat tx ts)))) 35 | (=> (exists ((x (_ BitVec 2))) (= (concat x s) (concat tx ts))) SC) 36 | ) 37 | ) 38 | ) 39 | (check-sat) 40 | (exit) 41 | -------------------------------------------------------------------------------- /tests/data/check_bvsge_bvashr0_16bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 16)) 17 | (declare-fun t () (_ BitVec 16)) 18 | 19 | (define-fun min () (_ BitVec 16) 20 | (bvnot (bvlshr (bvnot (_ bv0 16)) (_ bv1 16))) 21 | ) 22 | (define-fun max () (_ BitVec 16) 23 | (bvnot min) 24 | ) 25 | 26 | (define-fun SC ((s (_ BitVec 16)) (t (_ BitVec 16))) Bool 27 | (bvsge (bvlshr max s) t) 28 | ) 29 | 30 | (assert 31 | (not 32 | (and 33 | (=> (SC s t) (exists ((x (_ BitVec 16))) (bvsge (bvashr x s) t))) 34 | (=> (exists ((x (_ BitVec 16))) (bvsge (bvashr x s) t)) (SC s t)) 35 | ) 36 | ) 37 | ) 38 | (check-sat) 39 | (exit) 40 | -------------------------------------------------------------------------------- /tests/data/smtcomp18/02.smt2: -------------------------------------------------------------------------------- 1 | (set-logic BV) 2 | (declare-fun x5 () (_ BitVec 8)) 3 | (declare-fun x6 () (_ BitVec 8)) 4 | (declare-fun x1 () (_ BitVec 8)) 5 | (declare-fun x2 () (_ BitVec 8)) 6 | (declare-fun x3 () (_ BitVec 8)) 7 | (declare-fun x7 () (_ BitVec 8)) 8 | (assert (and (= ((_ extract 7 0) (bvsrem ((_ sign_extend 24) x1) ((_ sign_extend 24) x2))) x7) (= x5 x6) (= x2 x5) (not (= ((_ sign_extend 24) (_ bv0 8)) ((_ sign_extend 24) x2))))) 9 | (assert (or (forall ((x4 (_ BitVec 8))) (or (bvsge ((_ sign_extend 24) x3) ((_ sign_extend 24) x4)) (not (= ((_ sign_extend 24) ((_ extract 7 0) (bvsrem ((_ sign_extend 24) x2) ((_ sign_extend 24) x4)))) ((_ sign_extend 24) (_ bv0 8)))))) (= ((_ sign_extend 24) x2) ((_ sign_extend 24) (_ bv0 8))) (not (bvsgt ((_ sign_extend 24) x3) ((_ sign_extend 24) (_ bv0 8)))))) 10 | (assert (not (or (forall ((x4 (_ BitVec 8))) (or (bvsle ((_ sign_extend 24) x4) ((_ sign_extend 24) x3)) (not (= ((_ sign_extend 24) ((_ extract 7 0) (bvsrem ((_ sign_extend 24) x7) ((_ sign_extend 24) x4)))) ((_ sign_extend 24) (_ bv0 8)))))) (= ((_ sign_extend 24) x7) ((_ sign_extend 24) (_ bv0 8))) (bvslt ((_ sign_extend 24) x7) ((_ sign_extend 24) (_ bv0 8))) (not (bvslt ((_ sign_extend 24) (_ bv0 8)) ((_ sign_extend 24) x3)))))) 11 | (check-sat) 12 | (exit) 13 | -------------------------------------------------------------------------------- /lib/VariableOrderer.h: -------------------------------------------------------------------------------- 1 | #ifndef VARIABLEORDERER_H 2 | #define VARIABLEORDERER_H 3 | 4 | #include "UnionFind.cpp" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | typedef std::pair var; 13 | 14 | class VariableOrderer 15 | { 16 | private: 17 | std::set vars; 18 | std::map varIndices; 19 | UF *unionFind = NULL; 20 | z3::context* context; 21 | 22 | bool MergeByExpression(const z3::expr&, std::vector boundVars); 23 | void MarkDependent(const std::string&, const std::string&); 24 | void MergeVars(const std::set&); 25 | void MergeAllVarsInExpression(const z3::expr&, std::vector boundVars); 26 | std::set GetVars(const z3::expr&, std::vector); 27 | 28 | std::map> processedMergedSubformulaCache; 29 | std::map, std::vector>> processedVarsCache; 30 | 31 | public: 32 | VariableOrderer(const std::set&, z3::context&); 33 | void OrderFor(const z3::expr&); 34 | void MergeAll(); 35 | 36 | std::vector> GetOrdered() const; 37 | }; 38 | 39 | #endif // VARIABLEORDERER_H 40 | -------------------------------------------------------------------------------- /tests/data/AR-fixpoint-1.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Hardware fixpoint check problems. 5 | These benchmarks stem from an evaluation described in Wintersteiger, Hamadi, de Moura: Efficiently solving quantified bit-vector formulas, FMSD 42(1), 2013. 6 | The hardware models that were used are from the VCEGAR benchmark suite (see www.cprover.org/hardware/). 7 | |) 8 | (set-info :category "industrial") 9 | (set-info :status unsat) 10 | (assert (forall ((Verilog__main.a_64_0 (_ BitVec 2501))) (forall ((Verilog__main.b_64_0 (_ BitVec 2501))) (forall ((Verilog__main.a_64_1 (_ BitVec 2501))) (forall ((Verilog__main.b_64_1 (_ BitVec 2501))) (exists ((Verilog__main.a_64_0_39_ (_ BitVec 2501))) (exists ((Verilog__main.b_64_0_39_ (_ BitVec 2501))) (=> (and (and (= Verilog__main.a_64_0 (_ bv1 2501)) (= Verilog__main.b_64_0 (_ bv0 2501))) (and (= Verilog__main.a_64_1 (ite (bvult Verilog__main.a_64_0 (_ bv100 2501)) (bvadd Verilog__main.b_64_0 Verilog__main.a_64_0) Verilog__main.a_64_0)) (= Verilog__main.b_64_1 Verilog__main.a_64_0))) (and (and (= Verilog__main.a_64_0_39_ (_ bv1 2501)) (= Verilog__main.b_64_0_39_ (_ bv0 2501))) (and (= Verilog__main.a_64_1 Verilog__main.a_64_0_39_) (= Verilog__main.b_64_1 Verilog__main.b_64_0_39_)))) ) ) ) ) ) )) 11 | (check-sat) 12 | (exit) 13 | -------------------------------------------------------------------------------- /tests/data/check_bvsgt_bvudiv1_8bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 8)) 17 | (declare-fun t () (_ BitVec 8)) 18 | 19 | (define-fun udivtotal ((a (_ BitVec 8)) (b (_ BitVec 8))) (_ BitVec 8) 20 | (ite (= b (_ bv0 8)) (bvnot (_ bv0 8)) (bvudiv a b)) 21 | ) 22 | (define-fun uremtotal ((a (_ BitVec 8)) (b (_ BitVec 8))) (_ BitVec 8) 23 | (ite (= b (_ bv0 8)) a (bvurem a b)) 24 | ) 25 | 26 | (define-fun SC ((s (_ BitVec 8)) (t (_ BitVec 8))) Bool 27 | (and (=> (bvsge s (_ bv0 8)) (bvsgt s t)) (=> (bvslt s (_ bv0 8)) (bvsgt (bvlshr s (_ bv1 8)) t))) 28 | ) 29 | 30 | (assert 31 | (not 32 | (and 33 | (=> (SC s t) (exists ((x (_ BitVec 8))) (bvsgt (udivtotal s x) t))) 34 | (=> (exists ((x (_ BitVec 8))) (bvsgt (udivtotal s x) t)) (SC s t)) 35 | ) 36 | ) 37 | ) 38 | (check-sat) 39 | (exit) 40 | -------------------------------------------------------------------------------- /tests/data/check_bvsle_bvlshr0_4bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 4)) 17 | (declare-fun t () (_ BitVec 4)) 18 | 19 | (define-fun udivtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 20 | (ite (= b (_ bv0 4)) (bvnot (_ bv0 4)) (bvudiv a b)) 21 | ) 22 | (define-fun uremtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 23 | (ite (= b (_ bv0 4)) a (bvurem a b)) 24 | ) 25 | (define-fun min () (_ BitVec 4) 26 | (bvnot (bvlshr (bvnot (_ bv0 4)) (_ bv1 4))) 27 | ) 28 | (define-fun max () (_ BitVec 4) 29 | (bvnot min) 30 | ) 31 | 32 | (define-fun SC ((s (_ BitVec 4)) (t (_ BitVec 4))) Bool 33 | (bvsge t (bvlshr t s)) 34 | ) 35 | 36 | (assert 37 | (not 38 | (and 39 | (=> (SC s t) (exists ((x (_ BitVec 4))) (bvsle (bvlshr x s) t))) 40 | (=> (exists ((x (_ BitVec 4))) (bvsle (bvlshr x s) t)) (SC s t)) 41 | ) 42 | ) 43 | ) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /tests/data/check_bvslt_bvashr0_4bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 4)) 17 | (declare-fun t () (_ BitVec 4)) 18 | 19 | (define-fun udivtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 20 | (ite (= b (_ bv0 4)) (bvnot (_ bv0 4)) (bvudiv a b)) 21 | ) 22 | (define-fun uremtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 23 | (ite (= b (_ bv0 4)) a (bvurem a b)) 24 | ) 25 | (define-fun min () (_ BitVec 4) 26 | (bvnot (bvlshr (bvnot (_ bv0 4)) (_ bv1 4))) 27 | ) 28 | (define-fun max () (_ BitVec 4) 29 | (bvnot min) 30 | ) 31 | 32 | (define-fun SC ((s (_ BitVec 4)) (t (_ BitVec 4))) Bool 33 | (bvslt (bvashr min s) t) 34 | ) 35 | 36 | (assert 37 | (not 38 | (and 39 | (=> (SC s t) (exists ((x (_ BitVec 4))) (bvslt (bvashr x s) t))) 40 | (=> (exists ((x (_ BitVec 4))) (bvslt (bvashr x s) t)) (SC s t)) 41 | ) 42 | ) 43 | ) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /lib/UnionFind.cpp: -------------------------------------------------------------------------------- 1 | class UF { 2 | int *id, cnt, *sz; 3 | public: 4 | // Create an empty union find data structure with N isolated sets. 5 | UF(int N) { 6 | cnt = N; 7 | id = new int[N]; 8 | sz = new int[N]; 9 | for(int i=0; i (SC s t) (exists ((x (_ BitVec 4))) (bvsle (bvashr x s) t))) 40 | (=> (exists ((x (_ BitVec 4))) (bvsle (bvashr x s) t)) (SC s t)) 41 | ) 42 | ) 43 | ) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /tests/data/check_bvugt_bvshl0_4bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 4)) 17 | (declare-fun t () (_ BitVec 4)) 18 | 19 | (define-fun udivtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 20 | (ite (= b (_ bv0 4)) (bvnot (_ bv0 4)) (bvudiv a b)) 21 | ) 22 | (define-fun uremtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 23 | (ite (= b (_ bv0 4)) a (bvurem a b)) 24 | ) 25 | (define-fun min () (_ BitVec 4) 26 | (bvnot (bvlshr (bvnot (_ bv0 4)) (_ bv1 4))) 27 | ) 28 | (define-fun max () (_ BitVec 4) 29 | (bvnot min) 30 | ) 31 | 32 | (define-fun SC ((s (_ BitVec 4)) (t (_ BitVec 4))) Bool 33 | (bvult t (bvshl (bvnot (_ bv0 4)) s)) 34 | ) 35 | 36 | (assert 37 | (not 38 | (and 39 | (=> (SC s t) (exists ((x (_ BitVec 4))) (bvugt (bvshl x s) t))) 40 | (=> (exists ((x (_ BitVec 4))) (bvugt (bvshl x s) t)) (SC s t)) 41 | ) 42 | ) 43 | ) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /tests/data/check_eq_bvshl0_32bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 32)) 17 | (declare-fun t () (_ BitVec 32)) 18 | 19 | (define-fun udivtotal ((a (_ BitVec 32)) (b (_ BitVec 32))) (_ BitVec 32) 20 | (ite (= b (_ bv0 32)) (bvnot (_ bv0 32)) (bvudiv a b)) 21 | ) 22 | (define-fun uremtotal ((a (_ BitVec 32)) (b (_ BitVec 32))) (_ BitVec 32) 23 | (ite (= b (_ bv0 32)) a (bvurem a b)) 24 | ) 25 | (define-fun min () (_ BitVec 32) 26 | (bvnot (bvlshr (bvnot (_ bv0 32)) (_ bv1 32))) 27 | ) 28 | (define-fun max () (_ BitVec 32) 29 | (bvnot min) 30 | ) 31 | 32 | (define-fun SC ((s (_ BitVec 32)) (t (_ BitVec 32))) Bool 33 | (= (bvshl (bvlshr t s) s) t) 34 | ) 35 | 36 | (assert 37 | (not 38 | (and 39 | (=> (SC s t) (exists ((x (_ BitVec 32))) (= (bvshl x s) t))) 40 | (=> (exists ((x (_ BitVec 32))) (= (bvshl x s) t)) (SC s t)) 41 | ) 42 | ) 43 | ) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /tests/data/check_bvuge_bvudiv0_4bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 4)) 17 | (declare-fun t () (_ BitVec 4)) 18 | 19 | (define-fun udivtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 20 | (ite (= b (_ bv0 4)) (bvnot (_ bv0 4)) (bvudiv a b)) 21 | ) 22 | (define-fun uremtotal ((a (_ BitVec 4)) (b (_ BitVec 4))) (_ BitVec 4) 23 | (ite (= b (_ bv0 4)) a (bvurem a b)) 24 | ) 25 | (define-fun min () (_ BitVec 4) 26 | (bvnot (bvlshr (bvnot (_ bv0 4)) (_ bv1 4))) 27 | ) 28 | (define-fun max () (_ BitVec 4) 29 | (bvnot min) 30 | ) 31 | 32 | (define-fun SC ((s (_ BitVec 4)) (t (_ BitVec 4))) Bool 33 | (= (bvand (udivtotal (bvmul s t) t) s) s) 34 | ) 35 | 36 | (assert 37 | (not 38 | (and 39 | (=> (SC s t) (exists ((x (_ BitVec 4))) (bvuge (udivtotal x s) t))) 40 | (=> (exists ((x (_ BitVec 4))) (bvuge (udivtotal x s) t)) (SC s t)) 41 | ) 42 | ) 43 | ) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /tests/data/audio_ac97_wavepcistream2.cpp.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | Software ranking function synthesis problems. 4 | These benchmarks stem from an evaluation described in Wintersteiger, Hamadi, de Moura: Efficiently solving quantified bit-vector formulas, FMSD 42(1), 2013. 5 | The software models that were used are from a previous evaluation of termination proving tools described in Cook, Kroening, Ruemmer, Wintersteiger: Ranking Function Synthesis for Bit-Vector Relations, TACAS 2010. 6 | |) 7 | (set-info :category "industrial") 8 | (set-info :status unsat) 9 | (assert (exists ((cpp__main__c__main__1__1__i_36_C (_ BitVec 32))) (forall ((termination__pre__0__cpp__main__c__main__1__1__i (_ BitVec 32))) (forall ((cpp__main__c__main__1__1__i_35_0 (_ BitVec 32))) (forall ((cpp__main__c__main__1__nCurrentIndex (_ BitVec 8))) (forall ((cpp__main__c__main__1__1__i (_ BitVec 32))) (=> (and (= termination__pre__0__cpp__main__c__main__1__1__i cpp__main__c__main__1__1__i_35_0) (not (= cpp__main__c__main__1__1__i_35_0 ((_ zero_extend 24) cpp__main__c__main__1__nCurrentIndex))) (= cpp__main__c__main__1__1__i (bvand (bvadd cpp__main__c__main__1__1__i_35_0 (_ bv1 32)) (_ bv31 32)))) (bvslt (bvmul ((_ sign_extend 32) cpp__main__c__main__1__1__i_36_C) ((_ sign_extend 32) cpp__main__c__main__1__1__i)) (bvmul ((_ sign_extend 32) cpp__main__c__main__1__1__i_36_C) ((_ sign_extend 32) termination__pre__0__cpp__main__c__main__1__1__i)))) ) ) ) ) )) 10 | (check-sat) 11 | (exit) 12 | -------------------------------------------------------------------------------- /tests/data/check_bvuge_bvashr1_64bit.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by: Mathias Preiner 5 | Generated on: 2018-04-06 6 | Application: Verification of invertibility conditions generated in [1]. 7 | Target solver: Boolector, CVC4, Z3 8 | Publication: 9 | [1] Solving Quantified Bit-Vectors using Invertibility Conditions 10 | Aina Niemetz, Mathias Preiner, Andrew Reynolds, Clark Barrett and Cesare Tinelli 11 | To appear in CAV 2018 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "crafted") 15 | (set-info :status unsat) 16 | (declare-fun s () (_ BitVec 64)) 17 | (declare-fun t () (_ BitVec 64)) 18 | 19 | (define-fun udivtotal ((a (_ BitVec 64)) (b (_ BitVec 64))) (_ BitVec 64) 20 | (ite (= b (_ bv0 64)) (bvnot (_ bv0 64)) (bvudiv a b)) 21 | ) 22 | (define-fun uremtotal ((a (_ BitVec 64)) (b (_ BitVec 64))) (_ BitVec 64) 23 | (ite (= b (_ bv0 64)) a (bvurem a b)) 24 | ) 25 | (define-fun min () (_ BitVec 64) 26 | (bvnot (bvlshr (bvnot (_ bv0 64)) (_ bv1 64))) 27 | ) 28 | (define-fun max () (_ BitVec 64) 29 | (bvnot min) 30 | ) 31 | 32 | (define-fun SC ((s (_ BitVec 64)) (t (_ BitVec 64))) Bool 33 | (not (and (bvult s (bvnot s)) (bvult s t))) 34 | ) 35 | 36 | (assert 37 | (not 38 | (and 39 | (=> (SC s t) (exists ((x (_ BitVec 64))) (bvuge (bvashr s x) t))) 40 | (=> (exists ((x (_ BitVec 64))) (bvuge (bvashr s x) t)) (SC s t)) 41 | ) 42 | ) 43 | ) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | sudo: true 3 | language: c++ 4 | 5 | addons: 6 | ssh_known_hosts: 7 | - gitlab.fi.muni.cz 8 | apt: 9 | sources: 10 | - ubuntu-toolchain-r-test 11 | packages: 12 | - g++-7 13 | - ggcov 14 | - autotools-dev 15 | - automake 16 | 17 | notifications: 18 | email: 19 | - martin.jonas@mail.muni.cz 20 | 21 | before_install: 22 | - eval "${SET_GCC}" 23 | - sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-7 90 24 | - pip install --user cpp-coveralls 25 | 26 | install: 27 | - export CXX=g++-7 28 | - export CC=gcc-7 29 | - wget https://github.com/Z3Prover/z3/releases/download/z3-4.8.4/z3-4.8.4.d6df51951f4c-x64-ubuntu-16.04.zip 30 | - unzip -q z3-4.8.4.d6df51951f4c-x64-ubuntu-16.04.zip -d z3_downloaded 31 | - sudo cp z3_downloaded/z3-4.8.4.d6df51951f4c-x64-ubuntu-16.04/bin/libz3.{a,so} /usr/lib/ 32 | - sudo cp z3_downloaded/z3-4.8.4.d6df51951f4c-x64-ubuntu-16.04/include/* /usr/include/ 33 | - git clone https://github.com/martinjonas/cudd.git 34 | - cd cudd 35 | - ./configure --enable-silent-rules --enable-obj --enable-shared && make -j4 && sudo make install 36 | - cd .. 37 | - sudo wget https://www.antlr.org/download/antlr-4.8-complete.jar -P /usr/share/java 38 | 39 | script: 40 | - mkdir build && cd build && cmake .. -DCOVERAGE=1 -DANTLR_EXECUTABLE=/usr/share/java/antlr-4.8-complete.jar 41 | - make -j4 42 | - make test 43 | - cd .. 44 | 45 | after_success: 46 | - coveralls --exclude app --exclude cudd --exclude z3_downloaded --exclude build/antlr_runtime --exclude tests --gcov-options '\-lp' -------------------------------------------------------------------------------- /lib/Solver.h: -------------------------------------------------------------------------------- 1 | #ifndef BDDSOLVER_H 2 | #define BDDSOLVER_H 3 | 4 | #include 5 | #include "cudd.h" 6 | #include 7 | #include "ExprToBDDTransformer.h" 8 | #include "Config.h" 9 | #include "Model.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | enum Result { SAT, UNSAT, UNKNOWN, NORESULT }; 16 | 17 | class Solver 18 | { 19 | public: 20 | Solver(Config config) : config(config) { } 21 | 22 | Result Solve(z3::expr, Approximation approximation = NO_APPROXIMATION, int effectiveBitWidth = 0); 23 | Result SolveParallel(z3::expr); 24 | Model GetModel() const; 25 | 26 | static std::mutex m_z3context; 27 | static std::atomic resultComputed; 28 | 29 | private: 30 | Config config; 31 | 32 | Result runUnderApproximation(ExprToBDDTransformer&, int, int); 33 | Result runOverApproximation(ExprToBDDTransformer&, int, int); 34 | 35 | Result runWithApproximations(ExprToBDDTransformer&, Approximation); 36 | Result runWithOverApproximations(ExprToBDDTransformer&); 37 | Result runWithUnderApproximations(ExprToBDDTransformer&); 38 | 39 | Result getResult(z3::expr, Approximation approximation = NO_APPROXIMATION, int effectiveBitWidth = 0); 40 | static Result solverThread(z3::expr, Config config, Approximation approximation = NO_APPROXIMATION, int effectiveBitWidth = 0); 41 | 42 | static std::atomic globalResult; 43 | static Model model; 44 | Model threadModel; 45 | static std::mutex m; 46 | static std::mutex m_res; 47 | static std::condition_variable doneCV; 48 | }; 49 | 50 | #endif // BDDSOLVER_H 51 | -------------------------------------------------------------------------------- /lib/TermConstIntroducer.h: -------------------------------------------------------------------------------- 1 | #ifndef TERMCONSTINTRODUCER_H 2 | #define TERMCONSTINTRODUCER_H 3 | #include "z3++.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | struct OpVar 11 | { 12 | z3::expr result; 13 | Z3_decl_kind op; 14 | z3::expr l; 15 | z3::expr r; 16 | 17 | OpVar(z3::expr result, Z3_decl_kind op, z3::expr l, z3::expr r) : 18 | result(result), op(op), l(l), r(r) 19 | { 20 | } 21 | 22 | friend bool operator < (OpVar const& lhs, OpVar const& rhs); 23 | friend bool operator == (OpVar const& lhs, OpVar const& rhs); 24 | }; 25 | 26 | class TermConstIntroducer 27 | { 28 | public: 29 | TermConstIntroducer(z3::context &ctx) 30 | { 31 | this->context = &ctx; 32 | } 33 | 34 | z3::expr FlattenMul(const z3::expr&); 35 | 36 | private: 37 | enum BoundType { EXISTENTIAL, UNIVERSAL }; 38 | 39 | struct Var 40 | { 41 | std::string name; 42 | BoundType boundType; 43 | z3::expr expr; 44 | 45 | Var(std::string name, BoundType boundType, z3::expr e) : 46 | name(name), boundType(boundType), expr(e) 47 | { } 48 | 49 | bool operator == (const Var& rhs) const 50 | { 51 | return name == rhs.name; 52 | } 53 | }; 54 | 55 | z3::context* context; 56 | std::pair> flattenMulRec(const z3::expr&, const std::vector&); 57 | 58 | std::map> varsLInMul; 59 | std::map> varsRInMul; 60 | 61 | void fillVarsInMul(const z3::expr&); 62 | 63 | bool isVar(z3::expr); 64 | 65 | std::set fillVarsCache; 66 | std::map, std::set>> flattenMulCache; 67 | }; 68 | 69 | 70 | #endif // EXPRSIMPLIFIER_H 71 | -------------------------------------------------------------------------------- /lib/HexHelper.h: -------------------------------------------------------------------------------- 1 | #ifndef HEXHELPER_H 2 | #define HEXHELPER_H 3 | 4 | #include 5 | 6 | class HexHelper 7 | { 8 | private: 9 | static const char* hex_char_to_bin(char c) 10 | { 11 | // TODO handle default / error 12 | switch(toupper(c)) 13 | { 14 | case '0': return "0000"; 15 | case '1': return "0001"; 16 | case '2': return "0010"; 17 | case '3': return "0011"; 18 | case '4': return "0100"; 19 | case '5': return "0101"; 20 | case '6': return "0110"; 21 | case '7': return "0111"; 22 | case '8': return "1000"; 23 | case '9': return "1001"; 24 | case 'A': return "1010"; 25 | case 'B': return "1011"; 26 | case 'C': return "1100"; 27 | case 'D': return "1101"; 28 | case 'E': return "1110"; 29 | case 'F': return "1111"; 30 | default: return "0000"; 31 | } 32 | } 33 | 34 | public: 35 | static std::string hex_str_to_bin_str(const std::string& hex) 36 | { 37 | // TODO use a loop from or smth 38 | std::string bin; 39 | for(unsigned i = 0; i != hex.length(); ++i) 40 | bin += hex_char_to_bin(hex[i]); 41 | return bin; 42 | } 43 | 44 | static unsigned int get_numeral_value(const std::string& numeralString) 45 | { 46 | const std::string prefix = numeralString.substr(0, 2); 47 | const std::string valueString = numeralString.substr(2); 48 | 49 | std::stringstream ss; 50 | unsigned int value; 51 | 52 | if (prefix == "#x") 53 | { 54 | ss << std::hex << valueString; 55 | ss >> value; 56 | } 57 | else if (prefix == "#b") 58 | { 59 | value = std::stoull(valueString, 0, 2); 60 | } 61 | else 62 | { 63 | std::cout << "Invalid BV prefix in: " << numeralString << std::endl; 64 | std::cout << "unknown" << std::endl; 65 | exit(1); 66 | } 67 | 68 | return value; 69 | } 70 | }; 71 | 72 | #endif // HEXHELPER_H 73 | -------------------------------------------------------------------------------- /lib/HashUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template <> 4 | struct std::hash 5 | { 6 | std::size_t operator()(const z3::expr& e) const 7 | { 8 | return e.hash(); 9 | } 10 | }; 11 | 12 | template <> 13 | struct std::equal_to 14 | { 15 | bool operator()(const z3::expr& lhs, const z3::expr& rhs) const 16 | { 17 | return lhs.id() == rhs.id(); 18 | } 19 | }; 20 | 21 | namespace 22 | { 23 | // Code from boost 24 | // Reciprocal of the golden ratio helps spread entropy 25 | // and handles duplicates. 26 | // See Mike Seymour in magic-numbers-in-boosthash-combine: 27 | // http://stackoverflow.com/questions/4948780 28 | 29 | template 30 | inline void hash_combine(std::size_t& seed, T const& v) 31 | { 32 | seed ^= std::hash()(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); 33 | } 34 | 35 | // Recursive template code derived from Matthieu M. 36 | template ::value - 1> 37 | struct HashValueImpl 38 | { 39 | static void apply(size_t& seed, Tuple const& tuple) 40 | { 41 | HashValueImpl::apply(seed, tuple); 42 | hash_combine(seed, std::get(tuple)); 43 | } 44 | }; 45 | 46 | template 47 | struct HashValueImpl 48 | { 49 | static void apply(size_t& seed, Tuple const& tuple) 50 | { 51 | hash_combine(seed, std::get<0>(tuple)); 52 | } 53 | }; 54 | } 55 | 56 | template 57 | struct std::hash> 58 | { 59 | size_t operator()(std::tuple const& tt) const 60 | { 61 | size_t seed = 0; 62 | HashValueImpl >::apply(seed, tt); 63 | return seed; 64 | } 65 | }; 66 | 67 | template 68 | struct std::hash> 69 | { 70 | size_t operator()(std::pair const& t) const 71 | { 72 | size_t seed = 0; 73 | hash_combine(seed, t.first); 74 | hash_combine(seed, t.second); 75 | return seed; 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /tests/data/smtcomp23/heapsort.i_0.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by the tool Ultimate Automizer [1,2] which implements 5 | an automata theoretic approach [3] to software verification. 6 | 7 | This SMT script belongs to a set of SMT scripts that was generated by 8 | applying Ultimate Automizer to benchmarks [4] from the SV-COMP 2023 [5,6]. 9 | This script may not contain all SMT commands that Ultimate Automizer 10 | issued. In order to meet the restrictions for SMT-COMP benchmarks 11 | we dropped the commands for getting values (resp. models), 12 | unsatisfiable cores, and interpolants. 13 | 14 | 2023-03-21, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 15 | 16 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 17 | [2] Matthias Heizmann, Max Barth, Daniel Dietsch, Leonard Fichtner, 18 | Jochen Hoenicke, Dominik Klumpp, Mehdi Naouar, Tanja Schindler, 19 | Frank Schüssele, Andreas Podelski: Ultimate Automizer and the 20 | CommuHash Normal Form (Competition Contribution). TACAS 2023 21 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 22 | Checking for People Who Love Automata. CAV 2013 23 | [4] https://github.com/sosy-lab/sv-benchmarks 24 | [5] Dirk Beyer: Competition on Software Verification and 25 | Witness Validation: SV-COMP 2023. TACAS 2023 26 | [6] https://sv-comp.sosy-lab.org/2023/ 27 | |) 28 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 29 | (set-info :category "industrial") 30 | (set-info :status unknown) 31 | (declare-fun |c_ULTIMATE.start_main_~l~0#1| () (_ BitVec 32)) 32 | (assert (and (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (= (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) |c_ULTIMATE.start_main_~l~0#1|) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)))) (bvsgt (bvadd |c_ULTIMATE.start_main_~l~0#1| (_ bv1 32)) (_ bv1 32)))) 33 | (assert (not (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (bvsle (_ bv1 32) |ULTIMATE.start_main_~n~0#1|) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)) (= (bvadd (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) (_ bv1 32)) |c_ULTIMATE.start_main_~l~0#1|))))) 34 | (check-sat) 35 | (exit) 36 | -------------------------------------------------------------------------------- /tests/data/Fibonacci01_true-unreach-call_true-no-overflow.c_905.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by the tool Ultimate Automizer [1,2] which implements 5 | an automata theoretic approach [3] to software verification. 6 | 7 | This SMT script belongs to a set of SMT scripts that was generated by 8 | applying Ultimate Automizer to benchmarks [4] from the SV-COMP 2017 [5,6]. 9 | 10 | This script might _not_ contain all SMT commands that are used by 11 | Ultimate Automizer. In order to satisfy the restrictions of 12 | the SMT-COMP we have to drop e.g., the commands for getting 13 | values (resp. models), unsatisfiable cores and interpolants. 14 | 15 | 2017-05-01, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 16 | 17 | 18 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 19 | [2] Matthias Heizmann, Yu-Wen Chen, Daniel Dietsch, Marius Greitschus, 20 | Alexander Nutz, Betim Musa, Claus Schätzle, Christian Schilling, 21 | Frank Schüssele, Andreas Podelski: 22 | Ultimate Automizer with an On-Demand Construction of Floyd-Hoare 23 | Automata - (Competition Contribution). TACAS (2) 2017: 394-398 24 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 25 | Checking for People Who Love Automata. CAV 2013:36-52 26 | [4] https://github.com/sosy-lab/sv-benchmarks 27 | [5] Dirk Beyer: Software Verification with Validation of Results - 28 | (Report on SV-COMP 2017). TACAS (2) 2017: 331-349 29 | [6] https://sv-comp.sosy-lab.org/2017/ 30 | |) 31 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 32 | (set-info :category "industrial") 33 | (set-info :status unknown) 34 | (declare-fun |c_fibonacci_#in~n| () (_ BitVec 32)) 35 | (declare-fun |c_fibonacci_#res| () (_ BitVec 32)) 36 | (declare-fun c_main_~x~7 () (_ BitVec 32)) 37 | (declare-fun c_main_~result~7 () (_ BitVec 32)) 38 | (assert (and (forall ((v_prenex_1 (_ BitVec 32))) (or (not (bvsge (_ bv1 32) (bvsub v_prenex_1 (_ bv1 32)))) (bvsge |c_fibonacci_#res| (bvsub v_prenex_1 (_ bv1 32))))) (or (= (_ bv1 32) |c_fibonacci_#in~n|) (forall ((|v_fibonacci_#in~n_BEFORE_CALL_2| (_ BitVec 32))) (bvsge |c_fibonacci_#res| (bvsub |v_fibonacci_#in~n_BEFORE_CALL_2| (_ bv1 32))))))) 39 | (assert (not (bvsge c_main_~result~7 (bvsub c_main_~x~7 (_ bv1 32))))) 40 | (check-sat) 41 | (exit) 42 | -------------------------------------------------------------------------------- /tests/data/smtcomp23/heapsort.i_3.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by the tool Ultimate Automizer [1,2] which implements 5 | an automata theoretic approach [3] to software verification. 6 | 7 | This SMT script belongs to a set of SMT scripts that was generated by 8 | applying Ultimate Automizer to benchmarks [4] from the SV-COMP 2023 [5,6]. 9 | This script may not contain all SMT commands that Ultimate Automizer 10 | issued. In order to meet the restrictions for SMT-COMP benchmarks 11 | we dropped the commands for getting values (resp. models), 12 | unsatisfiable cores, and interpolants. 13 | 14 | 2023-03-21, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 15 | 16 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 17 | [2] Matthias Heizmann, Max Barth, Daniel Dietsch, Leonard Fichtner, 18 | Jochen Hoenicke, Dominik Klumpp, Mehdi Naouar, Tanja Schindler, 19 | Frank Schüssele, Andreas Podelski: Ultimate Automizer and the 20 | CommuHash Normal Form (Competition Contribution). TACAS 2023 21 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 22 | Checking for People Who Love Automata. CAV 2013 23 | [4] https://github.com/sosy-lab/sv-benchmarks 24 | [5] Dirk Beyer: Competition on Software Verification and 25 | Witness Validation: SV-COMP 2023. TACAS 2023 26 | [6] https://sv-comp.sosy-lab.org/2023/ 27 | |) 28 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 29 | (set-info :category "industrial") 30 | (set-info :status unknown) 31 | (declare-fun |c_ULTIMATE.start_main_~l~0#1| () (_ BitVec 32)) 32 | (declare-fun |c_ULTIMATE.start_main_~l~0#1_primed| () (_ BitVec 32)) 33 | (assert (and (bvsgt |c_ULTIMATE.start_main_~l~0#1| (_ bv1 32)) (= |c_ULTIMATE.start_main_~l~0#1| (bvadd |c_ULTIMATE.start_main_~l~0#1_primed| (_ bv1 32))))) 34 | (assert (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (bvsle (_ bv1 32) |ULTIMATE.start_main_~n~0#1|) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)) (= (bvadd (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) (_ bv1 32)) |c_ULTIMATE.start_main_~l~0#1|)))) 35 | (assert (not (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (bvsle (_ bv1 32) |ULTIMATE.start_main_~n~0#1|) (= |c_ULTIMATE.start_main_~l~0#1_primed| (bvadd (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) (_ bv1 32))) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)))))) 36 | (check-sat) 37 | (exit) 38 | -------------------------------------------------------------------------------- /lib/SMTLIBInterpreter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Solver.h" 10 | #include "Model.h" 11 | 12 | #include "SMTLIBv2BaseVisitor.h" 13 | 14 | class SMTLIBInterpreter : public SMTLIBv2BaseVisitor 15 | { 16 | public: 17 | Result Run(SMTLIBv2Parser::ScriptContext*); 18 | 19 | virtual antlrcpp::Any visitCommand(SMTLIBv2Parser::CommandContext *ctx) override; 20 | virtual antlrcpp::Any visitSort(SMTLIBv2Parser::SortContext *ctx) override; 21 | virtual antlrcpp::Any visitTerm(SMTLIBv2Parser::TermContext *ctx) override; 22 | virtual antlrcpp::Any visitSorted_var(SMTLIBv2Parser::Sorted_varContext *ctx) override; 23 | virtual antlrcpp::Any visitVar_binding(SMTLIBv2Parser::Var_bindingContext *ctx) override; 24 | virtual antlrcpp::Any visitBinary(SMTLIBv2Parser::BinaryContext *ctx) override; 25 | virtual antlrcpp::Any visitHexadecimal(SMTLIBv2Parser::HexadecimalContext *ctx) override; 26 | virtual antlrcpp::Any visitFunction_def(SMTLIBv2Parser::Function_defContext *ctx) override; 27 | 28 | Model GetModel() const { return model; } 29 | 30 | void SetConfig(Config config) 31 | { 32 | this->config = config; 33 | } 34 | private: 35 | z3::context ctx; 36 | std::map constants; 37 | std::vector> variables; 38 | std::vector> variableBindings; 39 | std::map> funDefinitions; 40 | std::map sortDefinitions; 41 | 42 | void RunCommand(SMTLIBv2Parser::CommandContext*); 43 | 44 | void addConstant(const std::string&, const z3::sort&); 45 | z3::expr addVar(const std::string&, const z3::sort&); 46 | void addVarBinding(const std::string&, const z3::expr&); 47 | z3::expr getConstant(const std::string&) const; 48 | void addFunctionDefinition(const std::string&, const z3::expr_vector&, const z3::expr&); 49 | void addSortDefinition(const std::string&, const z3::sort&); 50 | bool isDefinedFunction(const std::string&); 51 | bool isDefinedSort(const std::string&); 52 | z3::expr applyDefinedFunction(const std::string&, const z3::expr_vector&); 53 | 54 | Result result = NORESULT; 55 | 56 | Config config; 57 | std::vector asserts; 58 | 59 | bool exited = false; 60 | bool printSuccess = false; 61 | 62 | Model model; 63 | }; 64 | -------------------------------------------------------------------------------- /tests/data/intersection-example-onelane.proof-node1469.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | These benchmarks used in the paper: 5 | 6 | Dejan Jovanovic and Leonardo de Moura. Solving Non-Linear Arithmetic. 7 | In IJCAR 2012, published as LNCS volume 7364, pp. 339--354. 8 | 9 | The keymaera family contains VCs from Keymaera verification, see: 10 | 11 | A. Platzer, J.-D. Quesel, and P. Rummer. Real world verification. 12 | In CADE 2009, pages 485-501. Springer, 2009. 13 | 14 | Submitted by Dejan Jovanovic for SMT-LIB. 15 | 16 | KeYmaera example: intersection-example-onelane.proof, node 1469 For more info see: @see "Sarah M. Loos and Andre Platzer. Safe intersections: At the crossing of hybrid systems and verification. In Kyongsu Yi, editor, 14th International IEEE Conference on Intelligent Transportation Systems, ITSC 2011, Washington, DC, USA, Proceedings. 2011." 17 | 18 | Translated to BV by Mathias Preiner. 19 | |) 20 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 21 | (set-info :category "industrial") 22 | (set-info :status unknown) 23 | (declare-fun xI () (_ BitVec 32)) 24 | (declare-fun xuscore2dollarskuscore0 () (_ BitVec 32)) 25 | (declare-fun ts0uscore0 () (_ BitVec 32)) 26 | (declare-fun vuscore2dollarskuscore0 () (_ BitVec 32)) 27 | (declare-fun A () (_ BitVec 32)) 28 | (declare-fun B () (_ BitVec 32)) 29 | (declare-fun t1uscore0dollarskuscore0 () (_ BitVec 32)) 30 | (declare-fun I1 () (_ BitVec 32)) 31 | (declare-fun v () (_ BitVec 32)) 32 | (declare-fun V () (_ BitVec 32)) 33 | (declare-fun ep () (_ BitVec 32)) 34 | (declare-fun I1uscore2dollarskuscore0 () (_ BitVec 32)) 35 | (declare-fun x () (_ BitVec 32)) 36 | (assert (not (exists ((ts0uscore0 (_ BitVec 32))) (let ((?v_0 (bvadd (bvmul A ts0uscore0) vuscore2dollarskuscore0))) (=> (and (and (and (and (and (and (and (and (and (and (and (and (and (=> (and (bvsle (_ bv0 32) ts0uscore0) (bvsle ts0uscore0 t1uscore0dollarskuscore0)) (and (and (bvsge ?v_0 (_ bv0 32)) (bvsle ?v_0 V)) (bvsle ts0uscore0 ep))) (bvsge t1uscore0dollarskuscore0 (_ bv0 32))) (= xI xuscore2dollarskuscore0)) (= I1uscore2dollarskuscore0 (_ bv0 32))) (bvsge vuscore2dollarskuscore0 (_ bv0 32))) (bvsle vuscore2dollarskuscore0 V)) (= I1 (_ bv2 32))) (bvslt xI x)) (bvsgt B (_ bv0 32))) (bvsge v (_ bv0 32))) (bvsle v V)) (bvsge A (_ bv0 32))) (bvsgt V (_ bv0 32))) (bvsgt ep (_ bv0 32))) (or (= I1uscore2dollarskuscore0 (_ bv2 32)) (bvsge (bvadd (bvmul A t1uscore0dollarskuscore0) vuscore2dollarskuscore0) (_ bv0 32)))))))) 37 | (check-sat) 38 | (exit) 39 | -------------------------------------------------------------------------------- /tests/data/ETCS-essentials-node3023.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | These benchmarks used in the paper: 5 | 6 | Dejan Jovanovic and Leonardo de Moura. Solving Non-Linear Arithmetic. 7 | In IJCAR 2012, published as LNCS volume 7364, pp. 339--354. 8 | 9 | The keymaera family contains VCs from Keymaera verification, see: 10 | 11 | A. Platzer, J.-D. Quesel, and P. Rummer. Real world verification. 12 | In CADE 2009, pages 485-501. Springer, 2009. 13 | 14 | Submitted by Dejan Jovanovic for SMT-LIB. 15 | 16 | KeYmaera example: ETCS-essentials, node 3023 For more info see: @see "Andre Platzer. Differential dynamic logic for hybrid systems. Journal of Automated Reasoning, 41(2), pages 143-189, 2008." 17 | 18 | Translated to BV by Mathias Preiner. 19 | |) 20 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 21 | (set-info :category "industrial") 22 | (set-info :status unknown) 23 | (declare-fun v () (_ BitVec 32)) 24 | (declare-fun vuscore2dollarskuscore0 () (_ BitVec 32)) 25 | (declare-fun b () (_ BitVec 32)) 26 | (declare-fun A () (_ BitVec 32)) 27 | (declare-fun t1uscore0dollarskuscore0 () (_ BitVec 32)) 28 | (declare-fun ep () (_ BitVec 32)) 29 | (declare-fun m () (_ BitVec 32)) 30 | (declare-fun zuscore2dollarskuscore0 () (_ BitVec 32)) 31 | (declare-fun ts1uscore0 () (_ BitVec 32)) 32 | (declare-fun z () (_ BitVec 32)) 33 | (assert (not (exists ((ts1uscore0 (_ BitVec 32))) (let ((?v_3 (bvneg b)) (?v_1 (bvmul (_ bv2 32) b)) (?v_0 (bvmul vuscore2dollarskuscore0 vuscore2dollarskuscore0)) (?v_2 (bvsub m zuscore2dollarskuscore0))) (let ((?v_4 (bvadd (bvmul ?v_3 t1uscore0dollarskuscore0) vuscore2dollarskuscore0))) (=> (and (and (and (and (and (and (=> (and (bvsle (_ bv0 32) ts1uscore0) (bvsle ts1uscore0 t1uscore0dollarskuscore0)) (and (bvsge (bvadd (bvmul ?v_3 ts1uscore0) vuscore2dollarskuscore0) (_ bv0 32)) (bvsle ts1uscore0 ep))) (bvsge t1uscore0dollarskuscore0 (_ bv0 32))) (bvsle ?v_2 (bvadd (bvsdiv ?v_0 ?v_1) (bvmul (bvadd (bvsdiv A b) (_ bv1 32)) (bvadd (bvmul (bvsdiv A (_ bv2 32)) (bvmul ep ep)) (bvmul ep vuscore2dollarskuscore0)))))) (bvsle ?v_0 (bvmul ?v_1 ?v_2))) (bvsle (bvmul v v) (bvmul ?v_1 (bvsub m z)))) (bvsgt b (_ bv0 32))) (bvsge A (_ bv0 32))) (bvsle (bvmul ?v_4 ?v_4) (bvmul ?v_1 (bvsub m (bvmul (bvsdiv (_ bv1 32) (_ bv2 32)) (bvadd (bvadd (bvmul ?v_3 (bvmul t1uscore0dollarskuscore0 t1uscore0dollarskuscore0)) (bvmul (bvmul (_ bv2 32) t1uscore0dollarskuscore0) vuscore2dollarskuscore0)) (bvmul (_ bv2 32) zuscore2dollarskuscore0)))))))))))) 34 | (check-sat) 35 | (exit) 36 | -------------------------------------------------------------------------------- /tests/data/smtcomp23/heapsort.i_9.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by the tool Ultimate Automizer [1,2] which implements 5 | an automata theoretic approach [3] to software verification. 6 | 7 | This SMT script belongs to a set of SMT scripts that was generated by 8 | applying Ultimate Automizer to benchmarks [4] from the SV-COMP 2023 [5,6]. 9 | This script may not contain all SMT commands that Ultimate Automizer 10 | issued. In order to meet the restrictions for SMT-COMP benchmarks 11 | we dropped the commands for getting values (resp. models), 12 | unsatisfiable cores, and interpolants. 13 | 14 | 2023-03-21, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 15 | 16 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 17 | [2] Matthias Heizmann, Max Barth, Daniel Dietsch, Leonard Fichtner, 18 | Jochen Hoenicke, Dominik Klumpp, Mehdi Naouar, Tanja Schindler, 19 | Frank Schüssele, Andreas Podelski: Ultimate Automizer and the 20 | CommuHash Normal Form (Competition Contribution). TACAS 2023 21 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 22 | Checking for People Who Love Automata. CAV 2013 23 | [4] https://github.com/sosy-lab/sv-benchmarks 24 | [5] Dirk Beyer: Competition on Software Verification and 25 | Witness Validation: SV-COMP 2023. TACAS 2023 26 | [6] https://sv-comp.sosy-lab.org/2023/ 27 | |) 28 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 29 | (set-info :category "industrial") 30 | (set-info :status unknown) 31 | (declare-fun |c_ULTIMATE.start_main_~l~0#1| () (_ BitVec 32)) 32 | (declare-fun |c_ULTIMATE.start_main_~j~0#1| () (_ BitVec 32)) 33 | (assert (and (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (let ((.cse0 (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)))) (and (= (bvmul (_ bv2 32) .cse0) |c_ULTIMATE.start_main_~j~0#1|) (bvsgt (bvadd .cse0 (_ bv1 32)) (_ bv1 32)) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32))))) (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (= (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) |c_ULTIMATE.start_main_~l~0#1|) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)))) (bvsgt (bvadd |c_ULTIMATE.start_main_~l~0#1| (_ bv1 32)) (_ bv1 32)))) 34 | (assert (not (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (bvsle (_ bv1 32) |ULTIMATE.start_main_~n~0#1|) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)) (= (bvadd (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) (_ bv1 32)) |c_ULTIMATE.start_main_~l~0#1|))))) 35 | (check-sat) 36 | (exit) 37 | -------------------------------------------------------------------------------- /tests/data/MADWiFi-encode_ie_ok_true-unreach-call.i_7.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info 4 | :source | 5 | SMT script generated by Ultimate Automizer [1,2]. 6 | Ultimate Automizer is an automatic software verification tool that implements 7 | a new automata-theoretic approach [3]. 8 | 9 | This SMT script belongs to a set of SMT scripts that was generated by applying 10 | Ultimate Automizer to benchmarks from the SV-COMP 2015 [4,5] which are available 11 | at [6]. 12 | 13 | This script does _not_ contain all SMT commands that are used by Ultimate 14 | Automizer while verifying a program. In order to fulfill the restrictions of 15 | the main track at SMT-COMP this script contains only the commands that are 16 | sufficient to reproduce one single satisfiablity check. 17 | 18 | 2015-04-30, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 19 | 20 | 21 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 22 | [2] Matthias Heizmann, Daniel Dietsch, Jan Leike, Betim Musa, Andreas Podelski: 23 | Ultimate Automizer with Array Interpolation - (Competition Contribution). 24 | TACAS 2015: 455-457 25 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 26 | Checking for People Who Love Automata. CAV 2013:36-52 27 | [4] Dirk Beyer: Software Verification and Verifiable Witnesses - (Report on 28 | SV-COMP 2015). TACAS 2015: 401-416 29 | [5] http://sv-comp.sosy-lab.org/2015/ 30 | [6] https://svn.sosy-lab.org/software/sv-benchmarks/tags/svcomp15/ 31 | 32 | 33 | Made compatible to SMT-COMP rules by SMTInterpol 34 | 35 | Translated to BV by Mathias Preiner. 36 | |) 37 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 38 | (set-info :category "industrial") 39 | (set-info :status unsat) 40 | (declare-fun c_main_~p~6 () (_ BitVec 32)) 41 | (declare-fun c_main_~i~6 () (_ BitVec 32)) 42 | (declare-fun c_main_~bufsize_0~6 () (_ BitVec 32)) 43 | (declare-fun c_main_~ielen~6 () (_ BitVec 32)) 44 | (assert 45 | (and (bvslt c_main_~i~6 c_main_~ielen~6) 46 | (bvsle (_ bv3 32) c_main_~i~6) 47 | (bvsle (bvadd (bvmul (_ bv2 32) c_main_~ielen~6) c_main_~p~6) (bvadd c_main_~bufsize_0~6 (_ bv6 32))))) 48 | (assert 49 | (not 50 | (and (bvsle (bvadd (bvmul (_ bv2 32) c_main_~ielen~6) c_main_~p~6) (bvadd c_main_~bufsize_0~6 (_ bv6 32))) 51 | (bvsle (_ bv2 32) c_main_~i~6) 52 | (exists ((main_~ielen~6 (_ BitVec 32))) 53 | (and (bvsle (_ bv4 32) main_~ielen~6) 54 | (bvsle (bvadd (bvmul (_ bv2 32) main_~ielen~6) c_main_~p~6) (bvadd c_main_~bufsize_0~6 (_ bv6 32))))) 55 | (bvsle (_ bv3 32) c_main_~i~6)))) 56 | (check-sat) 57 | (exit) 58 | 59 | -------------------------------------------------------------------------------- /tests/data/smtcomp23/heapsort.i_8.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by the tool Ultimate Automizer [1,2] which implements 5 | an automata theoretic approach [3] to software verification. 6 | 7 | This SMT script belongs to a set of SMT scripts that was generated by 8 | applying Ultimate Automizer to benchmarks [4] from the SV-COMP 2023 [5,6]. 9 | This script may not contain all SMT commands that Ultimate Automizer 10 | issued. In order to meet the restrictions for SMT-COMP benchmarks 11 | we dropped the commands for getting values (resp. models), 12 | unsatisfiable cores, and interpolants. 13 | 14 | 2023-03-21, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 15 | 16 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 17 | [2] Matthias Heizmann, Max Barth, Daniel Dietsch, Leonard Fichtner, 18 | Jochen Hoenicke, Dominik Klumpp, Mehdi Naouar, Tanja Schindler, 19 | Frank Schüssele, Andreas Podelski: Ultimate Automizer and the 20 | CommuHash Normal Form (Competition Contribution). TACAS 2023 21 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 22 | Checking for People Who Love Automata. CAV 2013 23 | [4] https://github.com/sosy-lab/sv-benchmarks 24 | [5] Dirk Beyer: Competition on Software Verification and 25 | Witness Validation: SV-COMP 2023. TACAS 2023 26 | [6] https://sv-comp.sosy-lab.org/2023/ 27 | |) 28 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 29 | (set-info :category "industrial") 30 | (set-info :status unknown) 31 | (declare-fun |c_ULTIMATE.start_main_~l~0#1| () (_ BitVec 32)) 32 | (declare-fun |c_ULTIMATE.start_main_~r~0#1| () (_ BitVec 32)) 33 | (declare-fun |c_ULTIMATE.start_main_~i~0#1_primed| () (_ BitVec 32)) 34 | (declare-fun |c_ULTIMATE.start_main_~j~0#1_primed| () (_ BitVec 32)) 35 | (assert (and (= |c_ULTIMATE.start_main_~i~0#1_primed| |c_ULTIMATE.start_main_~l~0#1|) (bvsgt |c_ULTIMATE.start_main_~r~0#1| (_ bv1 32)) (= (bvmul (_ bv2 32) |c_ULTIMATE.start_main_~l~0#1|) |c_ULTIMATE.start_main_~j~0#1_primed|))) 36 | (assert (and (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (= (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) |c_ULTIMATE.start_main_~l~0#1|) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)))) (bvsgt (bvadd |c_ULTIMATE.start_main_~l~0#1| (_ bv1 32)) (_ bv1 32)))) 37 | (assert (not (exists ((|ULTIMATE.start_main_~n~0#1| (_ BitVec 32))) (and (bvsle (_ bv1 32) |ULTIMATE.start_main_~n~0#1|) (= |c_ULTIMATE.start_main_~l~0#1| (bvadd (bvsdiv |ULTIMATE.start_main_~n~0#1| (_ bv2 32)) (_ bv1 32))) (bvsle |ULTIMATE.start_main_~n~0#1| (_ bv1000000 32)))))) 38 | (check-sat) 39 | (exit) 40 | -------------------------------------------------------------------------------- /lib/maybeBdd/maybeBdd.cpp: -------------------------------------------------------------------------------- 1 | #include "maybeBdd.h" 2 | #include "../Solver.h" 3 | 4 | bool MaybeBDD::approximationHappened = false; 5 | 6 | MaybeBDD MaybeBDD::And(const MaybeBDD &other) const 7 | { 8 | if (Solver::resultComputed) return MaybeBDD(); 9 | if (this->HasValue() && other.HasValue()) 10 | { 11 | return MaybeBDD(GetBDD() & other.GetBDD()); 12 | } 13 | 14 | if (this->HasValue() && this->GetBDD().IsZero()) 15 | { 16 | return *this; 17 | } 18 | 19 | if (other.HasValue() && other.GetBDD().IsZero()) 20 | { 21 | return other; 22 | } 23 | 24 | return MaybeBDD(); 25 | } 26 | 27 | MaybeBDD MaybeBDD::Or(const MaybeBDD &other) const 28 | { 29 | if (Solver::resultComputed) return MaybeBDD(); 30 | if (this->HasValue() && other.HasValue()) 31 | { 32 | return MaybeBDD(GetBDD() | other.GetBDD()); 33 | } 34 | 35 | if (this->HasValue() && this->GetBDD().IsOne()) 36 | { 37 | return *this; 38 | } 39 | 40 | if (other.HasValue() && other.GetBDD().IsOne()) 41 | { 42 | return other; 43 | } 44 | 45 | return MaybeBDD(); 46 | } 47 | 48 | MaybeBDD MaybeBDD::Xor(const MaybeBDD &other) const 49 | { 50 | if (Solver::resultComputed) return MaybeBDD(); 51 | if (this->HasValue() && other.HasValue()) 52 | { 53 | return MaybeBDD(GetBDD() ^ other.GetBDD()); 54 | } 55 | 56 | return MaybeBDD(); 57 | } 58 | 59 | MaybeBDD MaybeBDD::Xnor(const MaybeBDD &other) const 60 | { 61 | if (Solver::resultComputed) return MaybeBDD(); 62 | if (this->HasValue() && other.HasValue()) 63 | { 64 | return MaybeBDD(GetBDD().Xnor(other.GetBDD())); 65 | } 66 | 67 | return MaybeBDD(); 68 | } 69 | 70 | MaybeBDD MaybeBDD::Not() const 71 | { 72 | if (Solver::resultComputed) return MaybeBDD(); 73 | if (this->HasValue()) 74 | { 75 | return MaybeBDD(!GetBDD()); 76 | } 77 | 78 | return MaybeBDD(); 79 | } 80 | 81 | MaybeBDD MaybeBDD::Ite(const MaybeBDD &thenBdd, const MaybeBDD &elseBdd) const 82 | { 83 | if (Solver::resultComputed) return MaybeBDD(); 84 | if (thenBdd.Equals(elseBdd)) 85 | { 86 | return thenBdd; 87 | } 88 | 89 | if (this->HasValue() && thenBdd.HasValue() && elseBdd.HasValue()) 90 | { 91 | return MaybeBDD(this->GetBDD().Ite(thenBdd.GetBDD(), elseBdd.GetBDD())); 92 | } 93 | 94 | if (this->HasValue() && this->GetBDD().IsOne()) 95 | { 96 | return thenBdd; 97 | } 98 | 99 | if (this->HasValue() && this->GetBDD().IsZero()) 100 | { 101 | return elseBdd; 102 | } 103 | 104 | return MaybeBDD(); 105 | } 106 | -------------------------------------------------------------------------------- /tests/data/accelerating-node2100.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | These benchmarks used in the paper: 5 | 6 | Dejan Jovanovic and Leonardo de Moura. Solving Non-Linear Arithmetic. 7 | In IJCAR 2012, published as LNCS volume 7364, pp. 339--354. 8 | 9 | The keymaera family contains VCs from Keymaera verification, see: 10 | 11 | A. Platzer, J.-D. Quesel, and P. Rummer. Real world verification. 12 | In CADE 2009, pages 485-501. Springer, 2009. 13 | 14 | Submitted by Dejan Jovanovic for SMT-LIB. 15 | 16 | KeYmaera example: accelerating, node 2100 For more info see: @see @see "Andre Platzer and Jan-David Quesel. European Train Control System: A case study in formal verification. In Karin Breitman and Ana Cavalcanti, editors, 11th International Conference on Formal Engineering Methods, ICFEM, Rio de Janeiro, Brasil, Proceedings, volume 5885 of LNCS, pages 246-265. Springer, 2009." 17 | 18 | Translated to BV by Mathias Preiner. 19 | |) 20 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 21 | (set-info :category "industrial") 22 | (set-info :status unknown) 23 | (declare-fun v () (_ BitVec 32)) 24 | (declare-fun b () (_ BitVec 32)) 25 | (declare-fun vuscore2dollarskuscore0 () (_ BitVec 32)) 26 | (declare-fun A () (_ BitVec 32)) 27 | (declare-fun ts2uscore0 () (_ BitVec 32)) 28 | (declare-fun ep () (_ BitVec 32)) 29 | (declare-fun m () (_ BitVec 32)) 30 | (declare-fun zuscore2dollarskuscore0 () (_ BitVec 32)) 31 | (declare-fun t2uscore0dollarskuscore0 () (_ BitVec 32)) 32 | (declare-fun z () (_ BitVec 32)) 33 | (assert (not (exists ((ts2uscore0 (_ BitVec 32))) (let ((?v_1 (bvmul (_ bv2 32) b)) (?v_0 (bvmul vuscore2dollarskuscore0 vuscore2dollarskuscore0)) (?v_2 (bvsub m zuscore2dollarskuscore0)) (?v_3 (bvadd (bvmul A t2uscore0dollarskuscore0) vuscore2dollarskuscore0))) (=> (and (and (and (and (and (and (=> (and (bvsle (_ bv0 32) ts2uscore0) (bvsle ts2uscore0 t2uscore0dollarskuscore0)) (and (bvsge (bvadd (bvmul A ts2uscore0) vuscore2dollarskuscore0) (_ bv0 32)) (bvsle ts2uscore0 ep))) (bvsge t2uscore0dollarskuscore0 (_ bv0 32))) (bvsge ?v_2 (bvadd (bvsdiv ?v_0 ?v_1) (bvmul (bvadd (bvsdiv A b) (_ bv1 32)) (bvadd (bvmul (bvsdiv A (_ bv2 32)) (bvmul ep ep)) (bvmul ep vuscore2dollarskuscore0)))))) (bvsle ?v_0 (bvmul ?v_1 ?v_2))) (bvsle (bvmul v v) (bvmul ?v_1 (bvsub m z)))) (bvsgt b (_ bv0 32))) (bvsge A (_ bv0 32))) (bvsle (bvmul ?v_3 ?v_3) (bvmul ?v_1 (bvsub m (bvmul (bvsdiv (_ bv1 32) (_ bv2 32)) (bvadd (bvadd (bvmul A (bvmul t2uscore0dollarskuscore0 t2uscore0dollarskuscore0)) (bvmul (bvmul (_ bv2 32) t2uscore0dollarskuscore0) vuscore2dollarskuscore0)) (bvmul (_ bv2 32) zuscore2dollarskuscore0))))))))))) 34 | (check-sat) 35 | (exit) 36 | -------------------------------------------------------------------------------- /tests/data/jain_7_true-unreach-call_true-no-overflow.i_61.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by the tool Ultimate Automizer [1,2] which implements 5 | an automata theoretic approach [3] to software verification. 6 | 7 | This SMT script belongs to a set of SMT scripts that was generated by 8 | applying Ultimate Automizer to benchmarks [4] from the SV-COMP 2017 [5,6]. 9 | 10 | This script might _not_ contain all SMT commands that are used by 11 | Ultimate Automizer. In order to satisfy the restrictions of 12 | the SMT-COMP we have to drop e.g., the commands for getting 13 | values (resp. models), unsatisfiable cores and interpolants. 14 | 15 | 2017-05-01, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 16 | 17 | 18 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 19 | [2] Matthias Heizmann, Yu-Wen Chen, Daniel Dietsch, Marius Greitschus, 20 | Alexander Nutz, Betim Musa, Claus Schätzle, Christian Schilling, 21 | Frank Schüssele, Andreas Podelski: 22 | Ultimate Automizer with an On-Demand Construction of Floyd-Hoare 23 | Automata - (Competition Contribution). TACAS (2) 2017: 394-398 24 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 25 | Checking for People Who Love Automata. CAV 2013:36-52 26 | [4] https://github.com/sosy-lab/sv-benchmarks 27 | [5] Dirk Beyer: Software Verification with Validation of Results - 28 | (Report on SV-COMP 2017). TACAS (2) 2017: 331-349 29 | [6] https://sv-comp.sosy-lab.org/2017/ 30 | |) 31 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 32 | (set-info :category "industrial") 33 | (set-info :status unknown) 34 | (declare-fun c_main_~x~5 () (_ BitVec 32)) 35 | (declare-fun c_main_~y~5 () (_ BitVec 32)) 36 | (declare-fun c_main_~z~5 () (_ BitVec 32)) 37 | (assert (forall ((|main_#t~nondet0| (_ BitVec 32)) (|main_#t~nondet2| (_ BitVec 32)) (|main_#t~nondet1| (_ BitVec 32))) (distinct (bvadd (bvmul (_ bv2 32) c_main_~y~5) (bvmul (_ bv4290772992 32) |main_#t~nondet0|) (bvmul (_ bv4294967292 32) c_main_~x~5) (bvmul (_ bv4194304 32) |main_#t~nondet1|) (_ bv1048576 32)) (bvadd c_main_~z~5 (bvmul (_ bv4194304 32) |main_#t~nondet2|))))) 38 | (assert (not (and (forall ((|main_#t~nondet0| (_ BitVec 32)) (|main_#t~nondet2| (_ BitVec 32)) (|main_#t~nondet1| (_ BitVec 32))) (distinct (bvadd (bvmul (_ bv2 32) c_main_~y~5) (bvmul (_ bv4290772992 32) |main_#t~nondet0|) (bvmul (_ bv4294967292 32) c_main_~x~5) (bvmul (_ bv4194304 32) |main_#t~nondet1|) (_ bv1048576 32)) (bvadd c_main_~z~5 (bvmul (_ bv4194304 32) |main_#t~nondet2|)))) (distinct (bvadd c_main_~z~5 (bvmul (_ bv4294967294 32) c_main_~y~5) (bvmul (_ bv4 32) c_main_~x~5) (_ bv4293918720 32)) (_ bv0 32))))) 39 | (check-sat) 40 | (exit) 41 | -------------------------------------------------------------------------------- /tests/data/magnetic_field-node118398.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | These benchmarks used in the paper: 5 | 6 | Dejan Jovanovic and Leonardo de Moura. Solving Non-Linear Arithmetic. 7 | In IJCAR 2012, published as LNCS volume 7364, pp. 339--354. 8 | 9 | The keymaera family contains VCs from Keymaera verification, see: 10 | 11 | A. Platzer, J.-D. Quesel, and P. Rummer. Real world verification. 12 | In CADE 2009, pages 485-501. Springer, 2009. 13 | 14 | Submitted by Dejan Jovanovic for SMT-LIB. 15 | 16 | KeYmaera example: magnetic_field, node 118398 For more info see: @see "Sriram Sankaranarayanan, Henny B. Sima, Zohar Manna: Constructing invariants for hybrid systems" 17 | 18 | Translated to BV by Mathias Preiner. 19 | |) 20 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 21 | (set-info :category "industrial") 22 | (set-info :status unknown) 23 | (declare-fun stateuscore2dollarskuscore35 () (_ BitVec 32)) 24 | (declare-fun b () (_ BitVec 32)) 25 | (declare-fun ts17uscore0 () (_ BitVec 32)) 26 | (declare-fun a () (_ BitVec 32)) 27 | (declare-fun vyuscore2dollarskuscore27 () (_ BitVec 32)) 28 | (declare-fun t17uscore0dollarskuscore0 () (_ BitVec 32)) 29 | (declare-fun vy () (_ BitVec 32)) 30 | (declare-fun vx () (_ BitVec 32)) 31 | (declare-fun yuscore2dollarskuscore21 () (_ BitVec 32)) 32 | (declare-fun xuscore2dollarskuscore22 () (_ BitVec 32)) 33 | (declare-fun vxuscore2dollarskuscore26 () (_ BitVec 32)) 34 | (declare-fun buscore2dollarskuscore35 () (_ BitVec 32)) 35 | (declare-fun y () (_ BitVec 32)) 36 | (declare-fun x () (_ BitVec 32)) 37 | (assert (not (exists ((ts17uscore0 (_ BitVec 32))) (let ((?v_0 (bvadd vyuscore2dollarskuscore27 (_ bv2 32)))) (=> (and (and (and (and (and (and (and (and (and (and (and (= ?v_0 (bvmul a (bvsub (bvadd (bvmul t17uscore0dollarskuscore0 vxuscore2dollarskuscore26) xuscore2dollarskuscore22) (_ bv2 32)))) (= (bvadd (bvmul vxuscore2dollarskuscore26 vxuscore2dollarskuscore26) (bvmul vyuscore2dollarskuscore27 vyuscore2dollarskuscore27)) (_ bv8 32))) (= (bvsub vxuscore2dollarskuscore26 (_ bv2 32)) (bvadd (bvmul (bvneg a) (bvadd (bvadd (bvmul t17uscore0dollarskuscore0 vyuscore2dollarskuscore27) yuscore2dollarskuscore21) (_ bv2 32))) (bvmul (bvmul (_ bv4 32) buscore2dollarskuscore35) (bvsub (_ bv1 32) a))))) (= stateuscore2dollarskuscore35 (_ bv1 32))) (=> (and (bvsle (_ bv0 32) ts17uscore0) (bvsle ts17uscore0 t17uscore0dollarskuscore0)) (bvsle vxuscore2dollarskuscore26 (_ bv0 32)))) (bvsge t17uscore0dollarskuscore0 (_ bv0 32))) (= stateuscore2dollarskuscore35 (_ bv2 32))) (= vx (_ bv2 32))) (= vy (bvneg (_ bv2 32)))) (= x (_ bv0 32))) (= y (_ bv0 32))) (= b (_ bv0 32))) (or (or (= stateuscore2dollarskuscore35 (_ bv0 32)) (= ?v_0 (bvmul a (bvsub xuscore2dollarskuscore22 (_ bv2 32))))) (= ?v_0 (_ bv0 32)))))))) 38 | (check-sat) 39 | (exit) 40 | -------------------------------------------------------------------------------- /lib/Model.cpp: -------------------------------------------------------------------------------- 1 | #include "Model.h" 2 | 3 | #include 4 | #include 5 | 6 | 7 | z3::expr substituteModel(z3::expr e, const Model& model) 8 | { 9 | auto &context = e.ctx(); 10 | z3::expr_vector consts(context); 11 | z3::expr_vector vals(context); 12 | 13 | for (auto &[varName, modelValue] : model) 14 | { 15 | if (std::holds_alternative(modelValue)) 16 | { 17 | consts.push_back(context.bool_const(varName.c_str())); 18 | vals.push_back(context.bool_val(std::get(modelValue))); 19 | continue; 20 | } 21 | 22 | auto bv = std::get>(modelValue); 23 | auto bitwidth = bv.size(); 24 | z3::expr c = context.bv_const(varName.c_str(), bitwidth); 25 | 26 | std::stringstream ss; 27 | for (auto bit : bv) 28 | { 29 | ss << bit; 30 | } 31 | 32 | unsigned long long value = 0; 33 | if (bitwidth <= 8 * sizeof(unsigned long long)) 34 | { 35 | value = stoull(ss.str(), 0, 2); 36 | } 37 | 38 | consts.push_back(c); 39 | vals.push_back(context.bv_val(static_cast(value), bitwidth)); 40 | } 41 | 42 | return e.substitute(consts, vals).simplify(); 43 | } 44 | 45 | std::variant vectorFromNumeral(z3::expr e) 46 | { 47 | if (e.is_false()) { 48 | return false; 49 | } 50 | if (e.is_true()) { 51 | return true; 52 | } 53 | 54 | std::string binary; 55 | if (!e.as_binary(binary)) { 56 | std::cerr << "Error during conversion from value to bit-vector." << std::endl; 57 | exit(1); 58 | } 59 | 60 | std::vector result; 61 | const auto bitWidth = static_cast(e.get_sort().is_bool() ? 1 : e.get_sort().bv_size()); 62 | const auto binarySize = binary.size(); 63 | 64 | for (size_t i = 0; i < bitWidth - binarySize; ++i) 65 | { 66 | result.push_back(false); 67 | } 68 | 69 | for (const char bit : binary) 70 | { 71 | assert(bit == '0' || bit == '1'); 72 | result.push_back(bit == '1'); 73 | } 74 | 75 | return result; 76 | } 77 | 78 | void printModelValue(std::string_view name, bool b) { 79 | std::cout << " (define-fun " << name << " () bool\n"; 80 | std::cout << " " << (b ? "true" : "false") << "\n"; 81 | std::cout << " )\n"; 82 | 83 | } 84 | 85 | void printModelValue(std::string_view name, const BitVector &bv) { 86 | std::cout << " (define-fun " << name << " () (_ BitVec " << bv.size() << ")\n"; 87 | std::cout << " #b"; 88 | for (const auto& bit : bv) 89 | { 90 | std::cout << bit; 91 | } 92 | 93 | std::cout << " )\n"; 94 | } 95 | 96 | void printModel(const Model& model) 97 | { 98 | std::cout << "(model " << std::endl; 99 | for (const auto& [var, val] : model) 100 | { 101 | std::visit([&](auto&& arg) { printModelValue(var, arg); }, val); 102 | } 103 | std::cout << ")" << std::endl; 104 | } 105 | -------------------------------------------------------------------------------- /tests/data/binary_driver-2007-10-09-node11383.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | These benchmarks used in the paper: 5 | 6 | Dejan Jovanovic and Leonardo de Moura. Solving Non-Linear Arithmetic. 7 | In IJCAR 2012, published as LNCS volume 7364, pp. 339--354. 8 | 9 | The keymaera family contains VCs from Keymaera verification, see: 10 | 11 | A. Platzer, J.-D. Quesel, and P. Rummer. Real world verification. 12 | In CADE 2009, pages 485-501. Springer, 2009. 13 | 14 | Submitted by Dejan Jovanovic for SMT-LIB. 15 | 16 | KeYmaera example: binary_driver-2007-10-09, node 11383 For more info see: No further information available. 17 | 18 | Translated to BV by Mathias Preiner. 19 | |) 20 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 21 | (set-info :category "industrial") 22 | (set-info :status unknown) 23 | (declare-fun ts4uscore0 () (_ BitVec 32)) 24 | (declare-fun vuscore2dollarskuscore5 () (_ BitVec 32)) 25 | (declare-fun duscore2dollarskuscore5 () (_ BitVec 32)) 26 | (declare-fun d () (_ BitVec 32)) 27 | (declare-fun b () (_ BitVec 32)) 28 | (declare-fun vdesuscore2dollarskuscore4 () (_ BitVec 32)) 29 | (declare-fun stateuscore2dollarskuscore2 () (_ BitVec 32)) 30 | (declare-fun m () (_ BitVec 32)) 31 | (declare-fun zuscore2dollarskuscore5 () (_ BitVec 32)) 32 | (declare-fun v () (_ BitVec 32)) 33 | (declare-fun ep () (_ BitVec 32)) 34 | (declare-fun muscore2dollarskuscore5 () (_ BitVec 32)) 35 | (declare-fun t4uscore0dollarskuscore0 () (_ BitVec 32)) 36 | (declare-fun z () (_ BitVec 32)) 37 | (declare-fun amax () (_ BitVec 32)) 38 | (assert (not (exists ((ts4uscore0 (_ BitVec 32))) (let ((?v_1 (bvneg b)) (?v_0 (bvmul (_ bv2 32) b)) (?v_3 (bvmul duscore2dollarskuscore5 duscore2dollarskuscore5))) (let ((?v_2 (bvadd (bvmul ?v_1 t4uscore0dollarskuscore0) vuscore2dollarskuscore5))) (=> (and (and (and (and (and (and (and (and (and (and (and (and (=> (and (bvsle (_ bv0 32) ts4uscore0) (bvsle ts4uscore0 t4uscore0dollarskuscore0)) (and (bvsge (bvadd (bvmul ?v_1 ts4uscore0) vuscore2dollarskuscore5) (_ bv0 32)) (bvsle ts4uscore0 ep))) (bvsge t4uscore0dollarskuscore0 (_ bv0 32))) (= stateuscore2dollarskuscore2 (_ bv1 32))) (bvsge vuscore2dollarskuscore5 vdesuscore2dollarskuscore4)) (bvsle (bvsub (bvmul vuscore2dollarskuscore5 vuscore2dollarskuscore5) ?v_3) (bvmul ?v_0 (bvsub muscore2dollarskuscore5 zuscore2dollarskuscore5)))) (bvsge vuscore2dollarskuscore5 (_ bv0 32))) (bvsge duscore2dollarskuscore5 (_ bv0 32))) (bvsle (bvsub (bvmul v v) (bvmul d d)) (bvmul ?v_0 (bvsub m z)))) (bvsge v (_ bv0 32))) (bvsgt ep (_ bv0 32))) (bvsgt b (_ bv0 32))) (bvsgt amax (_ bv0 32))) (bvsge d (_ bv0 32))) (bvsle (bvsub (bvmul ?v_2 ?v_2) ?v_3) (bvmul ?v_0 (bvsub muscore2dollarskuscore5 (bvmul (bvsdiv (_ bv1 32) (_ bv2 32)) (bvadd (bvadd (bvmul ?v_1 (bvmul t4uscore0dollarskuscore0 t4uscore0dollarskuscore0)) (bvmul (bvmul (_ bv2 32) t4uscore0dollarskuscore0) vuscore2dollarskuscore5)) (bvmul (_ bv2 32) zuscore2dollarskuscore5)))))))))))) 39 | (check-sat) 40 | (exit) 41 | -------------------------------------------------------------------------------- /lib/BDDInterval.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "cudd.h" 5 | #include 6 | 7 | class BDDInterval 8 | { 9 | private: 10 | bool isInterrupted() const; 11 | 12 | public: 13 | BDD upper; 14 | BDD lower; 15 | 16 | BDDInterval() = default; 17 | BDDInterval(const BDDInterval&) = default; 18 | BDDInterval& operator = (const BDDInterval&) = default; 19 | 20 | BDDInterval(BDD bdd) : 21 | upper(bdd), lower(bdd) 22 | { } 23 | 24 | BDDInterval(BDD upper, BDD lower) : 25 | upper(upper), lower(lower) 26 | { } 27 | 28 | BDDInterval operator & (const BDDInterval& rhs) 29 | { 30 | if (isInterrupted()) return *this; 31 | if (IsPrecise() && rhs.IsPrecise()) 32 | { 33 | return BDDInterval{upper & rhs.upper}; 34 | } 35 | 36 | return BDDInterval{upper & rhs.upper, lower & rhs.lower}; 37 | } 38 | 39 | BDDInterval operator * (const BDDInterval& rhs) 40 | { 41 | return *this & rhs; 42 | } 43 | 44 | BDDInterval operator | (const BDDInterval& rhs) 45 | { 46 | if (isInterrupted()) return *this; 47 | if (IsPrecise() && rhs.IsPrecise()) 48 | { 49 | return BDDInterval{upper | rhs.upper}; 50 | } 51 | 52 | return BDDInterval{upper | rhs.upper, lower | rhs.lower}; 53 | } 54 | 55 | BDDInterval operator + (const BDDInterval& rhs) 56 | { 57 | return *this | rhs; 58 | } 59 | 60 | BDDInterval operator ! () 61 | { 62 | if (isInterrupted()) return *this; 63 | if (IsPrecise()) 64 | { 65 | return BDDInterval{!upper}; 66 | } 67 | 68 | return BDDInterval{!upper, !lower}; 69 | } 70 | 71 | BDDInterval Xnor (const BDDInterval& rhs) const 72 | { 73 | if (isInterrupted()) return *this; 74 | if (IsPrecise() && rhs.IsPrecise()) 75 | { 76 | return BDDInterval{upper.Xnor(rhs.upper)}; 77 | } 78 | 79 | return BDDInterval{upper.Xnor(rhs.upper), lower.Xnor(rhs.lower)}; 80 | } 81 | 82 | BDDInterval Ite (const BDDInterval& t, const BDDInterval& e) const 83 | { 84 | if (isInterrupted()) return *this; 85 | if (IsPrecise() && t.IsPrecise() && e.IsPrecise()) 86 | { 87 | return BDDInterval{upper.Ite(t.upper, e.upper)}; 88 | } 89 | 90 | return BDDInterval{upper.Ite(t.upper, e.upper), lower.Ite(t.lower, e.lower)}; 91 | } 92 | 93 | BDDInterval UnivAbstract(const BDD& variables) 94 | { 95 | if (isInterrupted()) return *this; 96 | if (IsPrecise()) 97 | { 98 | return BDDInterval{upper.UnivAbstract(variables)}; 99 | } 100 | 101 | return BDDInterval{upper.UnivAbstract(variables), lower.UnivAbstract(variables)}; 102 | } 103 | 104 | BDDInterval ExistAbstract(const BDD& variables) 105 | { 106 | if (isInterrupted()) return *this; 107 | if (IsPrecise()) 108 | { 109 | return BDDInterval{upper.ExistAbstract(variables)}; 110 | } 111 | 112 | return BDDInterval{upper.ExistAbstract(variables), lower.ExistAbstract(variables)}; 113 | } 114 | 115 | bool IsPrecise() const 116 | { 117 | return upper == lower; 118 | } 119 | }; 120 | -------------------------------------------------------------------------------- /lib/ExprSimplifier.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPRSIMPLIFIER_H 2 | #define EXPRSIMPLIFIER_H 3 | #include "z3++.h" 4 | #include 5 | #include 6 | #include 7 | 8 | #include "SimplificationPass.h" 9 | #include "Model.h" 10 | #include "HashUtils.h" 11 | 12 | class ExprSimplifier 13 | { 14 | public: 15 | ExprSimplifier(z3::context &ctx) : 16 | propagateUnconstrained(false), 17 | goalUnconstrained(false) 18 | { 19 | this->context = &ctx; 20 | } 21 | 22 | ExprSimplifier(z3::context &ctx, bool propagateUnconstrained) : 23 | propagateUnconstrained(propagateUnconstrained), 24 | goalUnconstrained(false) 25 | { 26 | this->context = &ctx; 27 | } 28 | 29 | ExprSimplifier(z3::context &ctx, bool propagateUnconstrained, bool goalUnconstrained) : 30 | propagateUnconstrained(propagateUnconstrained), 31 | goalUnconstrained(goalUnconstrained) 32 | { 33 | this->context = &ctx; 34 | } 35 | 36 | z3::expr Simplify (z3::expr); 37 | z3::expr PushQuantifierIrrelevantSubformulas(const z3::expr&); 38 | z3::expr RefinedPushQuantifierIrrelevantSubformulas(const z3::expr&); 39 | z3::expr negate(const z3::expr&); 40 | bool isSentence(const z3::expr&); 41 | z3::expr PushNegations(const z3::expr&); 42 | z3::expr CanonizeBoundVariables(const z3::expr&); 43 | z3::expr DeCanonizeBoundVariables(const z3::expr&); 44 | z3::expr StripToplevelExistentials(const z3::expr&); 45 | z3::expr ReduceDivRem(const z3::expr&); 46 | 47 | void SetProduceModels(const bool value) 48 | { 49 | produceModels = value; 50 | } 51 | 52 | void ReconstructModel(Model &model); 53 | 54 | private: 55 | enum BoundType { EXISTENTIAL, UNIVERSAL }; 56 | 57 | struct Var 58 | { 59 | std::string name; 60 | BoundType boundType; 61 | z3::expr expr; 62 | 63 | Var(std::string name, BoundType boundType, z3::expr e) : 64 | name(name), boundType(boundType), expr(e) 65 | { } 66 | }; 67 | 68 | std::map refinedPushIrrelevantCache; 69 | std::unordered_map pushIrrelevantCache; 70 | std::unordered_map, z3::expr> decreaseDeBruijnCache; 71 | std::unordered_map, bool> isRelevantCache; 72 | std::unordered_map pushNegationsCache; 73 | std::unordered_map canonizeVariableRenaming; 74 | std::unordered_map isSentenceCache; 75 | std::unordered_map reduceDivRemCache; 76 | void clearCaches(); 77 | 78 | z3::context* context; 79 | z3::expr decreaseDeBruijnIndices(const z3::expr&, int, int); 80 | bool isRelevant(const z3::expr&, int, int); 81 | z3::expr mk_or(const z3::expr_vector&) const; 82 | z3::expr mk_and(const z3::expr_vector&) const ; 83 | z3::expr modifyQuantifierBody(const z3::expr& quantifierExpr, const z3::expr& newBody) const; 84 | z3::expr flipQuantifierAndModifyBody(const z3::expr& quantifierExpr, const z3::expr& newBody) const; 85 | z3::expr applyDer(const z3::expr&) const; 86 | 87 | bool propagateUnconstrained; 88 | bool goalUnconstrained; 89 | bool produceModels = false; 90 | 91 | int lastBound = 0; 92 | 93 | std::vector> usedPasses; 94 | }; 95 | 96 | 97 | #endif // EXPRSIMPLIFIER_H 98 | -------------------------------------------------------------------------------- /tests/data/003.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info 4 | :source | 5 | Generated by PSyCO 0.1 6 | More info in N. P. Lopes and J. Monteiro. Weakest Precondition Synthesis for 7 | Compiler Optimizations, VMCAI'14. 8 | 9 | Translated to BV by Mathias Preiner. 10 | |) 11 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 12 | (set-info :category "industrial") 13 | (set-info :status sat) 14 | (declare-fun W_S1_V1 () Bool) 15 | (declare-fun W_S1_V2 () Bool) 16 | (declare-fun W_S1_V4 () Bool) 17 | (declare-fun R_S1_V1 () Bool) 18 | (declare-fun R_S1_V2 () Bool) 19 | (declare-fun R_E1_V1 () Bool) 20 | (declare-fun R_E1_V3 () Bool) 21 | (declare-fun R_E1_V2 () Bool) 22 | (declare-fun R_E1_V4 () Bool) 23 | (declare-fun DISJ_W_S1_R_E1 () Bool) 24 | (declare-fun R_S1_V3 () Bool) 25 | (declare-fun R_S1_V4 () Bool) 26 | (declare-fun DISJ_W_S1_R_S1 () Bool) 27 | (declare-fun W_S1_V3 () Bool) 28 | (assert 29 | (let 30 | (($x341 31 | (forall 32 | ((V4_0 (_ BitVec 32)) (V2_0 (_ BitVec 32)) 33 | (V3_0 (_ BitVec 32)) (V1_0 (_ BitVec 32)) 34 | (MW_S1_V4 Bool) (MW_S1_V2 Bool) 35 | (MW_S1_V3 Bool) (MW_S1_V1 Bool) 36 | (S1_V3_!14 (_ BitVec 32)) (S1_V3_!20 (_ BitVec 32)) 37 | (E1_!11 (_ BitVec 32)) (E1_!16 (_ BitVec 32)) 38 | (E1_!17 (_ BitVec 32)) (S1_V1_!15 (_ BitVec 32)) 39 | (S1_V1_!21 (_ BitVec 32)) (S1_V2_!13 (_ BitVec 32)) 40 | (S1_V2_!19 (_ BitVec 32)) (S1_V4_!12 (_ BitVec 32)) 41 | (S1_V4_!18 (_ BitVec 32))) 42 | (let 43 | (($x276 44 | (and (= (ite MW_S1_V4 S1_V4_!12 V4_0) (ite MW_S1_V4 S1_V4_!18 V4_0)) 45 | (= E1_!16 (ite MW_S1_V2 S1_V2_!19 E1_!17)) 46 | (= (ite MW_S1_V3 S1_V3_!14 V3_0) (ite MW_S1_V3 S1_V3_!20 V3_0)) 47 | (= (ite MW_S1_V1 S1_V1_!15 E1_!11) (ite MW_S1_V1 S1_V1_!21 E1_!17))))) 48 | (let 49 | (($x292 50 | (and (or (not R_S1_V2) (= E1_!17 V2_0)) 51 | (or (not R_S1_V1) (= E1_!17 E1_!11))))) 52 | (let (($x293 (not $x292))) 53 | (let 54 | (($x300 55 | (and (or (not R_S1_V2) (= V2_0 E1_!17)) 56 | (or (not R_S1_V1) (= E1_!11 E1_!17))))) 57 | (let 58 | (($x315 59 | (and (or (not R_E1_V4) (= (ite MW_S1_V4 S1_V4_!12 V4_0) V4_0)) 60 | (or (not R_E1_V2) (= (ite MW_S1_V2 S1_V2_!13 V2_0) V2_0)) 61 | (or (not R_E1_V3) (= (ite MW_S1_V3 S1_V3_!14 V3_0) V3_0)) 62 | (or (not R_E1_V1) (= (ite MW_S1_V1 S1_V1_!15 E1_!11) V1_0))))) 63 | (let 64 | (($x327 65 | (and (or (not R_E1_V4) (= V4_0 (ite MW_S1_V4 S1_V4_!12 V4_0))) 66 | (or (not R_E1_V2) (= V2_0 (ite MW_S1_V2 S1_V2_!13 V2_0))) 67 | (or (not R_E1_V3) (= V3_0 (ite MW_S1_V3 S1_V3_!14 V3_0))) 68 | (or (not R_E1_V1) (= V1_0 (ite MW_S1_V1 S1_V1_!15 E1_!11)))))) 69 | (let 70 | (($x338 71 | (and (or $x293 (= S1_V3_!20 S1_V3_!14)) 72 | (or (not $x327) (= E1_!11 E1_!16)) 73 | (= E1_!11 E1_!17) (or (not $x315) (= E1_!16 E1_!17)) 74 | (or $x293 (= S1_V1_!21 S1_V1_!15)) 75 | (or (not $x300) (= S1_V2_!13 S1_V2_!19)) 76 | (or $x293 (= S1_V4_!18 S1_V4_!12)) 77 | (or (not MW_S1_V4) W_S1_V4) 78 | (or (not MW_S1_V2) W_S1_V2) 79 | (or (not MW_S1_V1) W_S1_V1)))) 80 | (or (not $x338) $x276))))))))))) 81 | (let 82 | (($x40 83 | (or (and W_S1_V4 R_E1_V4) 84 | (and W_S1_V2 R_E1_V2) R_E1_V3 85 | (and W_S1_V1 R_E1_V1)))) 86 | (let (($x42 (= DISJ_W_S1_R_E1 (not $x40)))) 87 | (let 88 | (($x37 89 | (or (and W_S1_V4 R_S1_V4) 90 | (and W_S1_V2 R_S1_V2) R_S1_V3 91 | (and W_S1_V1 R_S1_V1)))) 92 | (let (($x39 (= DISJ_W_S1_R_S1 (not $x37)))) (and W_S1_V3 $x39 $x42 $x341))))))) 93 | (check-sat) 94 | (exit) 95 | 96 | -------------------------------------------------------------------------------- /lib/simplificationPasses/PureLiteralEliminator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "PureLiteralEliminator.h" 4 | 5 | using namespace z3; 6 | 7 | void PureLiteralEliminator::getVariablePolarities(const z3::expr &e, bool isNegative) 8 | { 9 | auto item = processedPolaritiesCache.find({(Z3_ast)e, isNegative}); 10 | if (item != processedPolaritiesCache.end()) 11 | { 12 | return; 13 | } 14 | 15 | if (e.is_const() && !e.is_numeral()) 16 | { 17 | std::string expressionString = e.to_string(); 18 | 19 | if (e.get_sort().is_bool()) 20 | { 21 | if (expressionString == "true" || expressionString == "false") 22 | { 23 | return; 24 | } 25 | 26 | auto polarityIt = variablePolarities.find(expressionString); 27 | if (polarityIt == variablePolarities.end()) 28 | { 29 | variablePolarities.insert( {expressionString, isNegative ? NEGATIVE : POSITIVE} ); 30 | } 31 | else 32 | { 33 | auto polarity = polarityIt->second; 34 | 35 | if ((polarity == POSITIVE && isNegative) || 36 | (polarity == NEGATIVE && !isNegative)) 37 | { 38 | variablePolarities[expressionString] = BOTH_POLARITIES; 39 | } 40 | } 41 | } 42 | } 43 | else if (e.is_app()) 44 | { 45 | func_decl f = e.decl(); 46 | unsigned num = e.num_args(); 47 | 48 | if (f.decl_kind() == Z3_OP_NOT) 49 | { 50 | getVariablePolarities(e.arg(0), !isNegative); 51 | } 52 | else if (f.decl_kind() == Z3_OP_ITE) 53 | { 54 | getVariablePolarities(e.arg(0), isNegative); 55 | getVariablePolarities(e.arg(0), !isNegative); 56 | getVariablePolarities(e.arg(1), isNegative); 57 | getVariablePolarities(e.arg(2), isNegative); 58 | } 59 | else if (f.decl_kind() == Z3_OP_IFF || (f.decl_kind() == Z3_OP_EQ && e.arg(0).get_sort().is_bool())) 60 | { 61 | getVariablePolarities(e.arg(0), isNegative); 62 | getVariablePolarities(e.arg(0), !isNegative); 63 | getVariablePolarities(e.arg(1), isNegative); 64 | getVariablePolarities(e.arg(1), !isNegative); 65 | } 66 | else 67 | { 68 | for (unsigned i = 0; i < num; i++) 69 | { 70 | getVariablePolarities(e.arg(i), isNegative); 71 | } 72 | } 73 | } 74 | else if(e.is_quantifier()) 75 | { 76 | getVariablePolarities(e.body(), isNegative); 77 | } 78 | 79 | processedPolaritiesCache.insert({(Z3_ast)e, isNegative}); 80 | } 81 | 82 | z3::expr PureLiteralEliminator::Apply(z3::expr &e) 83 | { 84 | processedPolaritiesCache.clear(); 85 | variablePolarities.clear(); 86 | getVariablePolarities(e, false); 87 | 88 | z3::expr_vector polaritySubstitutesSrc(*context); 89 | z3::expr_vector polaritySubstitutesDst(*context); 90 | for (const auto &[var, polarity] : variablePolarities) 91 | { 92 | if (polarity == NEGATIVE || polarity == POSITIVE) 93 | { 94 | const auto literal = context->bool_const(var.c_str()); 95 | polaritySubstitutesSrc.push_back(literal); 96 | 97 | const auto newValue = context->bool_val(polarity == NEGATIVE ? false : true); 98 | polaritySubstitutesDst.push_back(newValue); 99 | appliedSubstitutions.push_back({literal, newValue}); 100 | } 101 | } 102 | 103 | if (polaritySubstitutesSrc.size() == 0) 104 | { 105 | return e; 106 | } 107 | else 108 | { 109 | return e.substitute(polaritySubstitutesSrc, polaritySubstitutesDst); 110 | } 111 | } 112 | 113 | void PureLiteralEliminator::ReconstructModel(Model &model) 114 | { 115 | for (auto it = appliedSubstitutions.rbegin(); it != appliedSubstitutions.rend(); it++) { 116 | const auto &[var, subst] = *it; 117 | 118 | std::stringstream variableString; 119 | variableString << var; 120 | 121 | model[variableString.str()] = vectorFromNumeral(substituteModel(subst, model)); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /tests/data/sum02_true-unreach-call_true-no-overflow.i_375.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Generated by the tool Ultimate Automizer [1,2] which implements 5 | an automata theoretic approach [3] to software verification. 6 | 7 | This SMT script belongs to a set of SMT scripts that was generated by 8 | applying Ultimate Automizer to benchmarks [4] from the SV-COMP 2017 [5,6]. 9 | 10 | This script might _not_ contain all SMT commands that are used by 11 | Ultimate Automizer. In order to satisfy the restrictions of 12 | the SMT-COMP we have to drop e.g., the commands for getting 13 | values (resp. models), unsatisfiable cores and interpolants. 14 | 15 | 2017-05-01, Matthias Heizmann (heizmann@informatik.uni-freiburg.de) 16 | 17 | 18 | [1] https://ultimate.informatik.uni-freiburg.de/automizer/ 19 | [2] Matthias Heizmann, Yu-Wen Chen, Daniel Dietsch, Marius Greitschus, 20 | Alexander Nutz, Betim Musa, Claus Schätzle, Christian Schilling, 21 | Frank Schüssele, Andreas Podelski: 22 | Ultimate Automizer with an On-Demand Construction of Floyd-Hoare 23 | Automata - (Competition Contribution). TACAS (2) 2017: 394-398 24 | [3] Matthias Heizmann, Jochen Hoenicke, Andreas Podelski: Software Model 25 | Checking for People Who Love Automata. CAV 2013:36-52 26 | [4] https://github.com/sosy-lab/sv-benchmarks 27 | [5] Dirk Beyer: Software Verification with Validation of Results - 28 | (Report on SV-COMP 2017). TACAS (2) 2017: 331-349 29 | [6] https://sv-comp.sosy-lab.org/2017/ 30 | |) 31 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 32 | (set-info :category "industrial") 33 | (set-info :status unknown) 34 | (declare-fun main_~sn~6_const_1701953089 () (_ BitVec 64)) 35 | (declare-fun main_~gauss~6_const_-911142799 () (_ BitVec 64)) 36 | (declare-fun main_~i~6_const_-993890350 () (_ BitVec 32)) 37 | (declare-fun main_~n~6_const_-993918699 () (_ BitVec 32)) 38 | (assert (or (forall ((main_~n~6 (_ BitVec 32))) (or (= (bvudiv (bvmul ((_ zero_extend 32) main_~n~6) (bvadd ((_ zero_extend 32) main_~n~6) (_ bv1 64))) (_ bv2 64)) (bvadd main_~sn~6_const_1701953089 ((_ zero_extend 32) (bvadd main_~i~6_const_-993890350 (_ bv1 32))))) (not (bvule (bvadd main_~i~6_const_-993890350 (_ bv1 32)) main_~n~6)) (bvule (bvadd main_~i~6_const_-993890350 (_ bv2 32)) main_~n~6))) (= ((_ sign_extend 32) (_ bv0 32)) (bvadd main_~sn~6_const_1701953089 ((_ zero_extend 32) (bvadd main_~i~6_const_-993890350 (_ bv1 32))))))) 39 | (assert (or (= ((_ sign_extend 32) (_ bv0 32)) main_~sn~6_const_1701953089) (= (bvudiv (bvmul ((_ zero_extend 32) main_~n~6_const_-993918699) (bvadd ((_ zero_extend 32) main_~n~6_const_-993918699) (_ bv1 64))) (_ bv2 64)) main_~sn~6_const_1701953089))) 40 | (assert (or (= ((_ sign_extend 32) (_ bv0 32)) main_~sn~6_const_1701953089) (= main_~sn~6_const_1701953089 main_~gauss~6_const_-911142799))) 41 | (assert (forall ((main_~n~6 (_ BitVec 32))) (or (not (bvule main_~i~6_const_-993890350 main_~n~6)) (= (bvudiv (bvmul ((_ zero_extend 32) main_~n~6) (bvadd ((_ zero_extend 32) main_~n~6) (_ bv1 64))) (_ bv2 64)) (bvadd main_~sn~6_const_1701953089 ((_ zero_extend 32) main_~i~6_const_-993890350))) (bvule (bvadd main_~i~6_const_-993890350 (_ bv1 32)) main_~n~6)))) 42 | (assert (not (= (bvadd (bvadd main_~sn~6_const_1701953089 ((_ zero_extend 32) main_~i~6_const_-993890350)) ((_ zero_extend 32) (bvadd main_~i~6_const_-993890350 (_ bv1 32)))) ((_ sign_extend 32) (_ bv0 32))))) 43 | (assert (not (forall ((main_~n~6 (_ BitVec 32))) (or (= (bvudiv (bvmul ((_ zero_extend 32) main_~n~6) (bvadd ((_ zero_extend 32) main_~n~6) (_ bv1 64))) (_ bv2 64)) (bvadd (bvadd main_~sn~6_const_1701953089 ((_ zero_extend 32) main_~i~6_const_-993890350)) ((_ zero_extend 32) (bvadd main_~i~6_const_-993890350 (_ bv1 32))))) (not (bvule (bvadd main_~i~6_const_-993890350 (_ bv1 32)) main_~n~6)) (bvule (bvadd main_~i~6_const_-993890350 (_ bv2 32)) main_~n~6))))) 44 | (check-sat) 45 | (exit) 46 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Q3B 2 | 3 | [![Build Status](https://travis-ci.org/martinjonas/Q3B.svg?branch=dev)](https://travis-ci.org/martinjonas/Q3B) 4 | [![Coverage Status](https://coveralls.io/repos/github/martinjonas/Q3B/badge.svg?branch=dev)](https://coveralls.io/github/martinjonas/Q3B?branch=dev) 5 | 6 | Q3B is an SMT solver for the quantified bit-vector formulas which uses 7 | BDDs. In a nutshell, it simplifies the input formula, converts it to 8 | the equivalent BDD, and answers `sat` if there is a satisfying path in 9 | the BDD. Q3B can also use approximations of formulas to solve some 10 | formulas containing complicated arithmetic, which can be hard to solve 11 | using BDDS. 12 | 13 | Details of the approach can be found in the paper [*Solving Quantified 14 | Bit-Vector Formulas Using Binary Decision 15 | Diagrams*](https://link.springer.com/chapter/10.1007/978-3-319-40970-2_17). 16 | 17 | ## Requirements 18 | * ANTLR 4 (for formula parser) 19 | * Z3 API >= 4.11 (for formula representation and to perform some of the 20 | simplifications) 21 | * CUDD BDD library (for BDD operations) 22 | 23 | All these requirements can be obtained by running 24 | ``` 25 | bash contrib/get_deps.sh 26 | ``` 27 | 28 | ## Compilation 29 | Q3B can be compiled by running 30 | ``` 31 | cmake -S . -B build 32 | cmake --build build -j4 33 | ``` 34 | (or with a different number of threads). 35 | 36 | ## Usage 37 | To process the file `file.smt2` in the SMT-LIB 2.5 format, run 38 | 39 | ``` 40 | ./q3b file.smt2 41 | ``` 42 | 43 | ## Abstractions 44 | 45 | If the input formula contains non-linear multiplication or division, 46 | abstractions of variables may be necessary, since otherwise the 47 | conversion to BDD is unlikely to terminate in reasonable time. By 48 | default, Q3B runs underapproximations and overapproximations in 49 | parallel with the base solver. To run only underapproximations or only 50 | overapproximations, run 51 | 52 | ``` 53 | ./q3b --abstractions=under file.smt2 54 | ``` 55 | or 56 | ``` 57 | ./q3b --abstractions=over file.smt2 58 | ``` 59 | 60 | To run the solver without abstractions, run 61 | ``` 62 | ./q3b --abstractions=none file.smt2 63 | ``` 64 | 65 | Q3B supports two types of abstractions, which are both enabled by default: 66 | 67 | ### Variable bit-width abstractions 68 | 69 | If variable abstractions are enabled, Q3B will fix some bits of chosen 70 | variables, which can result in smaller BDDs. To use only these 71 | approximations, run 72 | ``` 73 | ./q3b --abstract:method=variables file.smt2 74 | ``` 75 | 76 | ### Abstractions of bit-vector operations 77 | 78 | In addition to the mentioned variable approximations, Q3B also offers 79 | abstractions of bit-vector operations. If these abstractions are 80 | enabled, Q3B will compute only several bits of results of operations 81 | like addition or multiplication. It may be the case that only several 82 | result bits are necessary to decide satisfiability of the formula. To use only these 83 | approximations, run 84 | ``` 85 | ./q3b --abstract:method=operations file.smt2 86 | ``` 87 | 88 | ## Unconstrained variables 89 | 90 | Q3B also employs simplifications of formulas with unconstrained 91 | variables (i.e. variables that occur only once in the formula), as 92 | described in the paper [On Simplification of Formulas with 93 | Unconstrained Variables and 94 | Quantifiers](https://link.springer.com/chapter/10.1007/978-3-319-66263-3_23). 95 | These simplifications are enabled by default; to disable them, use the 96 | parameter `--simpl:unconstrained=0`. 97 | 98 | For unconstrained variables, Q3B takes their context into the account. 99 | For each term, Q3B keeps track of its goal: whether we want to 100 | minimize or maximize its signed or unsigned value. This information is 101 | used during the unconstrained variables simplification. To disable it, 102 | use the parameter `--uc:goal=0`. 103 | -------------------------------------------------------------------------------- /lib/simplificationPasses/EqualityPropagator.cpp: -------------------------------------------------------------------------------- 1 | #include "EqualityPropagator.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace z3; 7 | 8 | expr EqualityPropagator::Apply(const expr &e) 9 | { 10 | expr current = e; 11 | while (current.is_app() && e.decl().decl_kind() == Z3_OP_AND) 12 | { 13 | int argsCount = current.num_args(); 14 | bool wasSimplified = false; 15 | 16 | for (int i=0; i < argsCount; i++) 17 | { 18 | expr variable(*context); 19 | expr replacement(*context); 20 | if (getSubstitutableEquality(current.arg(i), &variable, &replacement)) 21 | { 22 | Z3_ast args [argsCount-1]; 23 | 24 | for (int j=0; j < argsCount-1; j++) 25 | { 26 | args[j] = j < i ? (Z3_ast)current.arg(j) : (Z3_ast)current.arg(j+1); 27 | } 28 | 29 | expr withoutSubstitutedEquality = to_expr(*context, Z3_mk_and(*context, argsCount - 1, args)); 30 | 31 | expr_vector src(*context); 32 | expr_vector dst(*context); 33 | 34 | src.push_back(variable); 35 | dst.push_back(replacement); 36 | 37 | appliedSubstitutions.push_back({variable, replacement}); 38 | 39 | current = withoutSubstitutedEquality.substitute(src, dst); 40 | wasSimplified = true; 41 | break; 42 | } 43 | } 44 | 45 | if (!wasSimplified) { 46 | break; 47 | } 48 | } 49 | 50 | return current; 51 | } 52 | 53 | void EqualityPropagator::ReconstructModel(Model &model) 54 | { 55 | for (auto it = appliedSubstitutions.rbegin(); it != appliedSubstitutions.rend(); it++) { 56 | const auto &[var, subst] = *it; 57 | 58 | std::stringstream variableString; 59 | variableString << var; 60 | 61 | model[variableString.str()] = vectorFromNumeral(substituteModel(subst, model)); 62 | } 63 | } 64 | 65 | 66 | bool EqualityPropagator::getSubstitutableEquality(const expr &e, expr *variable, expr *replacement) 67 | { 68 | if (e.is_app()) 69 | { 70 | func_decl dec = e.decl(); 71 | 72 | if (dec.decl_kind() == Z3_OP_EQ) 73 | { 74 | expr firstArg = e.arg(0); 75 | if (firstArg.is_app() && firstArg.num_args() == 0 && firstArg.decl().name() != NULL && firstArg.is_bv() && !firstArg.is_numeral()) 76 | { 77 | std::stringstream variableString; 78 | variableString << firstArg; 79 | std::stringstream replacementString; 80 | replacementString << e.arg(1); 81 | 82 | if (replacementString.str().find(variableString.str()) == std::string::npos) 83 | { 84 | *variable = firstArg; 85 | *replacement = e.arg(1); 86 | return true; 87 | } 88 | } 89 | 90 | expr secondArg = e.arg(1); 91 | if (secondArg.is_app() && secondArg.num_args() == 0 && secondArg.decl().name() != NULL && secondArg.is_bv() && !secondArg.is_numeral()) 92 | { 93 | std::stringstream variableString; 94 | variableString << secondArg; 95 | std::stringstream replacementString; 96 | replacementString << e.arg(0); 97 | 98 | if (replacementString.str().find(variableString.str()) == std::string::npos) 99 | { 100 | *variable = secondArg; 101 | *replacement = e.arg(0); 102 | return true; 103 | } 104 | } 105 | } 106 | else if (dec.decl_kind() == Z3_OP_NOT && isVar(e.arg(0))) 107 | { 108 | *variable = e.arg(0); 109 | *replacement = context->bool_val(false); 110 | return true; 111 | } 112 | } 113 | 114 | if (isVar(e) && e.is_bool()) 115 | { 116 | *variable = e; 117 | *replacement = context->bool_val(true); 118 | return true; 119 | } 120 | 121 | return false; 122 | } 123 | 124 | bool EqualityPropagator::isVar(const expr& e) const 125 | { 126 | if (e.is_var()) 127 | { 128 | return true; 129 | } 130 | 131 | if (e.is_app()) 132 | { 133 | func_decl f = e.decl(); 134 | unsigned num = e.num_args(); 135 | 136 | if (num == 0 && f.name() != NULL && !e.is_numeral()) 137 | { 138 | return true; 139 | } 140 | } 141 | 142 | return false; 143 | } 144 | -------------------------------------------------------------------------------- /lib/maybeBdd/maybeBdd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class MaybeBDD { 9 | private: 10 | std::optional innerBdd; 11 | static bool approximationHappened; 12 | 13 | public: 14 | MaybeBDD() 15 | { 16 | innerBdd = {}; 17 | } 18 | 19 | MaybeBDD(BDD bdd) 20 | : innerBdd(bdd) 21 | { 22 | 23 | } 24 | 25 | MaybeBDD& operator=(MaybeBDD other) 26 | { 27 | swap(other); 28 | return *this; 29 | } 30 | 31 | bool HasValue() const 32 | { 33 | return innerBdd.has_value(); 34 | } 35 | 36 | BDD GetBDD() const 37 | { 38 | return innerBdd.value(); 39 | } 40 | 41 | BDD GetBDD(BDD ifEmpty) const 42 | { 43 | if (!innerBdd.has_value()) 44 | { 45 | approximationHappened = true; 46 | } 47 | return innerBdd.value_or(ifEmpty); 48 | } 49 | 50 | MaybeBDD GetBDD(MaybeBDD ifEmpty) const 51 | { 52 | if (!innerBdd.has_value()) 53 | { 54 | approximationHappened = true; 55 | return ifEmpty; 56 | } 57 | return *this; 58 | } 59 | 60 | unsigned int NodeCount() const 61 | { 62 | if (innerBdd.has_value()) 63 | { 64 | return innerBdd.value().nodeCount(); 65 | } 66 | 67 | return 0; 68 | } 69 | 70 | static void ResetApproximationFlag() 71 | { 72 | approximationHappened = false; 73 | } 74 | 75 | static bool ApproximationHappened() 76 | { 77 | return approximationHappened; 78 | } 79 | 80 | MaybeBDD And(const MaybeBDD&) const; 81 | MaybeBDD Or(const MaybeBDD&) const; 82 | MaybeBDD Xor(const MaybeBDD&) const; 83 | MaybeBDD Xnor(const MaybeBDD&) const; 84 | MaybeBDD Not() const; 85 | 86 | MaybeBDD Ite(const MaybeBDD&, const MaybeBDD&) const; 87 | 88 | bool IsOne() const 89 | { 90 | return HasValue() && GetBDD().IsOne(); 91 | } 92 | 93 | bool IsZero() const 94 | { 95 | return HasValue() && GetBDD().IsZero(); 96 | } 97 | 98 | bool IsVar() const 99 | { 100 | return !HasValue() || GetBDD().IsVar(); 101 | } 102 | 103 | MaybeBDD operator&(const MaybeBDD& other) const 104 | { 105 | return this->And(other); 106 | } 107 | 108 | MaybeBDD operator&=(const MaybeBDD& other) 109 | { 110 | innerBdd = (*this & other).innerBdd; 111 | return *this; 112 | } 113 | 114 | MaybeBDD operator*(const MaybeBDD& other) const 115 | { 116 | return this->And(other); 117 | } 118 | 119 | MaybeBDD operator|(const MaybeBDD& other) const 120 | { 121 | return this->Or(other); 122 | } 123 | 124 | MaybeBDD operator|=(const MaybeBDD& other) 125 | { 126 | innerBdd = (*this | other).innerBdd; 127 | return *this; 128 | } 129 | 130 | MaybeBDD operator+(const MaybeBDD& other) const 131 | { 132 | return this->Or(other); 133 | } 134 | 135 | MaybeBDD operator!() const 136 | { 137 | return this->Not(); 138 | } 139 | 140 | MaybeBDD operator~() const 141 | { 142 | return this->Not(); 143 | } 144 | 145 | MaybeBDD operator^(const MaybeBDD& other) const 146 | { 147 | return this->Xor(other); 148 | } 149 | 150 | void swap(MaybeBDD& other) 151 | { 152 | using std::swap; 153 | swap(innerBdd, other.innerBdd); 154 | } 155 | 156 | bool Equals (const MaybeBDD& other) const 157 | { 158 | return (!this->HasValue() && !other.HasValue()) || 159 | (this->HasValue() && other.HasValue() && (this->GetBDD() == other.GetBDD())); 160 | } 161 | 162 | MaybeBDD LICompaction (BDD dontCare) 163 | { 164 | if (HasValue()) 165 | { 166 | return MaybeBDD(innerBdd.value().LICompaction(dontCare)); 167 | } 168 | else 169 | { 170 | return *this; 171 | } 172 | } 173 | 174 | MaybeBDD Minimize (BDD dontCare) 175 | { 176 | if (HasValue()) 177 | { 178 | return MaybeBDD(innerBdd.value().Minimize(dontCare)); 179 | } 180 | else 181 | { 182 | return *this; 183 | } 184 | } 185 | }; 186 | -------------------------------------------------------------------------------- /tests/data/RND_3_14.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Scholl, Christoph; Disch, Stefan; Pigorsch, Florian and Kupferschmid, 5 | Stefan; Using an SMT Solver and Craig Interpolation to Detect and Remove 6 | Redundant Linear Constraints in Representations of Non-Convex Polyhedra. 7 | Proceedings of 6th International Workshop on Satisfiability Modulo 8 | Theories, Princeton, USA, July 2008. 9 | 10 | 11 | Translated to BV by Mathias Preiner. 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "random") 15 | (set-info :status unsat) 16 | (declare-fun y2 () (_ BitVec 32)) 17 | (declare-fun y3 () (_ BitVec 32)) 18 | (declare-fun x1 () (_ BitVec 32)) 19 | (declare-fun y1 () (_ BitVec 32)) 20 | (assert (or (and (and (and (exists ((?y2 (_ BitVec 32))) (or (forall ((?y3 (_ BitVec 32))) (bvslt (bvadd (bvmul (bvneg (_ bv53 32)) ?y2) (bvmul (bvneg (_ bv56 32)) x1)) (_ bv79 32))) (or (= (bvmul (bvneg (_ bv94 32)) x1) (bvneg (_ bv54 32))) (bvsgt (bvadd (bvmul (_ bv34 32) ?y2) (bvmul (bvneg (_ bv28 32)) x1)) (_ bv62 32))))) (forall ((?y1 (_ BitVec 32))) (forall ((?y2 (_ BitVec 32))) (and (= (bvadd (bvmul (_ bv25 32) ?y2) (bvmul (bvneg (_ bv91 32)) x1)) (_ bv12 32)) (bvsgt (bvadd (bvmul (_ bv51 32) ?y2) (bvmul (_ bv22 32) ?y1)) (bvneg (_ bv49 32))))))) (or (and (forall ((?y1 (_ BitVec 32))) (exists ((?y2 (_ BitVec 32))) (forall ((?y3 (_ BitVec 32))) (bvslt (bvadd (bvadd (bvmul (_ bv20 32) ?y3) (bvmul (_ bv94 32) ?y1)) (bvmul (bvneg (_ bv42 32)) x1)) (_ bv0 32))))) (exists ((?y1 (_ BitVec 32))) (forall ((?y2 (_ BitVec 32))) (exists ((?y3 (_ BitVec 32))) (bvsle (bvadd (bvadd (bvmul (bvneg (_ bv1 32)) ?y3) (bvmul (_ bv84 32) ?y2)) (bvmul (_ bv79 32) x1)) (_ bv5 32)))))) (or (bvslt (bvmul (bvneg (_ bv26 32)) x1) (_ bv61 32)) (and (bvsge (bvmul (_ bv91 32) x1) (_ bv58 32)) (forall ((?y2 (_ BitVec 32))) (bvsgt (bvmul (bvneg (_ bv68 32)) x1) (_ bv74 32))))))) (forall ((?y1 (_ BitVec 32))) (exists ((?y2 (_ BitVec 32))) (exists ((?y3 (_ BitVec 32))) (or (and (or (bvsge (bvadd (bvadd (bvadd (bvmul (bvneg (_ bv47 32)) ?y3) (bvmul (_ bv1 32) ?y2)) (bvmul (bvneg (_ bv42 32)) ?y1)) (bvmul (bvneg (_ bv8 32)) x1)) (_ bv61 32)) (not (= (bvadd (bvadd (bvmul (_ bv38 32) ?y2) (bvmul (_ bv35 32) ?y1)) (bvmul (bvneg (_ bv80 32)) x1)) (_ bv48 32)))) (or (bvsge (bvadd (bvmul (bvneg (_ bv80 32)) ?y3) (bvmul (bvneg (_ bv78 32)) x1)) (_ bv25 32)) (bvsle (bvadd (bvmul (bvneg (_ bv66 32)) ?y3) (bvmul (bvneg (_ bv73 32)) ?y1)) (bvneg (_ bv19 32))))) (bvsle (bvadd (bvadd (bvmul (_ bv72 32) ?y3) (bvmul (_ bv10 32) ?y1)) (bvmul (bvneg (_ bv63 32)) x1)) (bvneg (_ bv28 32)))))))) (exists ((?y1 (_ BitVec 32))) (forall ((?y2 (_ BitVec 32))) (and (forall ((?y3 (_ BitVec 32))) (or (or (and (= (bvadd (bvadd (bvmul (_ bv33 32) ?y2) (bvmul (_ bv7 32) ?y1)) (bvmul (_ bv84 32) x1)) (_ bv0 32)) (bvslt (bvadd (bvmul (_ bv16 32) ?y3) (bvmul (_ bv57 32) ?y2)) (_ bv40 32))) (and (not (= (bvadd (bvadd (bvadd (bvmul (_ bv94 32) ?y3) (bvmul (bvneg (_ bv19 32)) ?y2)) (bvmul (bvneg (_ bv86 32)) ?y1)) (bvmul (bvneg (_ bv74 32)) x1)) (bvneg (_ bv6 32)))) (bvsgt (bvadd (bvmul (bvneg (_ bv32 32)) ?y3) (bvmul (_ bv16 32) ?y1)) (_ bv0 32)))) (and (and (not (= (bvadd (bvadd (bvadd (bvmul (bvneg (_ bv45 32)) ?y3) (bvmul (_ bv11 32) ?y2)) (bvmul (bvneg (_ bv90 32)) ?y1)) (bvmul (_ bv75 32) x1)) (_ bv57 32))) (bvsge (bvadd (bvadd (bvadd (bvmul (_ bv34 32) ?y3) (bvmul (_ bv36 32) ?y2)) (bvmul (_ bv75 32) ?y1)) (bvmul (_ bv67 32) x1)) (bvneg (_ bv8 32)))) (and (bvsgt (bvmul (bvneg (_ bv7 32)) ?y3) (_ bv0 32)) (= (bvadd (bvadd (bvmul (bvneg (_ bv17 32)) ?y3) (bvmul (_ bv44 32) ?y2)) (bvmul (_ bv27 32) ?y1)) (_ bv0 32)))))) (or (and (bvsge (bvadd (bvmul (_ bv5 32) ?y2) (bvmul (bvneg (_ bv33 32)) ?y1)) (bvneg (_ bv32 32))) (and (bvsle (bvadd (bvmul (_ bv77 32) ?y2) (bvmul (_ bv46 32) x1)) (_ bv51 32)) (bvslt (bvadd (bvmul (_ bv79 32) ?y2) (bvmul (_ bv1 32) ?y1)) (bvneg (_ bv86 32))))) (and (or (bvslt (bvmul (bvneg (_ bv46 32)) ?y1) (_ bv37 32)) (not (= (bvmul (bvneg (_ bv2 32)) x1) (_ bv50 32)))) (and (= (bvadd (bvadd (bvmul (bvneg (_ bv95 32)) ?y2) (bvmul (bvneg (_ bv96 32)) ?y1)) (bvmul (bvneg (_ bv74 32)) x1)) (bvneg (_ bv24 32))) (bvsge (bvmul (bvneg (_ bv70 32)) x1) (_ bv0 32)))))))))) 21 | (check-sat) 22 | (exit) 23 | -------------------------------------------------------------------------------- /tests/data/nlzbe008.smt2: -------------------------------------------------------------------------------- 1 | (set-logic QF_BV) 2 | (set-info :source | 3 | Number of leading zeros nlz(x) algorithm, working both ends at the same time 4 | From the book "Hacker's delight" by Henry S. Warren, Jr., page 79 5 | We cross-check it with an obvious method of counting leading zeros: 6 | 7 | s = 0; 8 | for (i = BW - 1; i >= 0; i--) 9 | if (x & (1 << i)) 10 | break; 11 | else 12 | s++; 13 | 14 | Contributed by Robert Brummayer (robert.brummayer@gmail.com) 15 | |) 16 | (set-info :smt-lib-version 2.0) 17 | (set-info :category "crafted") 18 | (set-info :status unsat) 19 | (declare-fun result1init () (_ BitVec 8)) 20 | (declare-fun x () (_ BitVec 8)) 21 | (assert (let ((?v_9 (ite (= x (_ bv0 8)) (_ bv1 1) (_ bv0 1))) (?v_8 (ite (bvslt x (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_13 (ite (= (_ bv1 1) (_ bv0 1)) result1init (ite (= (_ bv1 1) ?v_8) (_ bv0 8) (ite (= (_ bv1 1) ?v_9) (bvsub (_ bv8 8) (_ bv0 8)) result1init)))) (?v_7 (bvor (_ bv0 1) (bvor ?v_8 ?v_9))) (?v_12 (bvadd (_ bv0 8) (_ bv1 8))) (?v_0 ((_ zero_extend 5) (_ bv1 3)))) (let ((?v_1 (bvshl x ?v_0)) (?v_2 (bvashr x ?v_0))) (let ((?v_11 (ite (= ?v_2 (_ bv0 8)) (_ bv1 1) (_ bv0 1))) (?v_10 (ite (bvslt ?v_1 (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_17 (ite (= (_ bv1 1) ?v_7) ?v_13 (ite (= (_ bv1 1) ?v_10) ?v_12 (ite (= (_ bv1 1) ?v_11) (bvsub (_ bv8 8) ?v_12) ?v_13)))) (?v_6 (bvor ?v_7 (bvor ?v_10 ?v_11))) (?v_16 (bvadd ?v_12 (_ bv1 8))) (?v_3 (bvshl ?v_1 ?v_0)) (?v_4 (bvashr ?v_2 ?v_0))) (let ((?v_15 (ite (= ?v_4 (_ bv0 8)) (_ bv1 1) (_ bv0 1))) (?v_14 (ite (bvslt ?v_3 (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_21 (ite (= (_ bv1 1) ?v_6) ?v_17 (ite (= (_ bv1 1) ?v_14) ?v_16 (ite (= (_ bv1 1) ?v_15) (bvsub (_ bv8 8) ?v_16) ?v_17)))) (?v_5 (bvor ?v_6 (bvor ?v_14 ?v_15))) (?v_20 (bvadd ?v_16 (_ bv1 8))) (?v_22 (bvshl ?v_3 ?v_0)) (?v_23 (bvashr ?v_4 ?v_0))) (let ((?v_19 (ite (= ?v_23 (_ bv0 8)) (_ bv1 1) (_ bv0 1))) (?v_18 (ite (bvslt ?v_22 (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_25 (ite (= (_ bv1 1) ?v_5) ?v_21 (ite (= (_ bv1 1) ?v_18) ?v_20 (ite (= (_ bv1 1) ?v_19) (bvsub (_ bv8 8) ?v_20) ?v_21)))) (?v_24 (bvadd ?v_20 (_ bv1 8))) (?v_39 (ite (= (bvand x (bvshl (_ bv1 8) ((_ zero_extend 5) (_ bv7 3)))) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_40 (bvor (_ bv0 1) (bvnot ?v_39)))) (let ((?v_41 (ite (= (_ bv1 1) ?v_39) (ite (= (_ bv1 1) ?v_40) (_ bv0 8) ?v_12) (_ bv0 8))) (?v_37 (ite (= (bvand x (bvshl (_ bv1 8) ((_ zero_extend 5) (_ bv6 3)))) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_38 (bvor ?v_40 (bvnot ?v_37)))) (let ((?v_42 (ite (= (_ bv1 1) ?v_37) (ite (= (_ bv1 1) ?v_38) ?v_41 (bvadd ?v_41 (_ bv1 8))) ?v_41)) (?v_35 (ite (= (bvand x (bvshl (_ bv1 8) ((_ zero_extend 5) (_ bv5 3)))) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_36 (bvor ?v_38 (bvnot ?v_35)))) (let ((?v_43 (ite (= (_ bv1 1) ?v_35) (ite (= (_ bv1 1) ?v_36) ?v_42 (bvadd ?v_42 (_ bv1 8))) ?v_42)) (?v_33 (ite (= (bvand x (bvshl (_ bv1 8) ((_ zero_extend 5) (_ bv4 3)))) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_34 (bvor ?v_36 (bvnot ?v_33)))) (let ((?v_44 (ite (= (_ bv1 1) ?v_33) (ite (= (_ bv1 1) ?v_34) ?v_43 (bvadd ?v_43 (_ bv1 8))) ?v_43)) (?v_31 (ite (= (bvand x (bvshl (_ bv1 8) ((_ zero_extend 5) (_ bv3 3)))) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_32 (bvor ?v_34 (bvnot ?v_31)))) (let ((?v_45 (ite (= (_ bv1 1) ?v_31) (ite (= (_ bv1 1) ?v_32) ?v_44 (bvadd ?v_44 (_ bv1 8))) ?v_44)) (?v_29 (ite (= (bvand x (bvshl (_ bv1 8) ((_ zero_extend 5) (_ bv2 3)))) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_30 (bvor ?v_32 (bvnot ?v_29)))) (let ((?v_46 (ite (= (_ bv1 1) ?v_29) (ite (= (_ bv1 1) ?v_30) ?v_45 (bvadd ?v_45 (_ bv1 8))) ?v_45)) (?v_27 (ite (= (bvand x (bvshl (_ bv1 8) ?v_0)) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (let ((?v_28 (bvor ?v_30 (bvnot ?v_27)))) (let ((?v_47 (ite (= (_ bv1 1) ?v_27) (ite (= (_ bv1 1) ?v_28) ?v_46 (bvadd ?v_46 (_ bv1 8))) ?v_46)) (?v_26 (ite (= (bvand x (bvshl (_ bv1 8) ((_ zero_extend 5) (_ bv0 3)))) (_ bv0 8)) (_ bv1 1) (_ bv0 1)))) (not (= (bvnot (ite (= (ite (= (_ bv1 1) (bvor ?v_5 (bvor ?v_18 ?v_19))) ?v_25 (ite (= (_ bv1 1) (ite (bvslt (bvshl ?v_22 ?v_0) (_ bv0 8)) (_ bv1 1) (_ bv0 1))) ?v_24 (ite (= (_ bv1 1) (ite (= (bvashr ?v_23 ?v_0) (_ bv0 8)) (_ bv1 1) (_ bv0 1))) (bvsub (_ bv8 8) ?v_24) ?v_25))) (ite (= (_ bv1 1) ?v_26) (ite (= (_ bv1 1) (bvor ?v_28 (bvnot ?v_26))) ?v_47 (bvadd ?v_47 (_ bv1 8))) ?v_47)) (_ bv1 1) (_ bv0 1))) (_ bv0 1))))))))))))))))))))))))))) 22 | (check-sat) 23 | (exit) 24 | -------------------------------------------------------------------------------- /lib/UnconstrainedVariableSimplifier.h: -------------------------------------------------------------------------------- 1 | #ifndef UNCONSTRAINEDVARIABLESIMPLIFIER_H 2 | #define UNCONSTRAINEDVARIABLESIMPLIFIER_H 3 | 4 | #include "z3++.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "SimplificationPass.h" 16 | #include "HashUtils.h" 17 | enum BoundType { EXISTENTIAL, UNIVERSAL }; 18 | enum Goal { SIGN_MIN, SIGN_MAX, UNSIGN_MIN, UNSIGN_MAX, NONE }; 19 | 20 | typedef std::tuple BoundVar; 21 | 22 | namespace std 23 | { 24 | template<> 25 | struct hash 26 | { 27 | size_t operator() (const BoundVar& p) const 28 | { 29 | auto h1 = std::hash{}(std::get<0>(p)); 30 | auto h2 = 1 + std::get<1>(p); 31 | auto h3 = std::get<2>(p); 32 | 33 | return h1 ^ h2 ^ h3; 34 | } 35 | }; 36 | 37 | template<> 38 | struct hash> 39 | { 40 | std::size_t operator()(const std::vector& vec) const { 41 | std::size_t seed = vec.size(); 42 | for(auto& i : vec) { 43 | seed ^= std::hash{}(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 44 | } 45 | return seed; 46 | } 47 | }; 48 | } 49 | 50 | class UnconstrainedVariableSimplifier : public SimplificationPass 51 | { 52 | public: 53 | UnconstrainedVariableSimplifier(z3::context &ctx, z3::expr expr) : expression(expr) 54 | { 55 | this->context = &ctx; 56 | } 57 | 58 | void PrintUnconstrained() 59 | { 60 | std::cout << "------" << std::endl; 61 | bool allConstrained = true; 62 | 63 | for (auto &item : variableCounts) 64 | { 65 | if (item.second == 1) 66 | { 67 | allConstrained = false; 68 | std::cout << "Unconstrained variable: " << item.first << std::endl; 69 | } 70 | } 71 | if (allConstrained) std::cout << "All variables constrained" << std::endl; 72 | std::cout << "------" << std::endl; 73 | } 74 | 75 | void SimplifyOnce() 76 | { 77 | expression = simplifyOnce(expression, {}, true, NONE); 78 | } 79 | 80 | z3::expr GetExpr() const { return expression; } 81 | 82 | void SimplifyIte(); 83 | 84 | void SetDagCounting(bool dagCounting) 85 | { 86 | this->dagCounting = dagCounting; 87 | } 88 | 89 | void SetGoalUnconstrained(bool goalUnconstrained) 90 | { 91 | this->goalUnconstrained = goalUnconstrained; 92 | } 93 | 94 | void MarkConstrained(std::set vars) 95 | { 96 | forcedConstrained = vars; 97 | } 98 | 99 | void ForceGoal(Goal goal) 100 | { 101 | forcedGoal = goal; 102 | } 103 | 104 | void ReconstructModel(Model &model) override { 105 | std::cout << "Warning: model reconstruction for unconstrained simplifications is not implemented \n"; 106 | } 107 | 108 | private: 109 | z3::context* context; 110 | z3::expr expression; 111 | 112 | std::unordered_map, std::map> subformulaVariableCounts; 113 | std::unordered_map>, int> subformulaMaxLevels; 114 | std::map variableCounts; 115 | 116 | typedef std::unordered_map>> cacheMapType; 117 | 118 | cacheMapType trueSimplificationCache; 119 | cacheMapType falseSimplificationCache; 120 | 121 | std::map countVariableOccurences(z3::expr, bool, Goal); 122 | std::map countFormulaVarOccurences(z3::expr); 123 | void addCounts(const std::map&, std::map&); 124 | void maxCounts(std::map&&, std::map&); 125 | bool allConstrained(std::map&); 126 | int getMaxLevel(z3::expr, const std::vector&, bool); 127 | 128 | z3::expr simplifyOnce(z3::expr, std::vector, bool, Goal); 129 | bool isUnconstrained(z3::expr, const std::vector&) const; 130 | bool isVar(z3::expr) const; 131 | bool isBefore(z3::expr, z3::expr, const std::vector&, bool); 132 | BoundType getBoundType(z3::expr, const std::vector&); 133 | 134 | int getNumberOfLeadingZeroes(const z3::expr&); 135 | int lastBound = 0; 136 | 137 | bool dagCounting = false; 138 | bool goalUnconstrained = false; 139 | int cacheHits = 0; 140 | 141 | std::set forcedConstrained; 142 | std::optional forcedGoal; 143 | }; 144 | 145 | #endif // UNCONSTRAINEDVARIABLESIMPLIFIER_H 146 | -------------------------------------------------------------------------------- /tests/data/002.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info 4 | :source | 5 | Generated by PSyCO 0.1 6 | More info in N. P. Lopes and J. Monteiro. Weakest Precondition Synthesis for 7 | Compiler Optimizations, VMCAI'14. 8 | 9 | Translated to BV by Mathias Preiner. 10 | |) 11 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 12 | (set-info :category "industrial") 13 | (set-info :status unsat) 14 | (declare-fun W_S1_V1 () Bool) 15 | (declare-fun W_S1_V2 () Bool) 16 | (declare-fun W_S1_V4 () Bool) 17 | (declare-fun R_S1_V1 () Bool) 18 | (declare-fun R_E1_V1 () Bool) 19 | (declare-fun R_E1_V3 () Bool) 20 | (declare-fun R_E1_V2 () Bool) 21 | (declare-fun R_E1_V4 () Bool) 22 | (declare-fun DISJ_W_S1_R_E1 () Bool) 23 | (declare-fun R_S1_V3 () Bool) 24 | (declare-fun R_S1_V2 () Bool) 25 | (declare-fun R_S1_V4 () Bool) 26 | (declare-fun DISJ_W_S1_R_S1 () Bool) 27 | (declare-fun W_S1_V3 () Bool) 28 | (assert 29 | (let 30 | (($x324 31 | (forall 32 | ((V4_0 (_ BitVec 32)) (V2_0 (_ BitVec 32)) 33 | (V3_0 (_ BitVec 32)) (V1_0 (_ BitVec 32)) 34 | (MW_S1_V4 Bool) (MW_S1_V2 Bool) 35 | (MW_S1_V3 Bool) (MW_S1_V1 Bool) 36 | (S1_V3_!14 (_ BitVec 32)) (S1_V3_!20 (_ BitVec 32)) 37 | (E1_!11 (_ BitVec 32)) (E1_!16 (_ BitVec 32)) 38 | (E1_!17 (_ BitVec 32)) (S1_V1_!15 (_ BitVec 32)) 39 | (S1_V1_!21 (_ BitVec 32)) (S1_V2_!13 (_ BitVec 32)) 40 | (S1_V2_!19 (_ BitVec 32)) (S1_V4_!12 (_ BitVec 32)) 41 | (S1_V4_!18 (_ BitVec 32))) 42 | (let ((?x257 (ite MW_S1_V1 S1_V1_!21 E1_!17))) 43 | (let ((?x258 (ite MW_S1_V1 S1_V1_!15 E1_!11))) 44 | (let (($x259 (= ?x258 ?x257))) 45 | (let ((?x260 (ite MW_S1_V3 S1_V3_!20 V3_0))) 46 | (let ((?x261 (ite MW_S1_V3 S1_V3_!14 V3_0))) 47 | (let (($x262 (= ?x261 ?x260))) 48 | (let (($x263 (= E1_!16 ?x257))) 49 | (let ((?x264 (ite MW_S1_V4 S1_V4_!18 V4_0))) 50 | (let ((?x265 (ite MW_S1_V4 S1_V4_!12 V4_0))) 51 | (let (($x266 (= ?x265 ?x264))) 52 | (let (($x267 (and $x266 $x263 $x262 $x259))) 53 | (let (($x269 (not MW_S1_V1))) 54 | (let (($x270 (or $x269 W_S1_V1))) 55 | (let (($x273 (not MW_S1_V2))) 56 | (let (($x274 (or $x273 W_S1_V2))) 57 | (let (($x275 (not MW_S1_V4))) 58 | (let (($x276 (or $x275 W_S1_V4))) 59 | (let (($x278 (= S1_V4_!18 S1_V4_!12))) 60 | (let (($x279 (= E1_!17 E1_!11))) 61 | (let (($x88 (not R_S1_V1))) 62 | (let (($x280 (or $x88 $x279))) 63 | (let (($x281 (not $x280))) 64 | (let (($x282 (or $x281 $x278))) 65 | (let (($x283 (= S1_V2_!19 S1_V2_!13))) 66 | (let (($x284 (or $x281 $x283))) 67 | (let (($x285 (= S1_V1_!21 S1_V1_!15))) 68 | (let (($x286 (or $x281 $x285))) 69 | (let (($x287 (= E1_!16 E1_!17))) 70 | (let (($x288 (= ?x258 V1_0))) 71 | (let (($x99 (not R_E1_V1))) 72 | (let (($x289 (or $x99 $x288))) 73 | (let (($x290 (= ?x261 V3_0))) 74 | (let (($x97 (not R_E1_V3))) 75 | (let (($x291 (or $x97 $x290))) 76 | (let ((?x292 (ite MW_S1_V2 S1_V2_!13 V2_0))) 77 | (let (($x293 (= ?x292 V2_0))) 78 | (let (($x95 (not R_E1_V2))) 79 | (let (($x294 (or $x95 $x293))) 80 | (let (($x295 (= ?x265 V4_0))) 81 | (let (($x93 (not R_E1_V4))) 82 | (let (($x296 (or $x93 $x295))) 83 | (let (($x297 (and $x296 $x294 $x291 $x289))) 84 | (let (($x298 (not $x297))) 85 | (let (($x299 (or $x298 $x287))) 86 | (let (($x300 (= E1_!11 E1_!17))) 87 | (let (($x301 (= E1_!11 E1_!16))) 88 | (let (($x302 (= V1_0 ?x258))) 89 | (let (($x303 (or $x99 $x302))) 90 | (let (($x304 (= V3_0 ?x261))) 91 | (let (($x305 (or $x97 $x304))) 92 | (let (($x306 (= V2_0 ?x292))) 93 | (let (($x307 (or $x95 $x306))) 94 | (let (($x308 (= V4_0 ?x265))) 95 | (let (($x309 (or $x93 $x308))) 96 | (let (($x310 (and $x309 $x307 $x305 $x303))) 97 | (let (($x311 (not $x310))) 98 | (let (($x312 (or $x311 $x301))) 99 | (let (($x313 (= S1_V3_!20 S1_V3_!14))) 100 | (let (($x314 (or $x281 $x313))) 101 | (let 102 | (($x321 103 | (and $x314 $x312 $x300 $x299 $x286 $x284 $x282 $x276 $x274 $x270))) 104 | (let (($x322 (not $x321))) (or $x322 $x267))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) 105 | (let (($x30 (and W_S1_V1 R_E1_V1))) 106 | (let (($x26 (and W_S1_V2 R_E1_V2))) 107 | (let (($x24 (and W_S1_V4 R_E1_V4))) 108 | (let (($x40 (or $x24 $x26 R_E1_V3 $x30))) 109 | (let (($x41 (not $x40))) 110 | (let (($x42 (= DISJ_W_S1_R_E1 $x41))) 111 | (let (($x18 (and W_S1_V1 R_S1_V1))) 112 | (let (($x13 (and W_S1_V2 R_S1_V2))) 113 | (let (($x10 (and W_S1_V4 R_S1_V4))) 114 | (let (($x37 (or $x10 $x13 R_S1_V3 $x18))) 115 | (let (($x38 (not $x37))) 116 | (let (($x39 (= DISJ_W_S1_R_S1 $x38))) (and W_S1_V3 $x39 $x42 $x324))))))))))))))) 117 | (assert 118 | (let (($x155 (not W_S1_V1))) 119 | (let (($x99 (not R_E1_V1))) 120 | (let (($x380 (and $x99 $x155 DISJ_W_S1_R_E1))) (not $x380))))) 121 | (check-sat) 122 | (exit) 123 | 124 | -------------------------------------------------------------------------------- /cmake/FindANTLR.cmake: -------------------------------------------------------------------------------- 1 | find_package(Java QUIET COMPONENTS Runtime) 2 | 3 | if(NOT ANTLR_EXECUTABLE) 4 | find_program(ANTLR_EXECUTABLE 5 | NAMES antlr.jar antlr4.jar antlr-4.jar antlr-4.10.1-complete.jar) 6 | endif() 7 | 8 | if(ANTLR_EXECUTABLE AND Java_JAVA_EXECUTABLE) 9 | execute_process( 10 | COMMAND ${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE} 11 | OUTPUT_VARIABLE ANTLR_COMMAND_OUTPUT 12 | ERROR_VARIABLE ANTLR_COMMAND_ERROR 13 | RESULT_VARIABLE ANTLR_COMMAND_RESULT 14 | OUTPUT_STRIP_TRAILING_WHITESPACE) 15 | 16 | if(ANTLR_COMMAND_RESULT EQUAL 0) 17 | string(REGEX MATCH "Version [0-9]+(\\.[0-9])*" ANTLR_VERSION ${ANTLR_COMMAND_OUTPUT}) 18 | string(REPLACE "Version " "" ANTLR_VERSION ${ANTLR_VERSION}) 19 | else() 20 | message( 21 | SEND_ERROR 22 | "Command '${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE}' " 23 | "failed with the output '${ANTLR_COMMAND_ERROR}'") 24 | endif() 25 | 26 | macro(ANTLR_TARGET Name InputFile) 27 | set(ANTLR_OPTIONS LEXER PARSER LISTENER VISITOR) 28 | set(ANTLR_ONE_VALUE_ARGS PACKAGE OUTPUT_DIRECTORY DEPENDS_ANTLR) 29 | set(ANTLR_MULTI_VALUE_ARGS COMPILE_FLAGS DEPENDS) 30 | cmake_parse_arguments(ANTLR_TARGET 31 | "${ANTLR_OPTIONS}" 32 | "${ANTLR_ONE_VALUE_ARGS}" 33 | "${ANTLR_MULTI_VALUE_ARGS}" 34 | ${ARGN}) 35 | 36 | set(ANTLR_${Name}_INPUT ${InputFile}) 37 | 38 | get_filename_component(ANTLR_INPUT ${InputFile} NAME_WE) 39 | 40 | if(ANTLR_TARGET_OUTPUT_DIRECTORY) 41 | set(ANTLR_${Name}_OUTPUT_DIR ${ANTLR_TARGET_OUTPUT_DIRECTORY}) 42 | else() 43 | set(ANTLR_${Name}_OUTPUT_DIR 44 | ${CMAKE_CURRENT_BINARY_DIR}/antlr4cpp_generated_src/${ANTLR_INPUT}) 45 | endif() 46 | 47 | unset(ANTLR_${Name}_CXX_OUTPUTS) 48 | 49 | if((ANTLR_TARGET_LEXER AND NOT ANTLR_TARGET_PARSER) OR 50 | (ANTLR_TARGET_PARSER AND NOT ANTLR_TARGET_LEXER)) 51 | list(APPEND ANTLR_${Name}_CXX_OUTPUTS 52 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.h 53 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.cpp) 54 | set(ANTLR_${Name}_OUTPUTS 55 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.interp 56 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}.tokens) 57 | else() 58 | list(APPEND ANTLR_${Name}_CXX_OUTPUTS 59 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.h 60 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.cpp 61 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Parser.h 62 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Parser.cpp) 63 | list(APPEND ANTLR_${Name}_OUTPUTS 64 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.interp 65 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Lexer.tokens) 66 | endif() 67 | 68 | if(ANTLR_TARGET_LISTENER) 69 | list(APPEND ANTLR_${Name}_CXX_OUTPUTS 70 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseListener.h 71 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseListener.cpp 72 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Listener.h 73 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Listener.cpp) 74 | list(APPEND ANTLR_TARGET_COMPILE_FLAGS -listener) 75 | endif() 76 | 77 | if(ANTLR_TARGET_VISITOR) 78 | list(APPEND ANTLR_${Name}_CXX_OUTPUTS 79 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseVisitor.h 80 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}BaseVisitor.cpp 81 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Visitor.h 82 | ${ANTLR_${Name}_OUTPUT_DIR}/${ANTLR_INPUT}Visitor.cpp) 83 | list(APPEND ANTLR_TARGET_COMPILE_FLAGS -visitor) 84 | endif() 85 | 86 | if(ANTLR_TARGET_PACKAGE) 87 | list(APPEND ANTLR_TARGET_COMPILE_FLAGS -package ${ANTLR_TARGET_PACKAGE}) 88 | endif() 89 | 90 | list(APPEND ANTLR_${Name}_OUTPUTS ${ANTLR_${Name}_CXX_OUTPUTS}) 91 | 92 | if(ANTLR_TARGET_DEPENDS_ANTLR) 93 | if(ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_INPUT) 94 | list(APPEND ANTLR_TARGET_DEPENDS 95 | ${ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_INPUT}) 96 | list(APPEND ANTLR_TARGET_DEPENDS 97 | ${ANTLR_${ANTLR_TARGET_DEPENDS_ANTLR}_OUTPUTS}) 98 | else() 99 | message(SEND_ERROR 100 | "ANTLR target '${ANTLR_TARGET_DEPENDS_ANTLR}' not found") 101 | endif() 102 | endif() 103 | 104 | add_custom_command( 105 | OUTPUT ${ANTLR_${Name}_OUTPUTS} 106 | COMMAND ${Java_JAVA_EXECUTABLE} -jar ${ANTLR_EXECUTABLE} 107 | ${InputFile} 108 | -o ${ANTLR_${Name}_OUTPUT_DIR} 109 | -Xexact-output-dir 110 | -no-listener 111 | -Dlanguage=Cpp 112 | ${ANTLR_TARGET_COMPILE_FLAGS} 113 | DEPENDS ${InputFile} 114 | ${ANTLR_TARGET_DEPENDS} 115 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} 116 | COMMENT "Building ${Name} with ANTLR ${ANTLR_VERSION}") 117 | endmacro(ANTLR_TARGET) 118 | 119 | endif(ANTLR_EXECUTABLE AND Java_JAVA_EXECUTABLE) 120 | 121 | include(FindPackageHandleStandardArgs) 122 | find_package_handle_standard_args( 123 | ANTLR 124 | REQUIRED_VARS ANTLR_EXECUTABLE Java_JAVA_EXECUTABLE 125 | VERSION_VAR ANTLR_VERSION) 126 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(q3b) 3 | 4 | SET(CMAKE_CXX_STANDARD 17) 5 | 6 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 7 | 8 | if(NOT CMAKE_BUILD_TYPE) 9 | message(STATUS "No Build type specified; using RELEASE.") 10 | set(CMAKE_BUILD_TYPE Release) 11 | endif(NOT CMAKE_BUILD_TYPE) 12 | 13 | file(GLOB Q3B_SRC 14 | "lib/*.h" 15 | "lib/*.cpp" 16 | "lib/cudd/bvec_cudd.h" 17 | "lib/cudd/bvec_cudd.cpp" 18 | "lib/maybeBdd/maybeBdd.h" 19 | "lib/maybeBdd/maybeBdd.cpp" 20 | "lib/simplificationPasses/*.h" 21 | "lib/simplificationPasses/*.cpp" 22 | ) 23 | 24 | SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 25 | SET(BUILD_SHARED_LIBRARIES OFF) 26 | set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") 27 | 28 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall") 29 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall") 30 | 31 | set(Z3_DIR "contrib/z3/build" CACHE STRING "Path in which Z3 has been built") 32 | set(CUDD_DIR "contrib/cudd" CACHE STRING "Path in which CUDD has been built") 33 | set(ANTLR_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}/contrib/antlr/antlr-4.11.1-complete.jar" CACHE STRING "Path to ANTLR executable") 34 | 35 | find_package(Z3 CONFIG) 36 | set(LIBS ${LIBS} ${Z3_LIBRARIES}) 37 | include_directories(${Z3_CXX_INCLUDE_DIRS}) 38 | 39 | find_library(LibCUDD cudd 40 | HINTS ${CUDD_DIR}/cudd/.libs 41 | DOC "CUDD library" 42 | REQUIRED 43 | ) 44 | set(LIBS ${LIBS} ${LibCUDD}) 45 | include_directories(${CUDD_DIR}/cudd ${CUDD_DIR}/cplusplus) 46 | 47 | find_package(OpenMP) 48 | if (OPENMP_FOUND) 49 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 50 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 51 | endif() 52 | 53 | find_package (Threads) 54 | 55 | # required if linking to static library 56 | add_definitions(-DANTLR4CPP_STATIC) 57 | 58 | # using /MD flag for antlr4_runtime (for Visual C++ compilers only) 59 | set(ANTLR4_WITH_STATIC_CRT OFF) 60 | # add external build for antlrcpp 61 | include(ExternalAntlr4Cpp) 62 | # add antrl4cpp artifacts to project environment 63 | include_directories(SYSTEM ${ANTLR4_INCLUDE_DIRS}) 64 | 65 | find_package(ANTLR REQUIRED) 66 | 67 | # Call macro to add lexer and grammar to your build dependencies. 68 | antlr_target(SmtLibParser parser/smtlibv2-grammar/src/main/resources/SMTLIBv2.g4 VISITOR) 69 | 70 | # include generated files in project environment 71 | include_directories(SYSTEM ${ANTLR_SmtLibParser_OUTPUT_DIR}) 72 | 73 | add_library(q3blib ${Q3B_SRC} ${ANTLR_SmtLibParser_CXX_OUTPUTS}) 74 | target_link_libraries(q3blib ${CMAKE_THREAD_LIBS_INIT}) 75 | 76 | target_link_libraries(q3blib ${LIBS} antlr4_static) 77 | add_executable(q3b app/main.cpp) 78 | target_link_libraries(q3b q3blib) 79 | 80 | ### CATCH ### 81 | 82 | # Prepare "Catch" library for other executables 83 | set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests/catch) 84 | add_library(Catch INTERFACE) 85 | target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR}) 86 | 87 | # Make test executable 88 | set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests/testUnconstrained.cpp) 89 | add_executable(tests ${TEST_SOURCES}) 90 | target_link_libraries(tests PUBLIC q3blib Catch) 91 | 92 | SET(COVERAGE OFF CACHE BOOL "Coverage") 93 | if (COVERAGE) 94 | target_compile_options(tests PRIVATE --coverage) 95 | target_link_libraries(tests PRIVATE --coverage) 96 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") 97 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fprofile-arcs -ftest-coverage") 98 | endif() 99 | 100 | enable_testing() 101 | add_test(NAME RegressionNoApprox COMMAND ./tests [noapprox]) 102 | add_test(NAME RegressionVariableApprox COMMAND ./tests [variableapprox]) 103 | add_test(NAME RegressionBothLimitApprox COMMAND ./tests [bothlimitapprox]) 104 | add_test(NAME RegressionBothLimitApprox-TCI COMMAND ./tests [bothlimitapprox-tci]) 105 | add_test(NAME RegressionOperationLimitApprox-ITE COMMAND ./tests [operationapproxlimit-ite]) 106 | add_test(NAME RegressionSMTCOMP2018 COMMAND ./tests [smtcomp18]) 107 | add_test(NAME RegressionGoalUnconstrained COMMAND ./tests [goalunconstrained]) 108 | add_test(NAME RegressionParallel COMMAND ./tests [parallel]) 109 | 110 | add_test(NAME UnconstrainedBinaryTests COMMAND ./tests [verify-unconstrained-binary-functions]) 111 | add_test(NAME UnconstrainedGoalUnconstrained COMMAND ./tests [verify-goal-unconstrained]) 112 | add_test(NAME SMTLIB COMMAND ./tests [smtlib]) 113 | add_test(NAME Models COMMAND ./tests [models]) 114 | 115 | add_test(NAME BinaryHelp COMMAND ./q3b --help) 116 | add_test(NAME BinaryVersion COMMAND ./q3b --version) 117 | add_test(NAME Binary1 COMMAND ./q3b ../tests/data/AR-fixpoint-1.smt2) 118 | add_test(NAME Binary2 COMMAND ./q3b ../tests/data/accelerating-node2100.smt2) 119 | add_test(NAME Binary2Verbose COMMAND ./q3b ../tests/data/accelerating-node2100.smt2 --verbosity 10) 120 | 121 | 122 | ### STAREXEC ### 123 | 124 | add_custom_command(OUTPUT 125 | COMMAND rm -rf bin 126 | COMMAND mkdir bin 127 | COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/app/starexec_run_default" bin 128 | COMMAND cp q3b bin 129 | COMMAND tar -czf q3b_starexec.tar.gz bin 130 | COMMAND rm -rf bin 131 | OUTPUT q3b_starexec.tar.gz 132 | COMMENT "Generating starexec archive" 133 | VERBATIM 134 | ) 135 | 136 | add_custom_target(starexec DEPENDS q3b_starexec.tar.gz) 137 | -------------------------------------------------------------------------------- /tests/data/RND_6_4.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Scholl, Christoph; Disch, Stefan; Pigorsch, Florian and Kupferschmid, 5 | Stefan; Using an SMT Solver and Craig Interpolation to Detect and Remove 6 | Redundant Linear Constraints in Representations of Non-Convex Polyhedra. 7 | Proceedings of 6th International Workshop on Satisfiability Modulo 8 | Theories, Princeton, USA, July 2008. 9 | 10 | 11 | Translated to BV by Mathias Preiner. 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "random") 15 | (set-info :status unknown) 16 | (declare-fun y1 () (_ BitVec 32)) 17 | (declare-fun y3 () (_ BitVec 32)) 18 | (declare-fun y4 () (_ BitVec 32)) 19 | (declare-fun y5 () (_ BitVec 32)) 20 | (declare-fun y6 () (_ BitVec 32)) 21 | (declare-fun x1 () (_ BitVec 32)) 22 | (assert (forall ((?y1 (_ BitVec 32))) (or (forall ((?y3 (_ BitVec 32))) (exists ((?y4 (_ BitVec 32))) (or (or (or (forall ((?y5 (_ BitVec 32))) (forall ((?y6 (_ BitVec 32))) (bvslt (bvadd (bvadd (bvadd (bvadd (bvmul (_ bv30 32) ?y6) (bvmul (_ bv61 32) ?y5)) (bvmul (bvneg (_ bv94 32)) ?y4)) (bvmul (bvneg (_ bv60 32)) ?y1)) (bvmul (bvneg (_ bv22 32)) x1)) (_ bv49 32)))) (exists ((?y5 (_ BitVec 32))) (not (= (bvadd (bvadd (bvadd (bvmul (bvneg (_ bv81 32)) ?y5) (bvmul (_ bv33 32) ?y3)) (bvmul (_ bv51 32) ?y1)) (bvmul (bvneg (_ bv26 32)) x1)) (bvneg (_ bv60 32)))))) (forall ((?y6 (_ BitVec 32))) (let ((?v_0 (bvmul (bvneg (_ bv17 32)) ?y6))) (or (bvsle (bvadd (bvadd (bvadd ?v_0 (bvmul (bvneg (_ bv47 32)) ?y4)) (bvmul (bvneg (_ bv51 32)) ?y1)) (bvmul (bvneg (_ bv95 32)) x1)) (_ bv80 32)) (= (bvadd (bvadd (bvadd (bvadd ?v_0 (bvmul (_ bv98 32) ?y4)) (bvmul (bvneg (_ bv36 32)) ?y3)) (bvmul (_ bv7 32) ?y1)) (bvmul (_ bv42 32) x1)) (bvneg (_ bv94 32))))))) (and (exists ((?y5 (_ BitVec 32))) (forall ((?y6 (_ BitVec 32))) (and (bvsge (bvadd (bvadd (bvmul (_ bv36 32) ?y4) (bvmul (bvneg (_ bv17 32)) ?y3)) (bvmul (_ bv49 32) ?y1)) (_ bv0 32)) (bvsgt (bvadd (bvadd (bvadd (bvadd (bvmul (bvneg (_ bv23 32)) ?y6) (bvmul (bvneg (_ bv73 32)) ?y5)) (bvmul (_ bv5 32) ?y4)) (bvmul (bvneg (_ bv83 32)) ?y1)) (bvmul (bvneg (_ bv24 32)) x1)) (bvneg (_ bv55 32)))))) (and (exists ((?y5 (_ BitVec 32))) (forall ((?y6 (_ BitVec 32))) (bvslt (bvadd (bvadd (bvadd (bvmul (bvneg (_ bv40 32)) ?y4) (bvmul (bvneg (_ bv97 32)) ?y3)) (bvmul (bvneg (_ bv36 32)) ?y1)) (bvmul (_ bv83 32) x1)) (bvneg (_ bv59 32))))) (forall ((?y6 (_ BitVec 32))) (bvsle (bvadd (bvadd (bvmul (_ bv82 32) ?y6) (bvmul (_ bv27 32) ?y4)) (bvmul (_ bv89 32) ?y3)) (_ bv95 32)))))))) (or (or (and (or (forall ((?y5 (_ BitVec 32))) (bvsge (bvadd (bvmul (_ bv94 32) ?y5) (bvmul (bvneg (_ bv78 32)) ?y1)) (bvneg (_ bv8 32)))) (exists ((?y4 (_ BitVec 32))) (forall ((?y5 (_ BitVec 32))) (bvsge (bvadd (bvmul (_ bv24 32) ?y5) (bvmul (bvneg (_ bv2 32)) ?y4)) (_ bv76 32))))) (and (bvslt (bvadd (bvmul (_ bv24 32) ?y1) (bvmul (bvneg (_ bv35 32)) x1)) (bvneg (_ bv44 32))) (bvsgt (bvadd (bvmul (bvneg (_ bv44 32)) ?y1) (bvmul (bvneg (_ bv77 32)) x1)) (_ bv32 32)))) (exists ((?y4 (_ BitVec 32))) (and (and (= (bvadd (bvmul (bvneg (_ bv62 32)) ?y4) (bvmul (_ bv17 32) x1)) (_ bv12 32)) (not (= (bvadd (bvadd (bvmul (bvneg (_ bv22 32)) ?y4) (bvmul (bvneg (_ bv59 32)) ?y1)) (bvmul (_ bv7 32) x1)) (_ bv0 32)))) (forall ((?y6 (_ BitVec 32))) (bvsle (bvadd (bvadd (bvmul (_ bv45 32) ?y6) (bvmul (_ bv54 32) ?y4)) (bvmul (_ bv67 32) x1)) (bvneg (_ bv39 32))))))) (or (and (and (or (exists ((?y4 (_ BitVec 32))) (not (= (bvadd (bvadd (bvmul (_ bv16 32) ?y4) (bvmul (bvneg (_ bv64 32)) ?y1)) (bvmul (_ bv54 32) x1)) (_ bv63 32)))) (exists ((?y4 (_ BitVec 32))) (= (bvadd (bvadd (bvmul (bvneg (_ bv46 32)) ?y4) (bvmul (bvneg (_ bv80 32)) ?y1)) (bvmul (bvneg (_ bv53 32)) x1)) (_ bv50 32)))) (and (exists ((?y4 (_ BitVec 32))) (bvsgt (bvadd (bvmul (_ bv76 32) ?y4) (bvmul (bvneg (_ bv56 32)) ?y1)) (_ bv51 32))) (and (forall ((?y3 (_ BitVec 32))) (= (bvadd (bvadd (bvmul (bvneg (_ bv78 32)) ?y3) (bvmul (bvneg (_ bv78 32)) ?y1)) (bvmul (_ bv6 32) x1)) (_ bv39 32))) (not (= (bvadd (bvmul (bvneg (_ bv69 32)) ?y1) (bvmul (_ bv59 32) x1)) (_ bv0 32)))))) (forall ((?y3 (_ BitVec 32))) (or (or (forall ((?y4 (_ BitVec 32))) (bvsle (bvadd (bvadd (bvmul (_ bv17 32) ?y3) (bvmul (_ bv92 32) ?y1)) (bvmul (_ bv37 32) x1)) (_ bv0 32))) (forall ((?y4 (_ BitVec 32))) (bvslt (bvadd (bvadd (bvadd (bvmul (_ bv65 32) ?y4) (bvmul (_ bv73 32) ?y3)) (bvmul (bvneg (_ bv32 32)) ?y1)) (bvmul (bvneg (_ bv47 32)) x1)) (bvneg (_ bv74 32))))) (exists ((?y4 (_ BitVec 32))) (not (= (bvadd (bvmul (_ bv96 32) ?y4) (bvmul (bvneg (_ bv72 32)) x1)) (bvneg (_ bv3 32)))))))) (and (forall ((?y3 (_ BitVec 32))) (exists ((?y5 (_ BitVec 32))) (exists ((?y6 (_ BitVec 32))) (= (bvadd (bvadd (bvadd (bvadd (bvmul (bvneg (_ bv55 32)) ?y6) (bvmul (_ bv75 32) ?y5)) (bvmul (_ bv33 32) ?y3)) (bvmul (_ bv51 32) ?y1)) (bvmul (bvneg (_ bv76 32)) x1)) (_ bv0 32))))) (and (or (or (bvsge (bvmul (bvneg (_ bv73 32)) ?y1) (_ bv34 32)) (bvsgt (bvadd (bvmul (bvneg (_ bv60 32)) ?y1) (bvmul (_ bv3 32) x1)) (_ bv9 32))) (or (bvsgt (bvadd (bvmul (bvneg (_ bv12 32)) ?y1) (bvmul (bvneg (_ bv58 32)) x1)) (bvneg (_ bv87 32))) (bvsgt (bvadd (bvmul (bvneg (_ bv86 32)) ?y1) (bvmul (bvneg (_ bv37 32)) x1)) (_ bv0 32)))) (or (or (forall ((?y3 (_ BitVec 32))) (not (= (bvadd (bvmul (bvneg (_ bv45 32)) ?y3) (bvmul (bvneg (_ bv17 32)) x1)) (bvneg (_ bv67 32))))) (forall ((?y3 (_ BitVec 32))) (= (bvadd (bvmul (bvneg (_ bv19 32)) ?y1) (bvmul (_ bv20 32) x1)) (_ bv27 32)))) (forall ((?y3 (_ BitVec 32))) (bvsgt (bvadd (bvadd (bvmul (_ bv30 32) ?y3) (bvmul (_ bv17 32) ?y1)) (bvmul (bvneg (_ bv51 32)) x1)) (_ bv0 32))))))))))) 23 | (check-sat) 24 | (exit) 25 | -------------------------------------------------------------------------------- /cmake/ExternalAntlr4Cpp.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7) 2 | 3 | include(ExternalProject) 4 | 5 | set(ANTLR4_ROOT ${CMAKE_CURRENT_BINARY_DIR}/antlr4_runtime/src/antlr4_runtime) 6 | set(ANTLR4_INCLUDE_DIRS ${ANTLR4_ROOT}/runtime/Cpp/runtime/src) 7 | set(ANTLR4_GIT_REPOSITORY https://github.com/antlr/antlr4.git) 8 | if(NOT DEFINED ANTLR4_TAG) 9 | # Set to branch name to keep library updated at the cost of needing to rebuild after 'clean' 10 | # Set to commit hash to keep the build stable and does not need to rebuild after 'clean' 11 | set(ANTLR4_TAG master) 12 | endif() 13 | 14 | if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*") 15 | set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist/$(Configuration)) 16 | elseif(${CMAKE_GENERATOR} MATCHES "Xcode.*") 17 | set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist/$(CONFIGURATION)) 18 | else() 19 | set(ANTLR4_OUTPUT_DIR ${ANTLR4_ROOT}/runtime/Cpp/dist) 20 | endif() 21 | 22 | if(MSVC) 23 | set(ANTLR4_STATIC_LIBRARIES 24 | ${ANTLR4_OUTPUT_DIR}/antlr4-runtime-static.lib) 25 | set(ANTLR4_SHARED_LIBRARIES 26 | ${ANTLR4_OUTPUT_DIR}/antlr4-runtime.lib) 27 | set(ANTLR4_RUNTIME_LIBRARIES 28 | ${ANTLR4_OUTPUT_DIR}/antlr4-runtime.dll) 29 | else() 30 | set(ANTLR4_STATIC_LIBRARIES 31 | ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.a) 32 | if(MINGW) 33 | set(ANTLR4_SHARED_LIBRARIES 34 | ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a) 35 | set(ANTLR4_RUNTIME_LIBRARIES 36 | ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll) 37 | elseif(CYGWIN) 38 | set(ANTLR4_SHARED_LIBRARIES 39 | ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dll.a) 40 | set(ANTLR4_RUNTIME_LIBRARIES 41 | ${ANTLR4_OUTPUT_DIR}/cygantlr4-runtime-4.10.1.dll) 42 | elseif(APPLE) 43 | set(ANTLR4_RUNTIME_LIBRARIES 44 | ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.dylib) 45 | else() 46 | set(ANTLR4_RUNTIME_LIBRARIES 47 | ${ANTLR4_OUTPUT_DIR}/libantlr4-runtime.so) 48 | endif() 49 | endif() 50 | 51 | if(${CMAKE_GENERATOR} MATCHES ".* Makefiles") 52 | # This avoids 53 | # 'warning: jobserver unavailable: using -j1. Add '+' to parent make rule.' 54 | set(ANTLR4_BUILD_COMMAND $(MAKE)) 55 | elseif(${CMAKE_GENERATOR} MATCHES "Visual Studio.*") 56 | set(ANTLR4_BUILD_COMMAND 57 | ${CMAKE_COMMAND} 58 | --build . 59 | --config $(Configuration) 60 | --target) 61 | elseif(${CMAKE_GENERATOR} MATCHES "Xcode.*") 62 | set(ANTLR4_BUILD_COMMAND 63 | ${CMAKE_COMMAND} 64 | --build . 65 | --config $(CONFIGURATION) 66 | --target) 67 | else() 68 | set(ANTLR4_BUILD_COMMAND 69 | ${CMAKE_COMMAND} 70 | --build . 71 | --target) 72 | endif() 73 | 74 | if(NOT DEFINED ANTLR4_WITH_STATIC_CRT) 75 | set(ANTLR4_WITH_STATIC_CRT ON) 76 | endif() 77 | 78 | if(ANTLR4_ZIP_REPOSITORY) 79 | ExternalProject_Add( 80 | antlr4_runtime 81 | PREFIX antlr4_runtime 82 | URL ${ANTLR4_ZIP_REPOSITORY} 83 | DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR} 84 | BUILD_COMMAND "" 85 | BUILD_IN_SOURCE 1 86 | SOURCE_DIR ${ANTLR4_ROOT} 87 | SOURCE_SUBDIR runtime/Cpp 88 | CMAKE_CACHE_ARGS 89 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 90 | -DWITH_STATIC_CRT:BOOL=${ANTLR4_WITH_STATIC_CRT} 91 | # -DCMAKE_CXX_STANDARD:STRING=17 # if desired, compile the runtime with a different C++ standard 92 | # -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} # alternatively, compile the runtime with the same C++ standard as the outer project 93 | INSTALL_COMMAND "" 94 | EXCLUDE_FROM_ALL 1) 95 | else() 96 | ExternalProject_Add( 97 | antlr4_runtime 98 | PREFIX antlr4_runtime 99 | GIT_REPOSITORY ${ANTLR4_GIT_REPOSITORY} 100 | GIT_TAG ${ANTLR4_TAG} 101 | DOWNLOAD_DIR ${CMAKE_CURRENT_BINARY_DIR} 102 | BUILD_COMMAND "" 103 | BUILD_IN_SOURCE 1 104 | SOURCE_DIR ${ANTLR4_ROOT} 105 | SOURCE_SUBDIR runtime/Cpp 106 | CMAKE_CACHE_ARGS 107 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 108 | -DWITH_STATIC_CRT:BOOL=${ANTLR4_WITH_STATIC_CRT} 109 | # -DCMAKE_CXX_STANDARD:STRING=17 # if desired, compile the runtime with a different C++ standard 110 | # -DCMAKE_CXX_STANDARD:STRING=${CMAKE_CXX_STANDARD} # alternatively, compile the runtime with the same C++ standard as the outer project 111 | INSTALL_COMMAND "" 112 | EXCLUDE_FROM_ALL 1) 113 | endif() 114 | 115 | # Separate build step as rarely people want both 116 | set(ANTLR4_BUILD_DIR ${ANTLR4_ROOT}) 117 | if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0") 118 | # CMake 3.14 builds in above's SOURCE_SUBDIR when BUILD_IN_SOURCE is true 119 | set(ANTLR4_BUILD_DIR ${ANTLR4_ROOT}/runtime/Cpp) 120 | endif() 121 | 122 | ExternalProject_Add_Step( 123 | antlr4_runtime 124 | build_static 125 | COMMAND ${ANTLR4_BUILD_COMMAND} antlr4_static 126 | # Depend on target instead of step (a custom command) 127 | # to avoid running dependent steps concurrently 128 | DEPENDS antlr4_runtime 129 | BYPRODUCTS ${ANTLR4_STATIC_LIBRARIES} 130 | EXCLUDE_FROM_MAIN 1 131 | WORKING_DIRECTORY ${ANTLR4_BUILD_DIR}) 132 | ExternalProject_Add_StepTargets(antlr4_runtime build_static) 133 | 134 | add_library(antlr4_static STATIC IMPORTED) 135 | add_dependencies(antlr4_static antlr4_runtime-build_static) 136 | set_target_properties(antlr4_static PROPERTIES 137 | IMPORTED_LOCATION ${ANTLR4_STATIC_LIBRARIES}) 138 | 139 | ExternalProject_Add_Step( 140 | antlr4_runtime 141 | build_shared 142 | COMMAND ${ANTLR4_BUILD_COMMAND} antlr4_shared 143 | # Depend on target instead of step (a custom command) 144 | # to avoid running dependent steps concurrently 145 | DEPENDS antlr4_runtime 146 | BYPRODUCTS ${ANTLR4_SHARED_LIBRARIES} ${ANTLR4_RUNTIME_LIBRARIES} 147 | EXCLUDE_FROM_MAIN 1 148 | WORKING_DIRECTORY ${ANTLR4_BUILD_DIR}) 149 | ExternalProject_Add_StepTargets(antlr4_runtime build_shared) 150 | 151 | add_library(antlr4_shared SHARED IMPORTED) 152 | add_dependencies(antlr4_shared antlr4_runtime-build_shared) 153 | set_target_properties(antlr4_shared PROPERTIES 154 | IMPORTED_LOCATION ${ANTLR4_RUNTIME_LIBRARIES}) 155 | if(ANTLR4_SHARED_LIBRARIES) 156 | set_target_properties(antlr4_shared PROPERTIES 157 | IMPORTED_IMPLIB ${ANTLR4_SHARED_LIBRARIES}) 158 | endif() 159 | -------------------------------------------------------------------------------- /app/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../lib/Solver.h" 8 | #include "../lib/Logger.h" 9 | #include "../lib/Config.h" 10 | #include "../lib/SMTLIBInterpreter.h" 11 | 12 | #include "antlr4-runtime.h" 13 | #include "SMTLIBv2Lexer.h" 14 | #include "SMTLIBv2Parser.h" 15 | 16 | using namespace std; 17 | using namespace z3; 18 | using namespace antlr4; 19 | 20 | const std::string version = "1.1"; 21 | 22 | void print_usage() 23 | { 24 | std::cout << "Q3B (version " << version << ")" << std::endl; 25 | std::cout << "Usage: q3b [options] file.smt2" << std::endl << std::endl; 26 | 27 | std::cout << "Supported options without parameters:" << std::endl; 28 | std::cout << " --help print this help" << std::endl; 29 | std::cout << " --version print version" << std::endl << std::endl; 30 | 31 | std::cout << "Supported options with parameters [--option=value]:" << std::endl; 32 | std::cout << " --abstractions use abstractions (none|under|over|all) [all]" << std::endl; 33 | std::cout << " --abstract:methods type of abstractions (variables|operations|both) [both]" << std::endl; 34 | std::cout << " --abstract:check-models check models produces by overapproximation [1]" << std::endl; 35 | std::cout << " --abstract:necessary-bits deduce forced values of bits from overapproximation [1]" << std::endl; 36 | std::cout << " --simpl:add-congruences add congruences for expensive operations [1]" << std::endl; 37 | std::cout << " --simpl:unconstrained use unconstrained variable simplification [1]" << std::endl; 38 | std::cout << " --uc:goal take goals of unconstrained variables into account [1]" << std::endl; 39 | std::cout << " --bdd:reorder BDD reorder type (none|win2|win2ite|win3|win3ite|sift|siftite) [sift]" << std::endl; 40 | std::cout << " --simpl:flip-universal negate universal formulas [0]" << std::endl; 41 | std::cout << " --verbosity set level of debugging outputs [0]" << std::endl; 42 | } 43 | 44 | 45 | int main(int argc, char* argv[]) 46 | { 47 | static struct option long_options[] = { 48 | {"abstractions", required_argument, 0, 'a' }, 49 | {"abstract:method", required_argument, 0, 'm' }, 50 | {"abstract:check-models", required_argument, 0, 'c' }, 51 | {"abstract:necessary-bits", required_argument, 0, 'b' }, 52 | {"simpl:unconstrained", required_argument, 0, 'p' }, 53 | {"simpl:add-congruences", required_argument, 0, 'C' }, 54 | {"uc:goal", required_argument, 0, 'g' }, 55 | {"bdd:reorder", required_argument, 0, 'r' }, 56 | {"simpl:flip-universal", required_argument, 0, 'f' }, 57 | {"verbosity", required_argument, 0, 'v' }, 58 | {"version", no_argument, 0, 'V' }, 59 | {"help", no_argument, 0, 'h' }, 60 | {0, 0, 0, 0 } 61 | }; 62 | 63 | std::string filename; 64 | Config config; 65 | 66 | int opt = 0; 67 | int long_index = 0; 68 | while ((opt = getopt_long(argc, argv,"a:m:b:p:g:r:i:c:C:f:v:hV", long_options, &long_index )) != -1) { 69 | switch (opt) { 70 | case 'a': 71 | { 72 | string optionString(optarg); 73 | 74 | config.approximations = NO_APPROXIMATIONS; 75 | if (optionString == "over") config.approximations = ONLY_OVERAPPROXIMATIONS; 76 | else if (optionString == "under") config.approximations = ONLY_UNDERAPPROXIMATIONS; 77 | else if (optionString == "all") config.approximations = ALL_APPROXIMATIONS; 78 | break; 79 | } 80 | case 'p': 81 | config.propagateUnconstrained = atoi(optarg); 82 | break; 83 | case 'c': 84 | config.checkModels = atoi(optarg); 85 | break; 86 | case 'C': 87 | config.addCongruences = atoi(optarg); 88 | break; 89 | case 'f': 90 | config.flipUniversalQuantifier = atoi(optarg); 91 | break; 92 | case 'b': 93 | config.propagateNecessaryBits = atoi(optarg); 94 | break; 95 | case 'g': 96 | config.goalUnconstrained = atoi(optarg); 97 | break; 98 | case 'r': 99 | { 100 | string optionString(optarg); 101 | 102 | if (optionString == "win2") config.reorderType = WIN2; 103 | else if (optionString == "win2ite") config.reorderType = WIN2_ITE; 104 | else if (optionString == "win3") config.reorderType = WIN3; 105 | else if (optionString == "win3ite") config.reorderType = WIN3_ITE; 106 | else if (optionString == "sift") config.reorderType = SIFT; 107 | else if (optionString == "siftite") config.reorderType = SIFT_ITE; 108 | else if (optionString == "none") config.reorderType = NO_REORDER; 109 | else 110 | { 111 | std::cout << "Invalid reorder type" << std::endl; 112 | print_usage(); 113 | exit(1); 114 | } 115 | 116 | break; 117 | } 118 | case 'm': 119 | { 120 | string optionString(optarg); 121 | 122 | if (optionString == "variables") config.approximationMethod = VARIABLES; 123 | else if (optionString == "operations") config.approximationMethod = OPERATIONS; 124 | else if (optionString == "both") config.approximationMethod = BOTH; 125 | else 126 | { 127 | std::cout << "Invalid abstraction method" << std::endl; 128 | print_usage(); 129 | exit(1); 130 | } 131 | break; 132 | } 133 | case 'v': 134 | { 135 | Logger::SetVerbosity(atoi(optarg)); 136 | break; 137 | } 138 | case 'V': 139 | { 140 | std::cout << "Q3B version " << version << std::endl; 141 | return 0; 142 | } 143 | case 'h': 144 | { 145 | print_usage(); 146 | return 0; 147 | } 148 | 149 | default: 150 | std::cout << "Invalid arguments" << std::endl << std::endl; 151 | print_usage(); 152 | return 1; 153 | } 154 | } 155 | 156 | if (optind < argc) 157 | { 158 | filename = std::string(argv[optind]); 159 | } 160 | else 161 | { 162 | std::cout << "Filename required" << std::endl; 163 | print_usage(); 164 | return 1; 165 | } 166 | 167 | Solver solver(config); 168 | 169 | std::ifstream stream; 170 | stream.open(filename); 171 | if (!stream.good()) 172 | { 173 | std::cout << "(error \"failed to open file '" << filename << "'\")" << std::endl; 174 | return 1; 175 | } 176 | 177 | ANTLRInputStream input(stream); 178 | SMTLIBv2Lexer lexer(&input); 179 | CommonTokenStream tokens(&lexer); 180 | SMTLIBv2Parser parser(&tokens); 181 | 182 | SMTLIBv2Parser::StartContext* tree = parser.start(); 183 | 184 | SMTLIBInterpreter interpreter; 185 | interpreter.SetConfig(config); 186 | interpreter.Run(tree->script()); 187 | } 188 | -------------------------------------------------------------------------------- /tests/data/RNDPRE_3_48.smt2: -------------------------------------------------------------------------------- 1 | (set-info :smt-lib-version 2.6) 2 | (set-logic BV) 3 | (set-info :source | 4 | Scholl, Christoph; Disch, Stefan; Pigorsch, Florian and Kupferschmid, 5 | Stefan; Using an SMT Solver and Craig Interpolation to Detect and Remove 6 | Redundant Linear Constraints in Representations of Non-Convex Polyhedra. 7 | Proceedings of 6th International Workshop on Satisfiability Modulo 8 | Theories, Princeton, USA, July 2008. 9 | 10 | 11 | Translated to BV by Mathias Preiner. 12 | |) 13 | (set-info :license "https://creativecommons.org/licenses/by/4.0/") 14 | (set-info :category "random") 15 | (set-info :status unknown) 16 | (declare-fun x1 () (_ BitVec 32)) 17 | (declare-fun x2 () (_ BitVec 32)) 18 | (declare-fun x3 () (_ BitVec 32)) 19 | (assert (exists ((?x1 (_ BitVec 32))) (forall ((?x2 (_ BitVec 32))) (exists ((?x3 (_ BitVec 32))) (let ((?v_5 (bvmul (_ bv94 32) ?x1)) (?v_1 (bvmul (_ bv66 32) ?x1)) (?v_13 (bvmul (_ bv13 32) ?x3)) (?v_7 (bvmul (_ bv64 32) ?x3)) (?v_9 (bvmul (_ bv44 32) ?x3)) (?v_20 (bvmul (_ bv17 32) ?x1)) (?v_4 (bvmul (_ bv51 32) ?x1)) (?v_11 (bvmul (_ bv80 32) ?x2)) (?v_15 (bvmul (_ bv55 32) ?x2)) (?v_21 (bvmul (_ bv20 32) ?x3)) (?v_17 (bvmul (_ bv24 32) ?x1)) (?v_12 (bvmul (_ bv29 32) ?x3)) (?v_16 (bvmul (_ bv30 32) ?x3)) (?v_14 (bvmul (bvneg (_ bv85 32)) ?x1)) (?v_2 (bvmul (bvneg (_ bv52 32)) ?x2)) (?v_6 (bvmul (bvneg (_ bv95 32)) ?x3)) (?v_3 (bvmul (bvneg (_ bv10 32)) ?x1)) (?v_0 (bvmul (bvneg (_ bv68 32)) ?x3)) (?v_8 (bvmul (bvneg (_ bv93 32)) ?x3)) (?v_10 (bvmul (bvneg (_ bv49 32)) ?x3)) (?v_19 (bvmul (bvneg (_ bv27 32)) ?x2)) (?v_18 (bvmul (bvneg (_ bv28 32)) ?x1))) (or (and (or (or (and (and (bvsge (bvadd (bvadd ?v_14 ?v_2) (bvmul (_ bv65 32) ?x3)) (bvneg (_ bv77 32))) (bvsle (bvadd (bvmul (bvneg (_ bv72 32)) ?x1) (bvmul (_ bv52 32) ?x3)) (_ bv77 32))) (not (= (bvadd (bvadd (bvmul (_ bv67 32) ?x1) (bvmul (bvneg (_ bv16 32)) ?x2)) ?v_6) (bvneg (_ bv34 32))))) (or (or (bvsge (bvmul (bvneg (_ bv44 32)) ?x1) (bvneg (_ bv80 32))) (bvsle (bvadd (bvadd ?v_5 (bvmul (_ bv64 32) ?x2)) (bvmul (_ bv95 32) ?x3)) (bvneg (_ bv13 32)))) (not (= (bvadd (bvmul (_ bv59 32) ?x2) (bvmul (_ bv37 32) ?x3)) (bvneg (_ bv64 32)))))) (= (bvadd (bvmul (_ bv48 32) ?x1) (bvmul (_ bv70 32) ?x3)) (_ bv69 32))) (or (or (or (or (and (and (= (bvadd (bvadd ?v_3 (bvmul (_ bv32 32) ?x2)) (bvmul (_ bv7 32) ?x3)) (_ bv0 32)) (bvsle (bvmul (bvneg (_ bv31 32)) ?x2) (_ bv32 32))) (and (bvsgt (bvadd (bvadd (bvmul (bvneg (_ bv6 32)) ?x1) (bvmul (_ bv96 32) ?x2)) (bvmul (_ bv90 32) ?x3)) (_ bv0 32)) (not (= (bvadd (bvmul (bvneg (_ bv25 32)) ?x1) (bvmul (bvneg (_ bv30 32)) ?x3)) (bvneg (_ bv6 32)))))) (or (bvslt (bvadd (bvadd (bvmul (bvneg (_ bv16 32)) ?x1) (bvmul (bvneg (_ bv94 32)) ?x2)) ?v_0) (_ bv61 32)) (or (bvsgt (bvmul (bvneg (_ bv98 32)) ?x3) (_ bv0 32)) (bvsgt (bvadd (bvmul (bvneg (_ bv9 32)) ?x2) (bvmul (bvneg (_ bv12 32)) ?x3)) (bvneg (_ bv24 32)))))) (and (and (and (bvsgt (bvadd (bvmul (bvneg (_ bv43 32)) ?x1) (bvmul (bvneg (_ bv14 32)) ?x3)) (_ bv0 32)) (bvsge (bvadd ?v_1 ?v_0) (bvneg (_ bv47 32)))) (and (bvslt (bvadd (bvadd ?v_1 (bvmul (_ bv20 32) ?x2)) (bvmul (_ bv10 32) ?x3)) (_ bv4 32)) (not (= (bvadd (bvadd (bvmul (bvneg (_ bv29 32)) ?x1) (bvmul (_ bv26 32) ?x2)) (bvmul (bvneg (_ bv100 32)) ?x3)) (_ bv30 32))))) (bvslt (bvmul (_ bv39 32) ?x3) (_ bv0 32)))) (and (not (= (bvadd (bvmul (_ bv67 32) ?x2) ?v_13) (bvneg (_ bv1 32)))) (and (or (and (not (= (bvadd (bvmul (bvneg (_ bv62 32)) ?x1) ?v_7) (bvneg (_ bv48 32)))) (bvslt (bvadd (bvadd (bvmul (bvneg (_ bv58 32)) ?x1) (bvmul (bvneg (_ bv11 32)) ?x2)) ?v_9) (bvneg (_ bv14 32)))) (or (bvslt (bvadd ?v_2 (bvmul (_ bv4 32) ?x3)) (_ bv0 32)) (bvsge (bvmul (bvneg (_ bv83 32)) ?x3) (_ bv22 32)))) (and (and (bvsgt (bvadd ?v_20 (bvmul (bvneg (_ bv91 32)) ?x3)) (bvneg (_ bv36 32))) (not (= (bvadd (bvadd ?v_4 (bvmul (bvneg (_ bv47 32)) ?x2)) (bvmul (_ bv28 32) ?x3)) (_ bv99 32)))) (and (bvsle (bvadd (bvmul (_ bv16 32) ?x2) (bvmul (bvneg (_ bv76 32)) ?x3)) (_ bv89 32)) (bvsge (bvadd (bvadd ?v_3 (bvmul (_ bv77 32) ?x2)) (bvmul (bvneg (_ bv66 32)) ?x3)) (_ bv73 32))))))) (and (and (and (= (bvadd (bvmul (_ bv54 32) ?x1) (bvmul (_ bv47 32) ?x3)) (_ bv83 32)) (or (bvslt (bvmul (_ bv74 32) ?x2) (_ bv46 32)) (not (= (bvmul (_ bv21 32) ?x1) (_ bv0 32))))) (and (and (not (= (bvadd (bvadd (bvmul (_ bv7 32) ?x1) (bvmul (_ bv44 32) ?x2)) (bvmul (_ bv50 32) ?x3)) (_ bv14 32))) (bvsge (bvadd (bvadd ?v_4 (bvmul (bvneg (_ bv25 32)) ?x2)) (bvmul (bvneg (_ bv44 32)) ?x3)) (bvneg (_ bv47 32)))) (or (not (= (bvmul (_ bv50 32) ?x1) (bvneg (_ bv67 32)))) (bvsgt ?v_5 (_ bv20 32))))) (and (and (and (not (= (bvadd (bvadd (bvmul (_ bv39 32) ?x1) (bvmul (_ bv78 32) ?x2)) ?v_6) (_ bv0 32))) (= (bvadd (bvadd (bvmul (_ bv91 32) ?x1) ?v_11) ?v_7) (bvneg (_ bv33 32)))) (and (bvsle (bvadd (bvadd (bvmul (_ bv47 32) ?x1) (bvmul (_ bv73 32) ?x2)) ?v_8) (bvneg (_ bv60 32))) (= (bvadd ?v_15 (bvmul (bvneg (_ bv59 32)) ?x3)) (bvneg (_ bv48 32))))) (or (and (bvsge (bvadd (bvadd (bvmul (bvneg (_ bv89 32)) ?x1) (bvmul (_ bv6 32) ?x2)) (bvmul (bvneg (_ bv20 32)) ?x3)) (bvneg (_ bv98 32))) (bvsge (bvadd (bvmul (bvneg (_ bv64 32)) ?x1) (bvmul (_ bv99 32) ?x2)) (_ bv0 32))) (not (= (bvadd (bvadd (bvmul (_ bv95 32) ?x1) (bvmul (bvneg (_ bv6 32)) ?x2)) ?v_21) (_ bv12 32)))))))) (or (and (or (and (or (bvsgt ?v_4 (_ bv51 32)) (not (= (bvadd (bvadd ?v_17 (bvmul (_ bv86 32) ?x2)) ?v_10) (_ bv3 32)))) (and (bvsge (bvadd (bvmul (bvneg (_ bv37 32)) ?x1) (bvmul (_ bv16 32) ?x3)) (_ bv34 32)) (not (= (bvadd (bvmul (_ bv69 32) ?x2) ?v_8) (bvneg (_ bv78 32)))))) (and (and (bvslt (bvadd (bvmul (_ bv51 32) ?x2) ?v_12) (bvneg (_ bv95 32))) (not (= (bvadd (bvmul (bvneg (_ bv66 32)) ?x1) (bvmul (_ bv87 32) ?x2)) (_ bv69 32)))) (and (bvsgt (bvadd (bvmul (bvneg (_ bv67 32)) ?x1) ?v_9) (bvneg (_ bv54 32))) (bvsgt (bvadd (bvmul (_ bv57 32) ?x1) (bvmul (bvneg (_ bv2 32)) ?x3)) (_ bv0 32))))) (and (or (and (not (= (bvadd (bvmul (_ bv53 32) ?x2) (bvmul (bvneg (_ bv5 32)) ?x3)) (_ bv24 32))) (bvsle (bvadd (bvmul (bvneg (_ bv7 32)) ?x2) ?v_6) (bvneg (_ bv37 32)))) (bvsge (bvadd (bvadd (bvmul (_ bv63 32) ?x1) (bvmul (bvneg (_ bv40 32)) ?x2)) (bvmul (_ bv12 32) ?x3)) (bvneg (_ bv17 32)))) (or (or (not (= (bvadd (bvadd (bvmul (_ bv20 32) ?x1) ?v_19) (bvmul (_ bv32 32) ?x3)) (_ bv27 32))) (bvslt (bvadd (bvmul (_ bv49 32) ?x2) (bvmul (bvneg (_ bv80 32)) ?x3)) (_ bv1 32))) (and (not (= (bvadd (bvmul (bvneg (_ bv82 32)) ?x1) (bvmul (bvneg (_ bv63 32)) ?x2)) (_ bv75 32))) (bvsge (bvadd (bvmul (_ bv34 32) ?x2) ?v_10) (bvneg (_ bv62 32))))))) (or (and (not (= (bvadd ?v_18 ?v_16) (bvneg (_ bv39 32)))) (not (= (bvadd (bvmul (_ bv22 32) ?x2) (bvmul (_ bv71 32) ?x3)) (bvneg (_ bv96 32))))) (and (or (and (and (bvsle (bvadd (bvadd (bvmul (_ bv55 32) ?x1) ?v_11) ?v_12) (_ bv0 32)) (or (not (= (bvadd (bvmul (bvneg (_ bv99 32)) ?x2) ?v_13) (bvneg (_ bv9 32)))) (= (bvadd (bvmul (bvneg (_ bv61 32)) ?x1) (bvmul (_ bv66 32) ?x3)) (_ bv0 32)))) (and (or (bvsge (bvadd (bvmul (bvneg (_ bv27 32)) ?x1) (bvmul (bvneg (_ bv46 32)) ?x2)) (bvneg (_ bv11 32))) (bvsge (bvadd (bvadd (bvmul (_ bv82 32) ?x1) (bvmul (bvneg (_ bv13 32)) ?x2)) (bvmul (bvneg (_ bv32 32)) ?x3)) (bvneg (_ bv32 32)))) (bvslt (bvadd (bvmul (_ bv22 32) ?x1) (bvmul (_ bv18 32) ?x3)) (_ bv0 32)))) (or (and (and (bvsgt (bvadd ?v_14 (bvmul (bvneg (_ bv86 32)) ?x3)) (_ bv0 32)) (bvsle (bvadd (bvmul (_ bv17 32) ?x2) (bvmul (_ bv73 32) ?x3)) (_ bv80 32))) (and (bvsle (bvadd (bvadd (bvmul (bvneg (_ bv74 32)) ?x1) ?v_15) (bvmul (_ bv92 32) ?x3)) (_ bv83 32)) (bvsle (bvadd (bvmul (bvneg (_ bv19 32)) ?x1) (bvmul (_ bv59 32) ?x3)) (bvneg (_ bv46 32))))) (or (and (bvslt (bvadd (bvmul (_ bv35 32) ?x1) ?v_16) (bvneg (_ bv23 32))) (not (= (bvadd (bvmul (bvneg (_ bv90 32)) ?x1) (bvmul (bvneg (_ bv65 32)) ?x3)) (_ bv33 32)))) (or (bvslt (bvadd (bvadd ?v_17 (bvmul (_ bv62 32) ?x2)) (bvmul (_ bv5 32) ?x3)) (_ bv0 32)) (bvslt (bvadd (bvadd (bvmul (bvneg (_ bv60 32)) ?x1) (bvmul (bvneg (_ bv21 32)) ?x2)) (bvmul (_ bv54 32) ?x3)) (_ bv0 32)))))) (or (or (or (= (bvadd ?v_18 (bvmul (bvneg (_ bv34 32)) ?x3)) (_ bv90 32)) (bvsle (bvadd (bvadd (bvmul (bvneg (_ bv20 32)) ?x1) ?v_19) (bvmul (_ bv57 32) ?x3)) (_ bv48 32))) (and (bvsle (bvadd (bvadd (bvmul (_ bv30 32) ?x1) (bvmul (bvneg (_ bv32 32)) ?x2)) (bvmul (bvneg (_ bv70 32)) ?x3)) (_ bv0 32)) (bvslt (bvadd (bvmul (_ bv36 32) ?x1) (bvmul (bvneg (_ bv22 32)) ?x2)) (bvneg (_ bv53 32))))) (or (or (bvslt (bvadd (bvmul (_ bv40 32) ?x1) (bvmul (_ bv11 32) ?x2)) (bvneg (_ bv29 32))) (= (bvmul (bvneg (_ bv79 32)) ?x1) (bvneg (_ bv33 32)))) (not (= (bvadd ?v_20 ?v_21) (bvneg (_ bv84 32))))))))))))))) 20 | (check-sat) 21 | (exit) 22 | -------------------------------------------------------------------------------- /lib/ExprToBDDTransformer.h: -------------------------------------------------------------------------------- 1 | #ifndef ExprToBDDTransformer_h 2 | #define ExprToBDDTransformer_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "cudd.h" 11 | #include 12 | #include "cudd/bvec_cudd.h" 13 | #include 14 | #include "VariableOrderer.h" 15 | #include "Approximated.h" 16 | #include "Config.h" 17 | #include "BDDInterval.h" 18 | #include "Model.h" 19 | 20 | typedef std::pair var; 21 | 22 | enum BoundType { EXISTENTIAL, UNIVERSAL }; 23 | enum ApproximationType { ZERO_EXTEND, SIGN_EXTEND }; 24 | enum Approximation { UNDERAPPROXIMATION, OVERAPPROXIMATION, NO_APPROXIMATION }; 25 | 26 | typedef std::pair boundVar; 27 | 28 | using namespace cudd; 29 | 30 | class ExprToBDDTransformer 31 | { 32 | private: 33 | Cudd bddManager; 34 | 35 | std::map vars; 36 | std::map varSets; 37 | std::map> varIndices; 38 | std::map varSorts; 39 | 40 | std::set constSet; 41 | std::set boundVarSet; 42 | 43 | std::map, std::pair>> bddExprCache; 44 | std::map, std::vector>> bvecExprCache; 45 | 46 | std::map, std::pair>> preciseBdds; 47 | std::map, std::vector>> preciseBvecs; 48 | 49 | int lastBW = 0; 50 | std::map, std::pair>> sameBWPreciseBdds; 51 | std::map, std::vector>> sameBWPreciseBvecs; 52 | 53 | Approximated insertIntoCaches(const z3::expr&, const Approximated&, const std::vector&); 54 | BDDInterval insertIntoCaches(const z3::expr&, const BDDInterval&, const std::vector&, bool); 55 | 56 | std::set processedVarsCache; 57 | 58 | z3::context* context; 59 | 60 | void getVars(const z3::expr &e); 61 | void loadVars(); 62 | 63 | BDDInterval loadBDDsFromExpr(z3::expr); 64 | bool correctBoundVars(const std::vector&, const std::vector&) const; 65 | BDDInterval getBDDFromExpr(const z3::expr&, const std::vector&, bool onlyExistentials, bool isPositive); 66 | Approximated getApproximatedVariable(const std::string&, int, const ApproximationType&); 67 | Approximated getBvecFromExpr(const z3::expr&, const std::vector&); 68 | 69 | unsigned int getNumeralValue(const z3::expr&) const; 70 | Bvec getNumeralBvec(const z3::expr&); 71 | bool isMinusOne(const Bvec&); 72 | 73 | template < typename Top, typename TisDefinite, typename TdefaultResult > 74 | BDDInterval getConnectiveBdd(const std::vector& arguments, const std::vector& boundVars, bool onlyExistentials, bool isPositive, 75 | Top&& op, TisDefinite&& isDefinite, TdefaultResult&& defaultResult) 76 | { 77 | std::vector results; 78 | 79 | for (unsigned int i = 0; i < arguments.size(); i++) 80 | { 81 | if (isInterrupted()) { return defaultResult; } 82 | auto argBdd = getBDDFromExpr(arguments[i], boundVars, onlyExistentials, isPositive); 83 | 84 | if (isDefinite(argBdd)) { return argBdd; } 85 | else { results.push_back(argBdd); } 86 | } 87 | 88 | if (results.size() == 0) { return defaultResult; } 89 | else 90 | { 91 | std::sort(results.begin(), results.end(), 92 | [&](const auto a, const auto b) -> bool 93 | { 94 | return bddManager.nodeCount(std::vector{a.upper}) < bddManager.nodeCount(std::vector{b.upper}); 95 | }); 96 | 97 | auto toReturn = results.at(0); 98 | 99 | for (unsigned int i = 1; i < results.size(); i++) 100 | { 101 | if (isInterrupted()) { return defaultResult; } 102 | if (isDefinite(toReturn)) { return toReturn; } 103 | 104 | toReturn = op(toReturn, results.at(i)); 105 | } 106 | 107 | return toReturn; 108 | } 109 | } 110 | 111 | BDDInterval getConjunctionBdd(const std::vector&, const std::vector&, bool, bool); 112 | BDDInterval getDisjunctionBdd(const std::vector&, const std::vector&, bool, bool); 113 | 114 | Approximation approximation; 115 | int variableBitWidth; 116 | 117 | unsigned int operationPrecision; 118 | 119 | ApproximationType approximationType; 120 | 121 | bool variableApproximationHappened = false; 122 | bool operationApproximationHappened = false; 123 | 124 | int cacheHits = 0; 125 | 126 | Bvec bvec_mul(Bvec&, Bvec&); 127 | BDDInterval bvec_ule(Bvec&, Bvec&, bool); 128 | BDDInterval bvec_ult(Bvec&, Bvec&, bool); 129 | Approximated bvec_assocOp(const z3::expr&, const std::function&, const std::vector&); 130 | Approximated bvec_binOp(const z3::expr&, const std::function&, const std::vector&); 131 | Approximated bvec_unOp(const z3::expr&, const std::function&, const std::vector&); 132 | 133 | Config config; 134 | 135 | void clearCaches(); 136 | 137 | template< int n > 138 | void checkNumberOfArguments(const z3::expr& e) 139 | { 140 | if (e.num_args() != n) 141 | { 142 | std::cout << e << " -- unsupported number of arguments" << std::endl; 143 | std::cout << "unknown" << std::endl; 144 | exit(1); 145 | } 146 | } 147 | 148 | bool isInterrupted(); 149 | 150 | public: 151 | ExprToBDDTransformer(z3::context& context, z3::expr e, Config config); 152 | 153 | z3::expr expression; 154 | BDD Proccess(); 155 | 156 | BDDInterval ProcessUnderapproximation(int, unsigned int); 157 | BDDInterval ProcessOverapproximation(int, unsigned int); 158 | 159 | void setApproximationType(ApproximationType at) 160 | { 161 | approximationType = at; 162 | } 163 | 164 | bool IsPreciseResult() 165 | { 166 | return !variableApproximationHappened && !operationApproximationHappened; 167 | } 168 | 169 | bool VariableApproximationHappened() 170 | { 171 | return variableApproximationHappened; 172 | } 173 | 174 | bool OperationApproximationHappened() 175 | { 176 | return operationApproximationHappened; 177 | } 178 | 179 | void configureReorder() 180 | { 181 | if (config.reorderType != NO_REORDER) 182 | { 183 | switch (config.reorderType) 184 | { 185 | case WIN2: 186 | bddManager.AutodynEnable(CUDD_REORDER_WINDOW2); 187 | break; 188 | case WIN2_ITE: 189 | bddManager.AutodynEnable(CUDD_REORDER_WINDOW2_CONV); 190 | break; 191 | case WIN3: 192 | bddManager.AutodynEnable(CUDD_REORDER_WINDOW3); 193 | break; 194 | case WIN3_ITE: 195 | bddManager.AutodynEnable(CUDD_REORDER_WINDOW3_CONV); 196 | break; 197 | case SIFT: 198 | bddManager.SetMaxGrowth(1.05); 199 | bddManager.SetSiftMaxVar(1); 200 | bddManager.AutodynEnable(CUDD_REORDER_SYMM_SIFT); 201 | break; 202 | case SIFT_ITE: 203 | bddManager.SetMaxGrowth(1.05); 204 | bddManager.SetSiftMaxVar(1); 205 | bddManager.AutodynEnable(CUDD_REORDER_SYMM_SIFT_CONV); 206 | break; 207 | default: 208 | break; 209 | } 210 | } 211 | } 212 | 213 | void configureTermination(); 214 | 215 | void PrintModel(const std::map> &); 216 | Model GetModel(BDD); 217 | 218 | void PrintNecessaryValues(BDD); 219 | void PrintNecessaryVarValues(BDD, const std::string&); 220 | }; 221 | 222 | #endif 223 | -------------------------------------------------------------------------------- /tests/testUnconstrained.cpp: -------------------------------------------------------------------------------- 1 | #include "catch.hpp" 2 | 3 | #include 4 | #include "../lib/UnconstrainedVariableSimplifier.h" 5 | #include 6 | #include 7 | 8 | using namespace z3; 9 | 10 | bool CheckUnsatOrPrintModel(solver& s) 11 | { 12 | if (s.check() == sat) 13 | { 14 | std::cout << s << std::endl; 15 | std::cout << s.get_model() << std::endl; 16 | return false; 17 | } 18 | 19 | return true; 20 | } 21 | 22 | TEST_CASE( "Unconstrained: unconstrained binary functions", "[verify-unconstrained-binary-functions]" ) 23 | { 24 | context c; 25 | 26 | solver s(c); 27 | expr t = c.bv_const("t", 4); 28 | expr u = c.bv_const("u", 4); 29 | expr u2 = c.bv_const("u2", 4); 30 | expr res = c.bv_const("res", 4); 31 | expr v = c.bv_const("v", 4); 32 | expr v2 = c.bv_const("v2", 4); 33 | 34 | auto functions = { Z3_mk_bvadd, Z3_mk_bvsub, Z3_mk_bvmul, Z3_mk_bvudiv, Z3_mk_bvurem, 35 | Z3_mk_bvshl, Z3_mk_bvashr, Z3_mk_bvlshr, 36 | Z3_mk_bvand, Z3_mk_bvor, Z3_mk_bvxor 37 | }; 38 | 39 | SECTION( "f(t, u)") 40 | { 41 | for (auto& f : functions) 42 | { 43 | auto expr_f = [&] (z3::expr& x, z3::expr& y) { return to_expr(c, f(c, x, y)); }; 44 | 45 | expr original = expr_f(t, u); 46 | 47 | expr original_v = expr_f(t, v); 48 | UnconstrainedVariableSimplifier simplifier(c, original_v); 49 | simplifier.MarkConstrained({"t"}); 50 | simplifier.SimplifyIte(); 51 | expr simplified = simplifier.GetExpr(); 52 | 53 | INFO( " Checking " + original.to_string() + " subset"); 54 | 55 | s.push(); 56 | s.add(original == res && forall(v, simplified != res)); 57 | REQUIRE(s.check() == unsat); 58 | s.pop(); 59 | 60 | INFO( " Checking " + original.to_string() + " superset"); 61 | 62 | s.push(); 63 | s.add(simplified == res && forall(u, original != res)); 64 | REQUIRE(CheckUnsatOrPrintModel(s)); 65 | s.pop(); 66 | } 67 | } 68 | 69 | SECTION( "f(u, t)") 70 | { 71 | for (auto& f : functions) 72 | { 73 | auto expr_f = [&] (z3::expr& x, z3::expr& y) { return to_expr(c, f(c, x, y)); }; 74 | 75 | expr original = expr_f(u, t); 76 | 77 | expr original_v = expr_f(v, t); 78 | UnconstrainedVariableSimplifier simplifier(c, original_v); 79 | simplifier.MarkConstrained({"t"}); 80 | simplifier.SimplifyIte(); 81 | expr simplified = simplifier.GetExpr(); 82 | 83 | INFO( " Checking " + original.to_string() + " subset"); 84 | 85 | s.push(); 86 | s.add(original == res && forall(v, simplified != res)); 87 | REQUIRE(s.check() == unsat); 88 | s.pop(); 89 | 90 | INFO( " Checking " + original.to_string() + " superset"); 91 | 92 | s.push(); 93 | s.add(simplified == res && forall(u, original != res)); 94 | REQUIRE(CheckUnsatOrPrintModel(s)); 95 | s.pop(); 96 | } 97 | } 98 | 99 | SECTION( "f(u, u2)") 100 | { 101 | for (auto& f : functions) 102 | { 103 | auto expr_f = [&] (z3::expr& x, z3::expr& y) { return to_expr(c, f(c, x, y)); }; 104 | 105 | expr original = expr_f(u, u2); 106 | 107 | expr original_v = expr_f(v, v2); 108 | UnconstrainedVariableSimplifier simplifier(c, original_v); 109 | simplifier.MarkConstrained({}); 110 | simplifier.SimplifyIte(); 111 | expr simplified = simplifier.GetExpr(); 112 | 113 | INFO( " Checking " + original.to_string() + " subset"); 114 | 115 | s.push(); 116 | s.add(original == res && forall(v, forall(v2, simplified != res))); 117 | REQUIRE(s.check() == unsat); 118 | s.pop(); 119 | 120 | INFO( " Checking " + original.to_string() + " superset"); 121 | 122 | s.push(); 123 | s.add(simplified == res && forall(u, forall(u2, original != res))); 124 | REQUIRE(CheckUnsatOrPrintModel(s)); 125 | s.pop(); 126 | } 127 | } 128 | } 129 | 130 | TEST_CASE( "Unconstrained: goal unconstrained", "[verify-goal-unconstrained]" ) 131 | { 132 | context c; 133 | 134 | solver s(c); 135 | expr t = c.bv_const("t", 4); 136 | expr u = c.bv_const("u", 4); 137 | expr res = c.bv_const("res", 4); 138 | expr v = c.bv_const("v", 4); 139 | 140 | auto functions = { Z3_mk_bvadd, Z3_mk_bvsub, Z3_mk_bvmul, Z3_mk_bvudiv, Z3_mk_bvurem, 141 | Z3_mk_bvshl, Z3_mk_bvashr, Z3_mk_bvlshr, 142 | Z3_mk_bvand, Z3_mk_bvor, Z3_mk_bvxor }; 143 | 144 | auto signs = { std::make_tuple(SIGN_MIN, Z3_mk_bvsgt, "Signed min"), 145 | { SIGN_MAX, Z3_mk_bvslt, "Signed max" }, 146 | { UNSIGN_MIN, Z3_mk_bvugt, "Unsigned min" }, 147 | { UNSIGN_MAX, Z3_mk_bvult, "Unsigned max" } 148 | }; 149 | 150 | SECTION( "f(t, u)") 151 | { 152 | for (const auto& f : functions) 153 | { 154 | auto expr_f = [&] (z3::expr& x, z3::expr& y) { return to_expr(c, f(c, x, y)); }; 155 | 156 | for (auto& [goal, pred, goalString] : signs) 157 | { 158 | auto& p = pred; //to avoid clang bug https://bugs.llvm.org/show_bug.cgi?id=35984 159 | auto pred_f = [&c, &p] (z3::expr& x, z3::expr& y) { return to_expr(c, p(c, x, y)); }; 160 | 161 | expr original = expr_f(t, u); 162 | 163 | expr original_v = expr_f(t, v); 164 | UnconstrainedVariableSimplifier simplifier(c, original_v); 165 | simplifier.MarkConstrained({"t"}); 166 | simplifier.SetGoalUnconstrained(true); 167 | simplifier.ForceGoal(goal); 168 | simplifier.SimplifyIte(); 169 | expr simplified = simplifier.GetExpr(); 170 | 171 | INFO( " Checking " + original.to_string() + " " + goalString + " extremeness"); 172 | 173 | s.push(); 174 | s.add(original == res && forall(v, pred_f(simplified, res))); 175 | REQUIRE(CheckUnsatOrPrintModel(s)); 176 | s.pop(); 177 | 178 | INFO( " Checking " + original.to_string() + " " + goalString + " correctness"); 179 | 180 | s.push(); 181 | s.add(simplified == res && forall(u, original != res)); 182 | REQUIRE(CheckUnsatOrPrintModel(s)); 183 | s.pop(); 184 | } 185 | } 186 | } 187 | 188 | SECTION( "f(u, t)") 189 | { 190 | for (const auto& f : functions) 191 | { 192 | auto expr_f = [&] (z3::expr& x, z3::expr& y) { return to_expr(c, f(c, x, y)); }; 193 | 194 | for (auto& [goal, pred, goalString] : signs) 195 | { 196 | auto& p = pred; //to avoid clang bug https://bugs.llvm.org/show_bug.cgi?id=35984 197 | auto pred_f = [&c, &p] (z3::expr& x, z3::expr& y) { return to_expr(c, p(c, x, y)); }; 198 | 199 | expr original = expr_f(u, t); 200 | 201 | expr original_v = expr_f(v, t); 202 | UnconstrainedVariableSimplifier simplifier(c, original_v); 203 | simplifier.MarkConstrained({"t"}); 204 | simplifier.SetGoalUnconstrained(true); 205 | simplifier.ForceGoal(goal); 206 | simplifier.SimplifyIte(); 207 | expr simplified = simplifier.GetExpr(); 208 | 209 | INFO( " Checking " + original.to_string() + " " + goalString + " extremeness"); 210 | 211 | s.push(); 212 | s.add(original == res && forall(v, pred_f(simplified, res))); 213 | REQUIRE(CheckUnsatOrPrintModel(s)); 214 | s.pop(); 215 | 216 | INFO( " Checking " + original.to_string() + " " + goalString + " correctness"); 217 | 218 | s.push(); 219 | s.add(simplified == res && forall(u, original != res)); 220 | REQUIRE(CheckUnsatOrPrintModel(s)); 221 | s.pop(); 222 | } 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /lib/VariableOrderer.cpp: -------------------------------------------------------------------------------- 1 | #include "VariableOrderer.h" 2 | #include 3 | #include "Solver.h" 4 | 5 | using namespace std; 6 | using namespace z3; 7 | 8 | VariableOrderer::VariableOrderer(const std::set &vars, z3::context &ctx) : vars(vars) 9 | { 10 | this->context = &ctx; 11 | this->unionFind = new UF(vars.size()); 12 | 13 | int i = 0; 14 | for (auto const &v : vars) 15 | { 16 | varIndices[v.first] = i; 17 | i++; 18 | } 19 | } 20 | 21 | void VariableOrderer::MergeVars(const std::set &vars) 22 | { 23 | if (vars.size() > 0) 24 | { 25 | for (auto const &v : vars) 26 | { 27 | MarkDependent(*vars.begin(), v); 28 | } 29 | } 30 | } 31 | 32 | void VariableOrderer::MergeAllVarsInExpression(const z3::expr &e, std::vector boundVars) 33 | { 34 | MergeVars(GetVars(e, boundVars)); 35 | } 36 | 37 | bool VariableOrderer::MergeByExpression(const z3::expr &e, std::vector boundVars) 38 | { 39 | auto item = processedMergedSubformulaCache.find((Z3_ast)e); 40 | if (false && item != processedMergedSubformulaCache.end() && item->second == boundVars) 41 | { 42 | return false; 43 | } 44 | 45 | processedMergedSubformulaCache.insert({(Z3_ast)e, boundVars}); 46 | assert(e.is_bool()); 47 | 48 | if (e.is_app()) 49 | { 50 | //cout << "APP: " << e << endl; 51 | func_decl f = e.decl(); 52 | unsigned num = e.num_args(); 53 | 54 | string functionName = f.name().str(); 55 | //cout << "fun: " << functionName << endl; 56 | 57 | if (functionName == "not") 58 | { 59 | return MergeByExpression(e.arg(0), boundVars); 60 | } 61 | else if (functionName == "and" || functionName == "or") 62 | { 63 | bool allBool = true; 64 | std::set varsToMerge; 65 | 66 | for (unsigned int i = 0; i < num; i++) 67 | { 68 | bool currentAllBool = MergeByExpression(e.arg(i), boundVars); 69 | if (currentAllBool) 70 | { 71 | auto currentVars = GetVars(e.arg(i), boundVars); 72 | varsToMerge.insert(currentVars.begin(), currentVars.end()); 73 | } 74 | 75 | allBool &= currentAllBool; 76 | } 77 | 78 | //this actually degrades the performance 79 | //MergeVars(varsToMerge); 80 | 81 | return allBool; 82 | } 83 | else if (functionName == "iff") 84 | { 85 | bool b1 = MergeByExpression(e.arg(0), boundVars); 86 | bool b2 = MergeByExpression(e.arg(1), boundVars); 87 | 88 | if (b1 && b2) 89 | { 90 | //this actually degrades the performance 91 | //MergeAllVarsInExpression(e, boundVars); 92 | } 93 | 94 | return b1 && b2; 95 | } 96 | else if (functionName == "if") 97 | { 98 | bool b1 = MergeByExpression(e.arg(0), boundVars); 99 | bool b2 = MergeByExpression(e.arg(1), boundVars); 100 | bool b3 = MergeByExpression(e.arg(2), boundVars); 101 | 102 | if (b1 && b2 && b3) 103 | { 104 | //MergeAllVarsInExpression(e, boundVars); 105 | } 106 | 107 | return b1 && b2 && b3; 108 | } 109 | else 110 | { 111 | MergeAllVarsInExpression(e, boundVars); 112 | 113 | //cout << "function " << f.name().str() << endl; 114 | 115 | bool allBool = true; 116 | for (unsigned int i = 0; i < num; i++) 117 | { 118 | allBool &= e.arg(i).get_sort().is_bool(); 119 | } 120 | 121 | return allBool && e.get_sort().is_bool(); 122 | } 123 | } 124 | else if (e.is_quantifier()) 125 | { 126 | Z3_ast ast = (Z3_ast)e; 127 | 128 | int boundVariables = Z3_get_quantifier_num_bound(*context, ast); 129 | 130 | for (int i = 0; i < boundVariables; i++) 131 | { 132 | Z3_symbol z3_symbol = Z3_get_quantifier_bound_name(*context, ast, i); 133 | 134 | symbol current_symbol(*context, z3_symbol); 135 | 136 | string c = current_symbol.str(); 137 | boundVars.push_back(c); 138 | } 139 | 140 | MergeByExpression(e.body(), boundVars); 141 | return false; 142 | } 143 | else 144 | { 145 | return e.is_var() && e.get_sort().is_bool(); 146 | } 147 | } 148 | 149 | void VariableOrderer::MergeAll() 150 | { 151 | for (unsigned int i = 1; i < vars.size(); i++) 152 | { 153 | unionFind->merge(0, i); 154 | } 155 | } 156 | 157 | set VariableOrderer::GetVars(const expr &e, std::vector boundVars) 158 | { 159 | set vars; 160 | 161 | auto item = processedVarsCache.find((Z3_ast)e); 162 | if (item != processedVarsCache.end() && (item->second).second == boundVars) 163 | { 164 | return (item->second).first; 165 | } 166 | 167 | if (e.is_var()) 168 | { 169 | Z3_ast ast = (Z3_ast)e; 170 | int deBruijnIndex = Z3_get_index_value(*context, ast); 171 | vars.insert(boundVars.at(boundVars.size() - deBruijnIndex - 1)); 172 | return vars; 173 | } 174 | else if (e.is_const() && !e.is_numeral()) 175 | { 176 | if (e.get_sort().is_bool() || e.get_sort().is_bv()) 177 | { 178 | if (e.is_app() && (e.decl().decl_kind() == Z3_OP_TRUE || 179 | e.decl().decl_kind() == Z3_OP_FALSE)) 180 | { 181 | return vars; 182 | } 183 | 184 | std::unique_lock lk(Solver::m_z3context); 185 | vars.insert(e.to_string()); 186 | } 187 | } 188 | if (e.is_app()) 189 | { 190 | func_decl f = e.decl(); 191 | unsigned num = e.num_args(); 192 | 193 | if (num != 0) 194 | { 195 | for (unsigned i = 0; i < num; i++) 196 | { 197 | set currentVars = GetVars(e.arg(i), boundVars); 198 | vars.insert(currentVars.begin(), currentVars.end()); 199 | 200 | processedVarsCache.insert({(Z3_ast)e.arg(i), {currentVars, boundVars}}); 201 | } 202 | } 203 | else if (f.name() != NULL) 204 | { 205 | z3::sort s = f.range(); 206 | 207 | if (s.is_bv() && !e.is_numeral()) 208 | { 209 | vars.insert(f.name().str()); 210 | } 211 | } 212 | 213 | return vars; 214 | } 215 | else if(e.is_quantifier()) 216 | { 217 | Z3_ast ast = (Z3_ast)e; 218 | 219 | int boundVariables = Z3_get_quantifier_num_bound(*context, ast); 220 | 221 | for (int i = 0; i < boundVariables; i++) 222 | { 223 | Z3_symbol z3_symbol = Z3_get_quantifier_bound_name(*context, ast, i); 224 | 225 | symbol current_symbol(*context, z3_symbol); 226 | 227 | string c = current_symbol.str(); 228 | boundVars.push_back(c); 229 | } 230 | 231 | return GetVars(e.body(), boundVars); 232 | //bdd bodyBdd = getBDDFromExpr(e.body(), boundVars); 233 | } 234 | 235 | return vars; 236 | } 237 | 238 | void VariableOrderer::MarkDependent(const string &x, const string &y) 239 | { 240 | int index1 = varIndices[x]; 241 | int index2 = varIndices[y]; 242 | unionFind->merge(index1, index2); 243 | //cout << "merging " << x << " " << y << endl; 244 | } 245 | 246 | void VariableOrderer::OrderFor(const z3::expr &expr) 247 | { 248 | MergeByExpression(expr, vector()); 249 | } 250 | 251 | vector> VariableOrderer::GetOrdered() const 252 | { 253 | vector> pairList; 254 | for (auto const &v : vars) 255 | { 256 | auto varIndex = varIndices.find(v.first); 257 | auto p = pair(v, unionFind->find(varIndex->second)); 258 | pairList.push_back(p); 259 | } 260 | 261 | std::sort(pairList.begin(), pairList.end(), [](const std::pair &left, const std::pair &right) { 262 | return (left.second < right.second) || (left.second == right.second && left.first.second < right.first.second); 263 | }); 264 | 265 | vector> orderedVarGroups; 266 | 267 | list currentGroup; 268 | int lastGroupIndex = 0; 269 | for (auto const &p : pairList) 270 | { 271 | if (p.second != lastGroupIndex) 272 | { 273 | if (currentGroup.size() > 0) 274 | { 275 | orderedVarGroups.push_back(currentGroup); 276 | currentGroup.clear(); 277 | } 278 | lastGroupIndex = p.second; 279 | } 280 | currentGroup.push_back(p.first); 281 | } 282 | orderedVarGroups.push_back(currentGroup); 283 | 284 | std::sort(orderedVarGroups.begin(), orderedVarGroups.end(), [](const list &left, const list &right) { 285 | return left.size() > right.size(); 286 | }); 287 | 288 | return orderedVarGroups; 289 | } 290 | -------------------------------------------------------------------------------- /lib/TermConstIntroducer.cpp: -------------------------------------------------------------------------------- 1 | #include "TermConstIntroducer.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace z3; 8 | 9 | bool TermConstIntroducer::isVar(expr e) 10 | { 11 | if (e.is_var()) 12 | { 13 | return true; 14 | } 15 | 16 | if (e.is_app()) 17 | { 18 | func_decl f = e.decl(); 19 | unsigned num = e.num_args(); 20 | 21 | if (num == 0 && f.name() != NULL && !e.is_numeral()) 22 | { 23 | return true; 24 | } 25 | } 26 | 27 | return false; 28 | } 29 | 30 | z3::expr TermConstIntroducer::FlattenMul(const z3::expr &e) 31 | { 32 | varsLInMul.clear(); 33 | varsRInMul.clear(); 34 | fillVarsInMul(e); 35 | 36 | auto [newExpr, mulVars] = flattenMulRec(e, {}); 37 | 38 | for (const auto &mulVar : mulVars) 39 | { 40 | if (mulVar.op == Z3_OP_BMUL) 41 | { 42 | newExpr = newExpr && mulVar.result == mulVar.l * mulVar.r; 43 | } 44 | else if (mulVar.op == Z3_OP_BSDIV || mulVar.op == Z3_OP_BSDIV_I) 45 | { 46 | newExpr = newExpr && mulVar.result == mulVar.l / mulVar.r; 47 | } 48 | } 49 | 50 | varsLInMul.clear(); 51 | varsRInMul.clear(); 52 | 53 | return newExpr; 54 | } 55 | 56 | std::pair> TermConstIntroducer::flattenMulRec(const z3::expr &e, const std::vector &boundVars) 58 | { 59 | auto item = flattenMulCache.find(e); 60 | if (item != flattenMulCache.end() && boundVars == std::get<1>(item->second)) 61 | { 62 | return {std::get<0>(item->second), std::get<2>(item->second)}; 63 | } 64 | 65 | if (e.is_var()) 66 | { 67 | Z3_ast ast = (Z3_ast)e; 68 | int deBruijnIndex = Z3_get_index_value(*context, ast); 69 | return {boundVars[boundVars.size() - deBruijnIndex - 1].expr, {}}; 70 | } 71 | else if (e.is_app()) 72 | { 73 | func_decl f = e.decl(); 74 | unsigned numArgs = e.num_args(); 75 | auto decl_kind = f.decl_kind(); 76 | 77 | //TODO: also BVMUL of arity > 2 78 | if ((decl_kind == Z3_OP_BMUL || decl_kind == Z3_OP_BSDIV || decl_kind == Z3_OP_BSDIV_I) 79 | && numArgs == 2 && !e.arg(0).is_numeral() && !e.arg(1).is_numeral()) 80 | { 81 | auto [lExpr, lNewVars] = flattenMulRec(e.arg(0), boundVars); 82 | auto [rExpr, rNewVars] = flattenMulRec(e.arg(1), boundVars); 83 | 84 | if (isVar(lExpr) && isVar(rExpr)) 85 | { 86 | //if bound variable, replace by a corresponding Z3 expr 87 | if (lExpr.is_var()) 88 | { 89 | Z3_ast ast = (Z3_ast)e.arg(0); 90 | int deBruijnIndex = Z3_get_index_value(*context, ast); 91 | lExpr = boundVars[boundVars.size() - deBruijnIndex - 1].expr; 92 | } 93 | 94 | //if bound variable, replace by a corresponding Z3 expr 95 | if (rExpr.is_var()) 96 | { 97 | Z3_ast ast = (Z3_ast)e.arg(1); 98 | int deBruijnIndex = Z3_get_index_value(*context, ast); 99 | rExpr = boundVars[boundVars.size() - deBruijnIndex - 1].expr; 100 | } 101 | 102 | std::stringstream newName; 103 | if (decl_kind == Z3_OP_BMUL) 104 | { 105 | newName << "bvmul_" << lExpr << "_" << rExpr; 106 | } 107 | else if (decl_kind == Z3_OP_BSDIV || decl_kind == Z3_OP_BSDIV_I) 108 | { 109 | newName << "bvsdiv_" << lExpr << "_" << rExpr; 110 | } 111 | 112 | std::set mulVars; 113 | auto newMulExpr = context->bv_const(newName.str().c_str(), e.get_sort().bv_size()); 114 | 115 | std::set newVars; 116 | newVars.insert(lNewVars.begin(), lNewVars.end()); 117 | newVars.insert(rNewVars.begin(), rNewVars.end()); 118 | //add the newly created variable 119 | newVars.insert(OpVar(newMulExpr, decl_kind, lExpr, rExpr)); 120 | 121 | return {newMulExpr, newVars}; 122 | } 123 | } 124 | 125 | std::set mulVars; 126 | 127 | expr_vector arguments(*context); 128 | for (uint i = 0U; i < numArgs; i++) 129 | { 130 | auto [newExpr, newOpVars] = flattenMulRec(e.arg(i), boundVars); 131 | arguments.push_back(newExpr); 132 | mulVars.insert(newOpVars.begin(), newOpVars.end()); 133 | } 134 | 135 | expr result = f(arguments); 136 | flattenMulCache.insert({(Z3_ast)e, {result, boundVars, mulVars}}); 137 | return {result, mulVars}; 138 | } 139 | else if (e.is_quantifier()) 140 | { 141 | Z3_ast ast = (Z3_ast)e; 142 | 143 | int numBound = Z3_get_quantifier_num_bound(*context, ast); 144 | BoundType boundType = Z3_is_quantifier_forall(*context, ast) ? UNIVERSAL : EXISTENTIAL; 145 | auto newBoundVars = boundVars; 146 | 147 | expr_vector currentBound(*context); 148 | for (int i = 0; i < numBound; i++) 149 | { 150 | sort s(*context, Z3_get_quantifier_bound_sort(*context, ast, i)); 151 | Z3_symbol z3_symbol = Z3_get_quantifier_bound_name(*context, ast, i); 152 | symbol current_symbol(*context, z3_symbol); 153 | 154 | auto name = current_symbol.str(); 155 | if (s.is_bool()) 156 | { 157 | Var v(name, boundType, context->bool_const(name.c_str())); 158 | newBoundVars.push_back(v); 159 | currentBound.push_back(v.expr); 160 | } 161 | else if (s.is_bv()) 162 | { 163 | Var v(name, boundType, context->bv_const(name.c_str(), s.bv_size())); 164 | newBoundVars.push_back(v); 165 | currentBound.push_back(v.expr); 166 | } 167 | else 168 | { 169 | std::cout << "Unsupported quantifier sort" << std::endl; 170 | std::cout << "unknown" << std::endl; 171 | abort(); 172 | } 173 | } 174 | 175 | auto [newBody, mulVars] = flattenMulRec(e.body(), newBoundVars); 176 | std::set LquantifiedOpVars, RquantifiedOpVars; 177 | 178 | for (int i = 0; i < numBound; i++) 179 | { 180 | sort s(*context, Z3_get_quantifier_bound_sort(*context, ast, i)); 181 | Z3_symbol z3_symbol = Z3_get_quantifier_bound_name(*context, ast, i); 182 | symbol current_symbol(*context, z3_symbol); 183 | 184 | if (s.is_bv()) 185 | { 186 | auto v = context->bv_const(current_symbol.str().c_str(), s.bv_size()); 187 | std::copy_if(mulVars.begin(), 188 | mulVars.end(), 189 | std::inserter(LquantifiedOpVars, LquantifiedOpVars.end()), 190 | [=] (auto mulVar) 191 | { 192 | return v.to_string() == mulVar.l.to_string(); 193 | }); 194 | std::copy_if(mulVars.begin(), 195 | mulVars.end(), 196 | std::inserter(RquantifiedOpVars, RquantifiedOpVars.end()), 197 | [=] (auto mulVar) 198 | { 199 | return v.to_string() == mulVar.r.to_string() && 200 | v.to_string() != mulVar.l.to_string(); 201 | }); 202 | 203 | //TODO: Do not traverse twice 204 | std::set newOpVars; 205 | std::copy_if(mulVars.begin(), 206 | mulVars.end(), 207 | std::inserter(newOpVars, newOpVars.end()), 208 | [=] (auto mulVar) 209 | { 210 | return v.to_string() != mulVar.l.to_string() && 211 | v.to_string() != mulVar.r.to_string(); 212 | 213 | }); 214 | mulVars = newOpVars; 215 | } 216 | } 217 | 218 | //TODO: Add congruences also for bvsdiv 219 | for (const auto &mulVar : LquantifiedOpVars) 220 | { 221 | if (mulVar.op == Z3_OP_BMUL) 222 | { 223 | newBody = mulVar.result == mulVar.l * mulVar.r && newBody; 224 | 225 | for (const auto &v1 : varsLInMul[mulVar.r.to_string()]) 226 | { 227 | std::stringstream newName; 228 | newName << "bvmul_" << v1 << "_" << mulVar.r; 229 | 230 | auto equivOp = context->bv_const(newName.str().c_str(), mulVar.result.get_sort().bv_size()); 231 | newBody = newBody && 232 | implies(v1 == mulVar.l, mulVar.result == equivOp); 233 | } 234 | 235 | 236 | newBody = exists(mulVar.result, newBody.simplify()); 237 | } 238 | else if (mulVar.op == Z3_OP_BSDIV || mulVar.op == Z3_OP_BSDIV_I) 239 | { 240 | newBody = mulVar.result == mulVar.l / mulVar.r && newBody; 241 | } 242 | } 243 | 244 | for (const auto &mulVar : RquantifiedOpVars) 245 | { 246 | if (mulVar.op == Z3_OP_BMUL) 247 | { 248 | newBody = mulVar.result == mulVar.l * mulVar.r && newBody; 249 | 250 | for (const auto &v2 : varsRInMul[mulVar.l.to_string()]) 251 | { 252 | std::stringstream newName; 253 | newName << "bvmul_" << mulVar.l << "_" << v2; 254 | 255 | auto equivOp = context->bv_const(newName.str().c_str(), mulVar.result.get_sort().bv_size()); 256 | newBody = newBody && 257 | implies(v2 == mulVar.r, mulVar.result == equivOp); 258 | } 259 | 260 | 261 | newBody = exists(mulVar.result, newBody.simplify()); 262 | } 263 | else if (mulVar.op == Z3_OP_BSDIV || mulVar.op == Z3_OP_BSDIV_I) 264 | { 265 | newBody = mulVar.result == mulVar.l / mulVar.r && newBody; 266 | } 267 | } 268 | 269 | 270 | if (boundType == UNIVERSAL) 271 | { 272 | return {forall(currentBound, newBody), mulVars}; 273 | } 274 | else 275 | { 276 | return {exists(currentBound, newBody), mulVars}; 277 | } 278 | } 279 | 280 | std::cout << "FlattenMul: unsupported expression" << std::endl; 281 | std::cout << "unknown" << std::endl; 282 | abort(); 283 | } 284 | 285 | bool operator < (OpVar const& lhs, OpVar const& rhs) 286 | { 287 | return lhs.result.to_string() < rhs.result.to_string(); 288 | } 289 | 290 | bool operator == (OpVar const& lhs, OpVar const& rhs) 291 | { 292 | return lhs.result.to_string() == rhs.result.to_string(); 293 | } 294 | 295 | void TermConstIntroducer::fillVarsInMul(const z3::expr &e) 296 | { 297 | auto item = fillVarsCache.find((Z3_ast)e); 298 | if (item != fillVarsCache.end()) 299 | { 300 | return; 301 | } 302 | 303 | fillVarsCache.insert((Z3_ast)e); 304 | 305 | if (e.is_app()) 306 | { 307 | func_decl f = e.decl(); 308 | unsigned numArgs = e.num_args(); 309 | auto decl_kind = f.decl_kind(); 310 | 311 | //TODO: also BVMUL of arity > 2 312 | if (decl_kind == Z3_OP_BMUL && numArgs == 2 && isVar(e.arg(0)) && isVar(e.arg(1))) 313 | { 314 | auto l = e.arg(0); 315 | auto r = e.arg(1); 316 | 317 | if (!l.is_var()) 318 | { 319 | if (varsLInMul.find(r.to_string()) == varsLInMul.end()) 320 | { 321 | varsLInMul.emplace(r.to_string(), std::set{l}); 322 | } 323 | else 324 | { 325 | varsLInMul[r.to_string()].insert(l); 326 | } 327 | } 328 | 329 | if (!r.is_var()) 330 | { 331 | if (varsRInMul.find(l.to_string()) == varsRInMul.end()) 332 | { 333 | varsRInMul.insert({l.to_string(), std::set{r}}); 334 | } 335 | else 336 | { 337 | varsRInMul[l.to_string()].insert(r); 338 | } 339 | } 340 | } 341 | else 342 | { 343 | for (uint i = 0U; i < numArgs; i++) 344 | { 345 | fillVarsInMul(e.arg(i)); 346 | } 347 | } 348 | } 349 | else if (e.is_quantifier()) 350 | { 351 | fillVarsInMul(e.body()); 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file 2 | #include "catch.hpp" 3 | #include "../lib/Solver.h" 4 | 5 | #include "../lib/SMTLIBInterpreter.h" 6 | 7 | #include "antlr4-runtime.h" 8 | #include "SMTLIBv2Lexer.h" 9 | #include "SMTLIBv2Parser.h" 10 | 11 | using namespace antlr4; 12 | 13 | Model model; 14 | 15 | Result SolveWithoutApprox(std::string filename) 16 | { 17 | std::cout << "Without approx: " << filename << std::endl; 18 | Config config; 19 | config.propagateUnconstrained = true; 20 | config.approximationMethod = VARIABLES; 21 | config.approximations = NO_APPROXIMATIONS; 22 | 23 | std::ifstream stream; 24 | stream.open(filename); 25 | 26 | ANTLRInputStream input(stream); 27 | SMTLIBv2Lexer lexer(&input); 28 | CommonTokenStream tokens(&lexer); 29 | SMTLIBv2Parser parser{&tokens}; 30 | 31 | SMTLIBv2Parser::StartContext* tree = parser.start(); 32 | 33 | SMTLIBInterpreter interpreter; 34 | interpreter.SetConfig(config); 35 | 36 | auto result = interpreter.Run(tree->script()); 37 | if (result == SAT) 38 | { 39 | model = interpreter.GetModel(); 40 | } 41 | return result; 42 | } 43 | 44 | Result SolveWithVariableApprox(std::string filename, Approximation approx = NO_APPROXIMATION) 45 | { 46 | std::cout << "Var approx: " << filename << std::endl; 47 | Config config; 48 | config.propagateUnconstrained = true; 49 | config.approximationMethod = VARIABLES; 50 | config.checkModels = false; 51 | if (approx == UNDERAPPROXIMATION) 52 | config.approximations = ONLY_UNDERAPPROXIMATIONS; 53 | else 54 | config.approximations = ONLY_OVERAPPROXIMATIONS; 55 | 56 | 57 | std::ifstream stream; 58 | stream.open(filename); 59 | 60 | ANTLRInputStream input(stream); 61 | SMTLIBv2Lexer lexer(&input); 62 | CommonTokenStream tokens(&lexer); 63 | SMTLIBv2Parser parser{&tokens}; 64 | 65 | SMTLIBv2Parser::StartContext* tree = parser.start(); 66 | 67 | SMTLIBInterpreter interpreter; 68 | interpreter.SetConfig(config); 69 | 70 | return interpreter.Run(tree->script()); 71 | } 72 | 73 | Result SolveWithOperationsLimitApprox(std::string filename, Approximation approx = NO_APPROXIMATION, int precision = 0) 74 | { 75 | std::cout << "Op approx: " << filename << std::endl; 76 | Config config; 77 | config.propagateUnconstrained = true; 78 | config.approximationMethod = OPERATIONS; 79 | config.checkModels = true; 80 | if (approx == UNDERAPPROXIMATION) 81 | config.approximations = ONLY_UNDERAPPROXIMATIONS; 82 | else 83 | config.approximations = ONLY_OVERAPPROXIMATIONS; 84 | config.precision = precision; 85 | 86 | z3::context ctx; 87 | z3::solver s(ctx); 88 | s.from_file(filename.c_str()); 89 | z3::expr expr = mk_and(s.assertions()); 90 | 91 | std::ifstream stream; 92 | stream.open(filename); 93 | 94 | ANTLRInputStream input(stream); 95 | SMTLIBv2Lexer lexer(&input); 96 | CommonTokenStream tokens(&lexer); 97 | SMTLIBv2Parser parser{&tokens}; 98 | 99 | SMTLIBv2Parser::StartContext* tree = parser.start(); 100 | 101 | SMTLIBInterpreter interpreter; 102 | interpreter.SetConfig(config); 103 | 104 | return interpreter.Run(tree->script()); 105 | } 106 | 107 | Result SolveWithBothLimitApprox(std::string filename, Approximation approx = NO_APPROXIMATION, int precision = 0) 108 | { 109 | std::cout << "Both approx: " << filename << std::endl; 110 | Config config; 111 | config.propagateUnconstrained = true; 112 | config.approximationMethod = BOTH; 113 | config.checkModels = true; 114 | if (approx == UNDERAPPROXIMATION) 115 | config.approximations = ONLY_UNDERAPPROXIMATIONS; 116 | else 117 | config.approximations = ONLY_OVERAPPROXIMATIONS; 118 | config.precision = precision; 119 | 120 | std::ifstream stream; 121 | stream.open(filename); 122 | 123 | ANTLRInputStream input(stream); 124 | SMTLIBv2Lexer lexer(&input); 125 | CommonTokenStream tokens(&lexer); 126 | SMTLIBv2Parser parser{&tokens}; 127 | 128 | SMTLIBv2Parser::StartContext* tree = parser.start(); 129 | 130 | SMTLIBInterpreter interpreter; 131 | interpreter.SetConfig(config); 132 | return interpreter.Run(tree->script()); 133 | } 134 | 135 | Result SolveWithoutApproxAndGoalUnconstrained(std::string filename) 136 | { 137 | Config config; 138 | config.propagateUnconstrained = true; 139 | config.goalUnconstrained = true; 140 | config.approximations = NO_APPROXIMATIONS; 141 | 142 | std::ifstream stream; 143 | stream.open(filename); 144 | 145 | ANTLRInputStream input(stream); 146 | SMTLIBv2Lexer lexer(&input); 147 | CommonTokenStream tokens(&lexer); 148 | SMTLIBv2Parser parser{&tokens}; 149 | 150 | SMTLIBv2Parser::StartContext* tree = parser.start(); 151 | 152 | SMTLIBInterpreter interpreter; 153 | interpreter.SetConfig(config); 154 | 155 | return interpreter.Run(tree->script()); 156 | } 157 | 158 | Result SolveParallelAndGoalUnconstrained(std::string filename) 159 | { 160 | Config config; 161 | config.propagateUnconstrained = true; 162 | config.goalUnconstrained = true; 163 | config.approximations = ALL_APPROXIMATIONS; 164 | 165 | std::ifstream stream; 166 | stream.open(filename); 167 | 168 | ANTLRInputStream input(stream); 169 | SMTLIBv2Lexer lexer(&input); 170 | CommonTokenStream tokens(&lexer); 171 | SMTLIBv2Parser parser{&tokens}; 172 | 173 | SMTLIBv2Parser::StartContext* tree = parser.start(); 174 | 175 | SMTLIBInterpreter interpreter; 176 | interpreter.SetConfig(config); 177 | 178 | return interpreter.Run(tree->script()); 179 | } 180 | 181 | TEST_CASE( "Without approximations", "[noapprox]" ) 182 | { 183 | REQUIRE( SolveWithoutApprox("../tests/data/AR-fixpoint-1.smt2") == UNSAT ); 184 | REQUIRE( SolveWithoutApprox("../tests/data/cache-coherence-2-fixpoint-1.smt2") == UNSAT ); 185 | REQUIRE( SolveWithoutApprox("../tests/data/itc-b13-fixpoint-3.smt2") == SAT ); 186 | REQUIRE( SolveWithoutApprox("../tests/data/Fibonacci01_true-unreach-call_true-no-overflow.c_905.smt2") == SAT ); 187 | REQUIRE( SolveWithoutApprox("../tests/data/nlzbe008.smt2") == UNSAT ); 188 | REQUIRE( SolveWithoutApprox("../tests/data/falseAndFalse.smt2") == UNSAT ); 189 | REQUIRE( SolveWithoutApprox("../tests/data/bvshl0.smt2") == SAT ); 190 | REQUIRE( SolveWithoutApprox("../tests/data/check_bvsge_bvashr0_16bit.smt2") == UNSAT ); 191 | REQUIRE( SolveWithoutApprox("../tests/data/magnetic_field-node118398.smt2") == UNSAT ); 192 | REQUIRE( SolveWithoutApprox("../tests/data/unconstrainedMulVar.smt2") == UNSAT ); 193 | REQUIRE( SolveWithoutApprox("../tests/data/check_bvsle_bvmul_8bit.smt2") == UNSAT ); 194 | REQUIRE( SolveWithoutApprox("../tests/data/unconstrainedMulConst.smt2") == SAT ); 195 | REQUIRE( SolveWithoutApprox("../tests/data/check_eq_bvconcat0_2_64bit.smt2") == UNSAT ); 196 | REQUIRE( SolveWithoutApprox("../tests/data/002.smt2") == UNSAT ); 197 | REQUIRE( SolveWithoutApprox("../tests/data/MADWiFi-encode_ie_ok_true-unreach-call.i_7.smt2") == UNSAT ); 198 | REQUIRE( SolveWithoutApprox("../tests/data/usb-phy-fixpoint-1.smt2") == UNSAT ); 199 | REQUIRE( SolveWithoutApprox("../tests/data/pi-bus-fixpoint-1.smt2") == UNSAT ); 200 | REQUIRE( SolveWithoutApprox("../tests/data/check_eq_bvshl0_32bit.smt2") == UNSAT ); 201 | REQUIRE( SolveWithoutApprox("../tests/data/check_bvuge_bvashr1_64bit.smt2") == UNSAT ); 202 | REQUIRE( SolveWithoutApprox("../tests/data/preiner_bug_2020.smt2") == UNSAT ); 203 | REQUIRE( SolveWithoutApprox("../tests/data/smtcomp23/heapsort.i_0.smt2") == UNSAT ); 204 | REQUIRE( SolveWithoutApprox("../tests/data/smtcomp23/heapsort.i_3.smt2") == UNSAT ); 205 | REQUIRE( SolveWithoutApprox("../tests/data/smtcomp23/heapsort.i_8.smt2") == UNSAT ); 206 | REQUIRE( SolveWithoutApprox("../tests/data/smtcomp23/heapsort.i_9.smt2") == UNSAT ); 207 | REQUIRE( SolveWithoutApprox("../tests/data/smtcomp23/minimal.smt2") == UNSAT ); 208 | REQUIRE( SolveWithoutApprox("../tests/data/btor2c-eagerMod.bakery.1.prop1-func-interl.c_0.smt2") == SAT ); 209 | } 210 | 211 | TEST_CASE( "With variable approximations", "[variableapprox]" ) 212 | { 213 | REQUIRE( SolveWithVariableApprox("../tests/data/audio_ac97_wavepcistream2.cpp.smt2", OVERAPPROXIMATION) == UNSAT ); 214 | REQUIRE( SolveWithVariableApprox("../tests/data/jain_7_true-unreach-call_true-no-overflow.i_61.smt2", OVERAPPROXIMATION) == UNSAT ); 215 | REQUIRE( SolveWithVariableApprox("../tests/data/RNDPRE_3_48.smt2", UNDERAPPROXIMATION) == SAT ); 216 | REQUIRE( SolveWithVariableApprox("../tests/data/ETCS-essentials-node3023.smt2", UNDERAPPROXIMATION) == SAT ); 217 | REQUIRE( SolveWithVariableApprox("../tests/data/accelerating-node2100.smt2", UNDERAPPROXIMATION) == SAT ); 218 | REQUIRE( SolveWithVariableApprox("../tests/data/binary_driver-2007-10-09-node11383.smt2", UNDERAPPROXIMATION) == SAT ); 219 | REQUIRE( SolveWithVariableApprox("../tests/data/ARI118=1.smt2", OVERAPPROXIMATION) == UNSAT ); 220 | } 221 | 222 | TEST_CASE( "With bothLimit approximations", "[bothlimitapprox]" ) 223 | { 224 | REQUIRE( SolveWithBothLimitApprox("../tests/data/RNDPRE_4_42.smt2", OVERAPPROXIMATION) == UNSAT ); 225 | REQUIRE( SolveWithBothLimitApprox("../tests/data/RND_6_4.smt2", UNDERAPPROXIMATION) == SAT ); 226 | REQUIRE( SolveWithBothLimitApprox("../tests/data/jain_7_true-unreach-call_true-no-overflow.i_61.smt2", OVERAPPROXIMATION) == UNSAT ); 227 | 228 | //correct model returned by an overapproximation 229 | REQUIRE( SolveWithBothLimitApprox("../tests/data/007.smt2", OVERAPPROXIMATION) == SAT ); 230 | REQUIRE( SolveWithBothLimitApprox("../tests/data/sum02_true-unreach-call_true-no-overflow.i_375.smt2", OVERAPPROXIMATION) == SAT ); 231 | REQUIRE( SolveWithBothLimitApprox("../tests/data/check_bvsgt_bvudiv1_8bit.smt2", UNDERAPPROXIMATION) != SAT ); 232 | REQUIRE( SolveWithBothLimitApprox("../tests/data/bvurem_approx.smt2", UNDERAPPROXIMATION, 1) != SAT ); 233 | REQUIRE( SolveWithBothLimitApprox("../tests/data/RND_3_14.smt2") == UNSAT ); 234 | } 235 | 236 | TEST_CASE( "With bothLimit approximations -- term introducer ", "[bothlimitapprox-ti]" ) 237 | { 238 | REQUIRE( SolveWithBothLimitApprox("../tests/data/intersection-example-onelane.proof-node1469.smt2", OVERAPPROXIMATION) == UNSAT ); 239 | } 240 | 241 | TEST_CASE( "With operation approximations -- ite ", "[opapproxlimit-ite]" ) 242 | { 243 | REQUIRE( SolveWithOperationsLimitApprox("../tests/data/iteApprox.smt2", UNDERAPPROXIMATION, 1) != UNSAT ); 244 | } 245 | 246 | TEST_CASE( "With parallel approximations", "[parallel]" ) 247 | { 248 | REQUIRE( SolveParallelAndGoalUnconstrained ("../tests/data/003.smt2") == SAT ); 249 | } 250 | 251 | TEST_CASE( "SMT-COMP 2018", "[smtcomp18]" ) 252 | { 253 | REQUIRE( SolveWithVariableApprox( "../tests/data/smtcomp18/01.smt2", UNDERAPPROXIMATION ) != SAT ); 254 | REQUIRE( SolveWithBothLimitApprox( "../tests/data/smtcomp18/02.smt2", OVERAPPROXIMATION, 1 ) != UNSAT ); 255 | } 256 | 257 | TEST_CASE( "Without approximations -- goal unconstrained", "[goalunconstrained]" ) 258 | { 259 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/check_bvuge_bvudiv0_4bit.smt2" ) != SAT ); 260 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/check_bvugt_bvshl0_4bit.smt2" ) != SAT ); 261 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/check_bvsle_bvlshr0_4bit.smt2" ) != SAT ); 262 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/check_bvsle_bvashr0_4bit.smt2" ) != SAT ); 263 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/check_bvslt_bvashr0_4bit.smt2" ) != SAT ); 264 | } 265 | 266 | TEST_CASE( "SMT-LIB", "[smtlib]" ) 267 | { 268 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/binaryNumeral.smt2" ) == SAT ); 269 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/hexNumeral.smt2" ) == SAT ); 270 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/push.smt2" ) == SAT ); 271 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/pushPush.smt2" ) == UNSAT ); 272 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/pushPushPop.smt2" ) == SAT ); 273 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/push2Pop.smt2" ) == UNSAT ); 274 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/push2Pop2.smt2" ) == SAT); 275 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/reset.smt2" ) == SAT); 276 | REQUIRE( SolveWithoutApproxAndGoalUnconstrained( "../tests/data/smtlib/resetAssertions.smt2" ) == SAT); 277 | } 278 | 279 | TEST_CASE( "Models", "[models]" ) 280 | { 281 | REQUIRE( SolveWithoutApprox( "../tests/data/smtlib/model1.smt2" ) == SAT ); 282 | REQUIRE( model.find("x") != model.end() ); 283 | REQUIRE( std::get<1>(model["x"]) == std::vector{false, false, false, true} ); 284 | 285 | REQUIRE( SolveWithoutApprox( "../tests/data/smtlib/model2.smt2" ) == SAT ); 286 | REQUIRE( model.find("x") != model.end() ); 287 | REQUIRE( model.find("y") != model.end() ); 288 | REQUIRE( model.find("z") != model.end() ); 289 | REQUIRE( std::get<1>(model["x"]) == std::vector{false, false, false, true} ); 290 | REQUIRE( std::get<1>(model["y"]) == std::vector{false, false, false, true} ); 291 | REQUIRE( std::get<1>(model["z"]) == std::vector{false, false, true, false} ); 292 | 293 | REQUIRE( SolveWithoutApprox( "../tests/data/smtlib/model3.smt2" ) == SAT ); 294 | REQUIRE( model.find("x") != model.end() ); 295 | REQUIRE( model.find("y") != model.end() ); 296 | REQUIRE( model.find("z") != model.end() ); 297 | REQUIRE( std::get<1>(model["x"]) == std::vector{false, false, true, true} ); 298 | REQUIRE( std::get<1>(model["y"]) == std::vector{false, false, true, true} ); 299 | REQUIRE( std::get<1>(model["z"]) == std::vector{true, false, false, true} ); 300 | } 301 | --------------------------------------------------------------------------------