3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-14 12:58:44 +00:00
This commit is contained in:
Nikolaj Bjorner 2017-04-25 10:30:16 -07:00
commit dedc130e98
54 changed files with 1755 additions and 915 deletions

View file

@ -53,8 +53,8 @@ make
sudo make install sudo make install
``` ```
Note by default ``gcc`` is used as the C++ compiler if it is available. If you Note by default ``g++`` is used as the C++ compiler if it is available. If you
would prefer to use Clang change the ``mk_make.py`` line to would prefer to use Clang change the ``mk_make.py`` invocation to:
```bash ```bash
CXX=clang++ CC=clang python scripts/mk_make.py CXX=clang++ CC=clang python scripts/mk_make.py

View file

@ -0,0 +1,7 @@
qprofdiff: main.cpp
$(CXX) $(CXXFLAGS) main.cpp -o qprofdiff
all: qprofdiff
clean:
rm -f qprofdiff

284
contrib/qprofdiff/main.cpp Normal file
View file

@ -0,0 +1,284 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
main.cpp
Abstract:
Main file for qprofdiff.
Author:
Christoph M. Wintersteiger (cwinter)
Revision History:
--*/
#include<errno.h>
#include<limits.h>
#include<string>
#include<iostream>
#include<fstream>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
set<string> options;
// Profile format:
// [quantifier_instances] qname : num_instances : max_generation : max_cost_s
const string prefix = "[quantifier_instances]";
unsigned prefix_len = prefix.length();
typedef struct { unsigned num_instances, max_generation, max_cost; } map_entry;
string trim(string str) {
size_t linx = str.find_first_not_of(' ');
size_t rinx = str.find_last_not_of(' ');
return str.substr(linx, rinx-linx+1);
}
int parse(string const & filename, map<string, map_entry> & data) {
ifstream fs(filename.c_str());
if (!fs.is_open()) {
cout << "Can't open file '" << filename << "'" << endl;
return ENOENT;
}
string qid;
string tokens[4];
unsigned cur_token = 0;
while (!fs.eof()) {
string line;
getline(fs, line);
if (line.substr(0, prefix_len) == prefix) {
line = trim(line.substr(prefix_len));
size_t from = 0, ti = 0;
for (size_t inx = line.find(':', from);
inx != string::npos;
inx = line.find(':', from)) {
tokens[ti] = trim(line.substr(from, inx-from));
from = inx+1;
ti++;
}
if (from != line.length() && ti < 4)
tokens[ti] = trim(line.substr(from));
qid = tokens[0];
if (data.find(qid) == data.end()) {
map_entry & entry = data[qid];
entry.num_instances = entry.max_generation = entry.max_cost = 0;
}
map_entry & entry = data[qid];
entry.num_instances = atoi(tokens[1].c_str());
entry.max_generation = (unsigned)atoi(tokens[2].c_str());
entry.max_cost = (unsigned)atoi(tokens[3].c_str());
}
}
fs.close();
return 0;
}
void display_data(map<string, map_entry> & data) {
for (map<string, map_entry>::iterator it = data.begin();
it != data.end();
it++)
cout << it->first << ": " << it->second.num_instances <<
", " << it->second.max_generation <<
", " << it->second.max_cost << endl;
}
typedef struct {
int d_num_instances, d_max_generation, d_max_cost;
bool left_only, right_only;
} diff_entry;
typedef struct { string qid; diff_entry e; } diff_item;
#define DIFF_LT(X) bool diff_item_lt_ ## X (diff_item const & l, diff_item const & r) { \
int l_lt_r = l.e.d_ ## X < r.e.d_ ## X; \
int l_eq_r = l.e.d_ ## X == r.e.d_ ## X; \
return \
l.e.left_only ? (r.e.left_only ? ((l_eq_r) ? l.qid < r.qid : l_lt_r) : false) : \
l.e.right_only ? (r.e.right_only ? ((l_eq_r) ? l.qid < r.qid : l_lt_r) : true) : \
r.e.right_only ? false : \
r.e.left_only ? true : \
l_lt_r; \
}
DIFF_LT(num_instances)
DIFF_LT(max_generation)
DIFF_LT(max_cost)
int indicate(diff_entry const & e, bool suppress_unchanged) {
if (e.left_only) {
cout << "< ";
return INT_MIN;
}
else if (e.right_only) {
cout << "> ";
return INT_MAX;
}
else {
int const & delta =
(options.find("-si") != options.end()) ? e.d_num_instances :
(options.find("-sg") != options.end()) ? e.d_max_generation :
(options.find("-sc") != options.end()) ? e.d_max_cost :
e.d_num_instances;
if (delta < 0)
cout << "+ ";
else if (delta > 0)
cout << "- ";
else if (delta == 0 && !suppress_unchanged)
cout << "= ";
return delta;
}
}
void diff(map<string, map_entry> & left, map<string, map_entry> & right) {
map<string, diff_entry> diff_data;
for (map<string, map_entry>::const_iterator lit = left.begin();
lit != left.end();
lit++) {
string const & qid = lit->first;
map_entry const & lentry = lit->second;
map<string, map_entry>::const_iterator rit = right.find(qid);
if (rit != right.end()) {
map_entry const & rentry = rit->second;
diff_entry & de = diff_data[qid];
de.left_only = de.right_only = false;
de.d_num_instances = lentry.num_instances - rentry.num_instances;
de.d_max_generation = lentry.max_generation - rentry.max_generation;
de.d_max_cost = lentry.max_cost - rentry.max_cost;
}
else {
diff_entry & de = diff_data[qid];
de.left_only = true;
de.right_only = false;
de.d_num_instances = lentry.num_instances;
de.d_max_generation = lentry.max_generation;
de.d_max_cost = lentry.max_cost;
}
}
for (map<string, map_entry>::const_iterator rit = right.begin();
rit != right.end();
rit++) {
string const & qid = rit->first;
map_entry const & rentry = rit->second;
map<string, map_entry>::const_iterator lit = left.find(qid);
if (lit == left.end()) {
diff_entry & de = diff_data[qid];
de.left_only = false;
de.right_only = true;
de.d_num_instances = -(int)rentry.num_instances;
de.d_max_generation = -(int)rentry.max_generation;
de.d_max_cost = -(int)rentry.max_cost;
}
}
vector<diff_item> flat_data;
for (map<string, diff_entry>::const_iterator it = diff_data.begin();
it != diff_data.end();
it++) {
flat_data.push_back(diff_item());
flat_data.back().qid = it->first;
flat_data.back().e = it->second;
}
stable_sort(flat_data.begin(), flat_data.end(),
options.find("-si") != options.end() ? diff_item_lt_num_instances:
options.find("-sg") != options.end() ? diff_item_lt_max_generation :
options.find("-sc") != options.end() ? diff_item_lt_max_cost :
diff_item_lt_num_instances);
bool suppress_unchanged = options.find("-n") != options.end();
for (vector<diff_item>::const_iterator it = flat_data.begin();
it != flat_data.end();
it++) {
diff_item const & d = *it;
string const & qid = d.qid;
diff_entry const & e = d.e;
int delta = indicate(e, suppress_unchanged);
if (!(delta == 0 && suppress_unchanged))
cout << qid << " (" <<
(e.d_num_instances > 0 ? "" : "+") << -e.d_num_instances << " inst., " <<
(e.d_max_generation > 0 ? "" : "+") << -e.d_max_generation << " max. gen., " <<
(e.d_max_cost > 0 ? "" : "+") << -e.d_max_cost << " max. cost)" <<
endl;
}
}
void display_usage() {
cout << "Usage: qprofdiff [options] <filename> <filename>" << endl;
cout << "Options:" << endl;
cout << " -n Suppress unchanged items" << endl;
cout << " -si Sort by difference in number of instances" << endl;
cout << " -sg Sort by difference in max. generation" << endl;
cout << " -sc Sort by difference in max. cost" << endl;
}
int main(int argc, char ** argv) {
char * filename1 = 0;
char * filename2 = 0;
for (int i = 1; i < argc; i++) {
int len = string(argv[i]).length();
if (len > 1 && argv[i][0] == '-') {
options.insert(string(argv[i]));
}
else if (filename1 == 0)
filename1 = argv[i];
else if (filename2 == 0)
filename2 = argv[i];
else {
cout << "Invalid argument: " << argv[i] << endl << endl;
display_usage();
return EINVAL;
}
}
if (filename1 == 0 || filename2 == 0) {
cout << "Two filenames required." << endl << endl;
display_usage();
return EINVAL;
}
cout << "Comparing " << filename1 << " to " << filename2 << endl;
map<string, map_entry> data1, data2;
int r = parse(filename1, data1);
if (r != 0) return r;
r = parse(filename2, data2);
if (r != 0) return r;
// display_data(data1);
// display_data(data2);
diff(data1, data2);
return 0;
}

View file

@ -0,0 +1,3 @@
# Maintainers
- Christoph M. Wintersteiger (@wintersteiger, cwinter@microsoft.com)

View file

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{96E7E3EF-4162-474D-BD32-C702632AAF2B}</ProjectGuid>
<RootNamespace>qprofdiff</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<AdditionalIncludeDirectories>..\..\src\util;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>
</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(LibraryPath);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\src\util;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\src\util;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\src\util;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -128,7 +128,7 @@ extern "C" {
lbool r = l_undef; lbool r = l_undef;
cancel_eh<reslimit> eh(mk_c(c)->m().limit()); cancel_eh<reslimit> eh(mk_c(c)->m().limit());
unsigned timeout = to_optimize_ptr(o)->get_params().get_uint("timeout", mk_c(c)->get_timeout()); unsigned timeout = to_optimize_ptr(o)->get_params().get_uint("timeout", mk_c(c)->get_timeout());
unsigned rlimit = mk_c(c)->get_rlimit(); unsigned rlimit = to_optimize_ptr(o)->get_params().get_uint("rlimit", mk_c(c)->get_rlimit());
api::context::set_interruptable si(*(mk_c(c)), eh); api::context::set_interruptable si(*(mk_c(c)), eh);
{ {
scoped_timer timer(timeout, &eh); scoped_timer timer(timeout, &eh);

View file

@ -2244,7 +2244,7 @@ namespace z3 {
void from_file(char const* s) { Z3_fixedpoint_from_file(ctx(), m_fp, s); check_error(); } void from_file(char const* s) { Z3_fixedpoint_from_file(ctx(), m_fp, s); check_error(); }
void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); } void add_rule(expr& rule, symbol const& name) { Z3_fixedpoint_add_rule(ctx(), m_fp, rule, name); check_error(); }
void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); } void add_fact(func_decl& f, unsigned * args) { Z3_fixedpoint_add_fact(ctx(), m_fp, f, f.arity(), args); check_error(); }
check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); to_check_result(r); } check_result query(expr& q) { Z3_lbool r = Z3_fixedpoint_query(ctx(), m_fp, q); check_error(); return to_check_result(r); }
check_result query(func_decl_vector& relations) { check_result query(func_decl_vector& relations) {
array<Z3_func_decl> rs(relations); array<Z3_func_decl> rs(relations);
Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr()); Z3_lbool r = Z3_fixedpoint_query_relations(ctx(), m_fp, rs.size(), rs.ptr());

View file

@ -1890,43 +1890,43 @@ public class Context implements AutoCloseable {
/** /**
* Create the empty sequence. * Create the empty sequence.
*/ */
public SeqExpr MkEmptySeq(Sort s) public SeqExpr mkEmptySeq(Sort s)
{ {
checkContextMatch(s); checkContextMatch(s);
return new SeqExpr(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject())); return (SeqExpr) Expr.create(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
} }
/** /**
* Create the singleton sequence. * Create the singleton sequence.
*/ */
public SeqExpr MkUnit(Expr elem) public SeqExpr mkUnit(Expr elem)
{ {
checkContextMatch(elem); checkContextMatch(elem);
return new SeqExpr(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject())); return (SeqExpr) Expr.create(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
} }
/** /**
* Create a string constant. * Create a string constant.
*/ */
public SeqExpr MkString(String s) public SeqExpr mkString(String s)
{ {
return new SeqExpr(this, Native.mkString(nCtx(), s)); return (SeqExpr) Expr.create(this, Native.mkString(nCtx(), s));
} }
/** /**
* Concatentate sequences. * Concatentate sequences.
*/ */
public SeqExpr MkConcat(SeqExpr... t) public SeqExpr mkConcat(SeqExpr... t)
{ {
checkContextMatch(t); checkContextMatch(t);
return new SeqExpr(this, Native.mkSeqConcat(nCtx(), t.length, AST.arrayToNative(t))); return (SeqExpr) Expr.create(this, Native.mkSeqConcat(nCtx(), t.length, AST.arrayToNative(t)));
} }
/** /**
* Retrieve the length of a given sequence. * Retrieve the length of a given sequence.
*/ */
public IntExpr MkLength(SeqExpr s) public IntExpr mkLength(SeqExpr s)
{ {
checkContextMatch(s); checkContextMatch(s);
return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject())); return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject()));
@ -1935,128 +1935,219 @@ public class Context implements AutoCloseable {
/** /**
* Check for sequence prefix. * Check for sequence prefix.
*/ */
public BoolExpr MkPrefixOf(SeqExpr s1, SeqExpr s2) public BoolExpr mkPrefixOf(SeqExpr s1, SeqExpr s2)
{ {
checkContextMatch(s1, s2); checkContextMatch(s1, s2);
return new BoolExpr(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject())); return (BoolExpr) Expr.create(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
} }
/** /**
* Check for sequence suffix. * Check for sequence suffix.
*/ */
public BoolExpr MkSuffixOf(SeqExpr s1, SeqExpr s2) public BoolExpr mkSuffixOf(SeqExpr s1, SeqExpr s2)
{ {
checkContextMatch(s1, s2); checkContextMatch(s1, s2);
return new BoolExpr(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject())); return (BoolExpr)Expr.create(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
} }
/** /**
* Check for sequence containment of s2 in s1. * Check for sequence containment of s2 in s1.
*/ */
public BoolExpr MkContains(SeqExpr s1, SeqExpr s2) public BoolExpr mkContains(SeqExpr s1, SeqExpr s2)
{ {
checkContextMatch(s1, s2); checkContextMatch(s1, s2);
return new BoolExpr(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject())); return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
} }
/** /**
* Retrieve sequence of length one at index. * Retrieve sequence of length one at index.
*/ */
public SeqExpr MkAt(SeqExpr s, IntExpr index) public SeqExpr mkAt(SeqExpr s, IntExpr index)
{ {
checkContextMatch(s, index); checkContextMatch(s, index);
return new SeqExpr(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject())); return (SeqExpr) Expr.create(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
} }
/** /**
* Extract subsequence. * Extract subsequence.
*/ */
public SeqExpr MkExtract(SeqExpr s, IntExpr offset, IntExpr length) public SeqExpr mkExtract(SeqExpr s, IntExpr offset, IntExpr length)
{ {
checkContextMatch(s, offset, length); checkContextMatch(s, offset, length);
return new SeqExpr(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject())); return (SeqExpr) Expr.create(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
} }
/** /**
* Extract index of sub-string starting at offset. * Extract index of sub-string starting at offset.
*/ */
public IntExpr MkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset) public IntExpr mkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset)
{ {
checkContextMatch(s, substr, offset); checkContextMatch(s, substr, offset);
return new IntExpr(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject())); return (IntExpr)Expr.create(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
} }
/** /**
* Replace the first occurrence of src by dst in s. * Replace the first occurrence of src by dst in s.
*/ */
public SeqExpr MkReplace(SeqExpr s, SeqExpr src, SeqExpr dst) public SeqExpr mkReplace(SeqExpr s, SeqExpr src, SeqExpr dst)
{ {
checkContextMatch(s, src, dst); checkContextMatch(s, src, dst);
return new SeqExpr(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject())); return (SeqExpr) Expr.create(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
} }
/** /**
* Convert a regular expression that accepts sequence s. * Convert a regular expression that accepts sequence s.
*/ */
public ReExpr MkToRe(SeqExpr s) public ReExpr mkToRe(SeqExpr s)
{ {
checkContextMatch(s); checkContextMatch(s);
return new ReExpr(this, Native.mkSeqToRe(nCtx(), s.getNativeObject())); return (ReExpr) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
} }
/** /**
* Check for regular expression membership. * Check for regular expression membership.
*/ */
public BoolExpr MkInRe(SeqExpr s, ReExpr re) public BoolExpr mkInRe(SeqExpr s, ReExpr re)
{ {
checkContextMatch(s, re); checkContextMatch(s, re);
return new BoolExpr(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject())); return (BoolExpr) Expr.create(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));
} }
/** /**
* Take the Kleene star of a regular expression. * Take the Kleene star of a regular expression.
*/ */
public ReExpr MkStar(ReExpr re) public ReExpr mkStar(ReExpr re)
{ {
checkContextMatch(re); checkContextMatch(re);
return new ReExpr(this, Native.mkReStar(nCtx(), re.getNativeObject())); return (ReExpr) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
} }
/**
* Take the lower and upper-bounded Kleene star of a regular expression.
*/
public ReExpr mkLoop(ReExpr re, int lo, int hi)
{
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, hi));
}
/**
* Take the lower-bounded Kleene star of a regular expression.
*/
public ReExpr mkLoop(ReExpr re, int lo)
{
return (ReExpr) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, 0));
}
/** /**
* Take the Kleene plus of a regular expression. * Take the Kleene plus of a regular expression.
*/ */
public ReExpr MPlus(ReExpr re) public ReExpr mkPlus(ReExpr re)
{ {
checkContextMatch(re); checkContextMatch(re);
return new ReExpr(this, Native.mkRePlus(nCtx(), re.getNativeObject())); return (ReExpr) Expr.create(this, Native.mkRePlus(nCtx(), re.getNativeObject()));
} }
/** /**
* Create the optional regular expression. * Create the optional regular expression.
*/ */
public ReExpr MOption(ReExpr re) public ReExpr mkOption(ReExpr re)
{ {
checkContextMatch(re); checkContextMatch(re);
return new ReExpr(this, Native.mkReOption(nCtx(), re.getNativeObject())); return (ReExpr) Expr.create(this, Native.mkReOption(nCtx(), re.getNativeObject()));
}
/**
* Create the complement regular expression.
*/
public ReExpr mkComplement(ReExpr re)
{
checkContextMatch(re);
return (ReExpr) Expr.create(this, Native.mkReComplement(nCtx(), re.getNativeObject()));
} }
/** /**
* Create the concatenation of regular languages. * Create the concatenation of regular languages.
*/ */
public ReExpr MkConcat(ReExpr... t) public ReExpr mkConcat(ReExpr... t)
{ {
checkContextMatch(t); checkContextMatch(t);
return new ReExpr(this, Native.mkReConcat(nCtx(), t.length, AST.arrayToNative(t))); return (ReExpr) Expr.create(this, Native.mkReConcat(nCtx(), t.length, AST.arrayToNative(t)));
} }
/** /**
* Create the union of regular languages. * Create the union of regular languages.
*/ */
public ReExpr MkUnion(ReExpr... t) public ReExpr mkUnion(ReExpr... t)
{ {
checkContextMatch(t); checkContextMatch(t);
return new ReExpr(this, Native.mkReUnion(nCtx(), t.length, AST.arrayToNative(t))); return (ReExpr) Expr.create(this, Native.mkReUnion(nCtx(), t.length, AST.arrayToNative(t)));
}
/**
* Create the intersection of regular languages.
*/
public ReExpr mkIntersect(ReExpr... t)
{
checkContextMatch(t);
return (ReExpr) Expr.create(this, Native.mkReIntersect(nCtx(), t.length, AST.arrayToNative(t)));
}
/**
* Create a range expression.
*/
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
{
checkContextMatch(lo, hi);
return (ReExpr) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
}
/**
* Create an at-most-k constraint.
*/
public BoolExpr mkAtMost(BoolExpr[] args, int k)
{
checkContextMatch(args);
return (BoolExpr) Expr.create(this, Native.mkAtmost(nCtx(), args.length, AST.arrayToNative(args), k));
}
/**
* Create an at-least-k constraint.
*/
public BoolExpr mkAtLeast(BoolExpr[] args, int k)
{
checkContextMatch(args);
return (BoolExpr) Expr.create(this, Native.mkAtleast(nCtx(), args.length, AST.arrayToNative(args), k));
}
/**
* Create a pseudo-Boolean less-or-equal constraint.
*/
public BoolExpr mkPBLe(int[] coeffs, BoolExpr[] args, int k)
{
checkContextMatch(args);
return (BoolExpr) Expr.create(this, Native.mkPble(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
}
/**
* Create a pseudo-Boolean greater-or-equal constraint.
*/
public BoolExpr mkPBGe(int[] coeffs, BoolExpr[] args, int k)
{
checkContextMatch(args);
return (BoolExpr) Expr.create(this, Native.mkPbge(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
}
/**
* Create a pseudo-Boolean equal constraint.
*/
public BoolExpr mkPBEq(int[] coeffs, BoolExpr[] args, int k)
{
checkContextMatch(args);
return (BoolExpr) Expr.create(this, Native.mkPbeq(nCtx(), args.length, AST.arrayToNative(args), coeffs, k));
} }

View file

@ -162,7 +162,7 @@ void defined_names::impl::bound_vars(sort_ref_buffer const & sorts, buffer<symbo
1, symbol::null, symbol::null, 1, symbol::null, symbol::null,
1, patterns); 1, patterns);
TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m_manager) << "\n";); TRACE("mk_definition_bug", tout << "before elim_unused_vars:\n" << mk_ismt2_pp(q, m_manager) << "\n";);
elim_unused_vars(m_manager, q, result); elim_unused_vars(m_manager, q, params_ref(), result);
TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m_manager) << "\n";); TRACE("mk_definition_bug", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m_manager) << "\n";);
} }
} }

View file

@ -194,7 +194,7 @@ bool arith_rewriter::is_bound(expr * arg1, expr * arg2, op_kind kind, expr_ref &
} }
} }
expr* t1, *t2; expr* t1, *t2;
bool is_int; bool is_int = false;
if (m_util.is_mod(arg2)) { if (m_util.is_mod(arg2)) {
std::swap(arg1, arg2); std::swap(arg1, arg2);
switch (kind) { switch (kind) {

View file

@ -138,7 +138,7 @@ void der::operator()(quantifier * q, expr_ref & r, proof_ref & pr) {
// Eliminate variables that have become unused // Eliminate variables that have become unused
if (reduced && is_forall(r)) { if (reduced && is_forall(r)) {
quantifier * q = to_quantifier(r); quantifier * q = to_quantifier(r);
elim_unused_vars(m_manager, q, r); elim_unused_vars(m_manager, q, params_ref(), r);
if (m_manager.proofs_enabled()) { if (m_manager.proofs_enabled()) {
proof * p1 = m_manager.mk_elim_unused_vars(q, r); proof * p1 = m_manager.mk_elim_unused_vars(q, r);
pr = m_manager.mk_transitivity(pr, p1); pr = m_manager.mk_transitivity(pr, p1);

View file

@ -8,5 +8,6 @@ def_module_params('rewriter',
("push_ite_bv", BOOL, False, "push if-then-else over bit-vector terms."), ("push_ite_bv", BOOL, False, "push if-then-else over bit-vector terms."),
("pull_cheap_ite", BOOL, False, "pull if-then-else terms when cheap."), ("pull_cheap_ite", BOOL, False, "pull if-then-else terms when cheap."),
("bv_ineq_consistency_test_max", UINT, 0, "max size of conjunctions on which to perform consistency test based on inequalities on bitvectors."), ("bv_ineq_consistency_test_max", UINT, 0, "max size of conjunctions on which to perform consistency test based on inequalities on bitvectors."),
("cache_all", BOOL, False, "cache all intermediate results."))) ("cache_all", BOOL, False, "cache all intermediate results."),
("ignore_patterns_on_ground_qbody", BOOL, True, "ignores patterns on quantifiers that don't mention their bound variables.")))

View file

@ -60,7 +60,12 @@ expr_ref sym_expr::accept(expr* e) {
} }
std::ostream& sym_expr::display(std::ostream& out) const { std::ostream& sym_expr::display(std::ostream& out) const {
return out << m_t; switch (m_ty) {
case t_char: return out << m_t;
case t_range: return out << m_t << ":" << m_s;
case t_pred: return out << m_t;
}
return out << "expression type not recognized";
} }
struct display_expr1 { struct display_expr1 {
@ -237,6 +242,7 @@ eautomaton* re2automaton::re2aut(expr* e) {
unsigned nb = s1.num_bits(); unsigned nb = s1.num_bits();
expr_ref _start(bv.mk_numeral(start, nb), m); expr_ref _start(bv.mk_numeral(start, nb), m);
expr_ref _stop(bv.mk_numeral(stop, nb), m); expr_ref _stop(bv.mk_numeral(stop, nb), m);
TRACE("seq", tout << "Range: " << start << " " << stop << "\n";);
a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop)); a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop));
return a.detach(); return a.detach();
} }
@ -646,6 +652,29 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
result = m().mk_true(); result = m().mk_true();
return BR_DONE; return BR_DONE;
} }
bool all_units = true;
for (unsigned i = 0; i < bs.size(); ++i) {
all_units = m_util.str.is_unit(bs[i].get());
}
for (unsigned i = 0; i < as.size(); ++i) {
all_units = m_util.str.is_unit(as[i].get());
}
if (all_units) {
if (as.size() < bs.size()) {
result = m().mk_false();
return BR_DONE;
}
expr_ref_vector ors(m());
for (unsigned i = 0; i < as.size() - bs.size() + 1; ++i) {
expr_ref_vector ands(m());
for (unsigned j = 0; j < bs.size(); ++j) {
ands.push_back(m().mk_eq(as[i + j].get(), bs[j].get()));
}
ors.push_back(::mk_and(ands));
}
result = ::mk_or(ors);
return BR_REWRITE_FULL;
}
return BR_FAILED; return BR_FAILED;
} }
@ -1435,6 +1464,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
zstring s; zstring s;
bool lchange = false; bool lchange = false;
SASSERT(lhs.empty()); SASSERT(lhs.empty());
TRACE("seq", tout << ls << "\n"; tout << rs << "\n";);
// solve from back // solve from back
while (true) { while (true) {
while (!rs.empty() && m_util.str.is_empty(rs.back())) { while (!rs.empty() && m_util.str.is_empty(rs.back())) {
@ -1552,9 +1582,11 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
head2 < rs.size() && head2 < rs.size() &&
m_util.str.is_string(ls[head1].get(), s1) && m_util.str.is_string(ls[head1].get(), s1) &&
m_util.str.is_string(rs[head2].get(), s2)) { m_util.str.is_string(rs[head2].get(), s2)) {
TRACE("seq", tout << s1 << " - " << s2 << " " << s1.length() << " " << s2.length() << "\n";);
unsigned l = std::min(s1.length(), s2.length()); unsigned l = std::min(s1.length(), s2.length());
for (unsigned i = 0; i < l; ++i) { for (unsigned i = 0; i < l; ++i) {
if (s1[i] != s2[i]) { if (s1[i] != s2[i]) {
TRACE("seq", tout << "different at position " << i << " " << s1[i] << " " << s2[i] << "\n";);
return false; return false;
} }
} }

View file

@ -54,6 +54,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
bool m_cache_all; bool m_cache_all;
bool m_push_ite_arith; bool m_push_ite_arith;
bool m_push_ite_bv; bool m_push_ite_bv;
bool m_ignore_patterns_on_ground_qbody;
// substitution support // substitution support
expr_dependency_ref m_used_dependencies; // set of dependencies of used substitutions expr_dependency_ref m_used_dependencies; // set of dependencies of used substitutions
@ -70,6 +71,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
m_cache_all = p.cache_all(); m_cache_all = p.cache_all();
m_push_ite_arith = p.push_ite_arith(); m_push_ite_arith = p.push_ite_arith();
m_push_ite_bv = p.push_ite_bv(); m_push_ite_bv = p.push_ite_bv();
m_ignore_patterns_on_ground_qbody = p.ignore_patterns_on_ground_qbody();
} }
void updt_params(params_ref const & p) { void updt_params(params_ref const & p) {
@ -649,7 +651,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
SASSERT(is_well_sorted(m(), q1)); SASSERT(is_well_sorted(m(), q1));
} }
elim_unused_vars(m(), q1, result); elim_unused_vars(m(), q1, params_ref(), result);
TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m()) << "\n";); TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << mk_ismt2_pp(result, m()) << "\n";);

View file

@ -39,10 +39,16 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";); tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
} }
unused_vars_eliminator::unused_vars_eliminator(ast_manager & m, params_ref const & params) :
m(m), m_subst(m), m_params(params)
{
m_ignore_patterns_on_ground_qbody = m_params.get_bool("ignore_patterns_on_ground_qbody", true);
}
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) { void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
SASSERT(is_well_sorted(m, q)); SASSERT(is_well_sorted(m, q));
if (is_ground(q->get_expr())) { if (m_ignore_patterns_on_ground_qbody && is_ground(q->get_expr())) {
// ignore patterns if the body is a ground formula. // Ignore patterns if the body is a ground formula.
result = q->get_expr(); result = q->get_expr();
return; return;
} }
@ -146,8 +152,8 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
SASSERT(is_well_sorted(m, result)); SASSERT(is_well_sorted(m, result));
} }
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) { void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & result) {
unused_vars_eliminator el(m); unused_vars_eliminator el(m, params);
el(q, result); el(q, result);
} }

View file

@ -21,6 +21,7 @@ Notes:
#include"rewriter.h" #include"rewriter.h"
#include"used_vars.h" #include"used_vars.h"
#include"params.h"
/** /**
\brief Alias for var_shifter class. \brief Alias for var_shifter class.
@ -58,12 +59,14 @@ class unused_vars_eliminator {
ast_manager & m; ast_manager & m;
var_subst m_subst; var_subst m_subst;
used_vars m_used; used_vars m_used;
params_ref m_params;
bool m_ignore_patterns_on_ground_qbody;
public: public:
unused_vars_eliminator(ast_manager& m): m(m), m_subst(m) {} unused_vars_eliminator(ast_manager & m, params_ref const & params);
void operator()(quantifier* q, expr_ref& r); void operator()(quantifier* q, expr_ref& r);
}; };
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & r); void elim_unused_vars(ast_manager & m, quantifier * q, params_ref const & params, expr_ref & r);
/** /**
\brief Instantiate quantifier q using the given exprs. \brief Instantiate quantifier q using the given exprs.

View file

@ -126,13 +126,14 @@ static bool is_escape_char(char const *& s, unsigned& result) {
zstring::zstring(encoding enc): m_encoding(enc) {} zstring::zstring(encoding enc): m_encoding(enc) {}
zstring::zstring(char const* s, encoding enc): m_encoding(enc) { zstring::zstring(char const* s, encoding enc): m_encoding(enc) {
unsigned mask = 0xFF; // TBD for UTF
while (*s) { while (*s) {
unsigned ch; unsigned ch;
if (is_escape_char(s, ch)) { if (is_escape_char(s, ch)) {
m_buffer.push_back(ch); m_buffer.push_back(ch & mask);
} }
else { else {
m_buffer.push_back(*s); m_buffer.push_back(*s & mask);
++s; ++s;
} }
} }

View file

@ -304,6 +304,7 @@ public:
app* mk_to_re(expr* s) { return m.mk_app(m_fid, OP_SEQ_TO_RE, 1, &s); } app* mk_to_re(expr* s) { return m.mk_app(m_fid, OP_SEQ_TO_RE, 1, &s); }
app* mk_in_re(expr* s, expr* r) { return m.mk_app(m_fid, OP_SEQ_IN_RE, s, r); } app* mk_in_re(expr* s, expr* r) { return m.mk_app(m_fid, OP_SEQ_IN_RE, s, r); }
app* mk_range(expr* s1, expr* s2) { return m.mk_app(m_fid, OP_RE_RANGE, s1, s2); }
app* mk_concat(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_CONCAT, r1, r2); } app* mk_concat(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_CONCAT, r1, r2); }
app* mk_union(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_UNION, r1, r2); } app* mk_union(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_UNION, r1, r2); }
app* mk_inter(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_INTERSECT, r1, r2); } app* mk_inter(expr* r1, expr* r2) { return m.mk_app(m_fid, OP_RE_INTERSECT, r1, r2); }

View file

@ -126,7 +126,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
quantifier_ref tmp_q(m_manager); quantifier_ref tmp_q(m_manager);
tmp_q = m_manager.update_quantifier(q, not_arg); tmp_q = m_manager.update_quantifier(q, not_arg);
expr_ref new_q(m_manager); expr_ref new_q(m_manager);
elim_unused_vars(m_manager, tmp_q, new_q); elim_unused_vars(m_manager, tmp_q, params_ref(), new_q);
new_args.push_back(new_q); new_args.push_back(new_q);
} }
expr_ref result(m_manager); expr_ref result(m_manager);

View file

@ -188,7 +188,7 @@ void elim_bounds::operator()(quantifier * q, expr_ref & r) {
} }
quantifier_ref new_q(m_manager); quantifier_ref new_q(m_manager);
new_q = m_manager.update_quantifier(q, new_body); new_q = m_manager.update_quantifier(q, new_body);
elim_unused_vars(m_manager, new_q, r); elim_unused_vars(m_manager, new_q, params_ref(), r);
TRACE("elim_bounds", tout << mk_pp(q, m_manager) << "\n" << mk_pp(r, m_manager) << "\n";); TRACE("elim_bounds", tout << mk_pp(q, m_manager) << "\n" << mk_pp(r, m_manager) << "\n";);
} }

View file

@ -852,7 +852,7 @@ void simplifier::reduce1_quantifier(quantifier * q) {
} }
expr_ref r(m); expr_ref r(m);
elim_unused_vars(m, q1, r); elim_unused_vars(m, q1, params_ref(), r);
proof * pr = 0; proof * pr = 0;
if (m.fine_grain_proofs()) { if (m.fine_grain_proofs()) {

View file

@ -29,6 +29,7 @@ Notes:
#include"bound_manager.h" #include"bound_manager.h"
#include"used_vars.h" #include"used_vars.h"
#include"var_subst.h" #include"var_subst.h"
#include"gparams.h"
#ifndef _EXTERNAL_RELEASE #ifndef _EXTERNAL_RELEASE
@ -271,7 +272,7 @@ UNARY_CMD(elim_unused_vars_cmd, "dbg-elim-unused-vars", "<expr>", "eliminate unu
return; return;
} }
expr_ref r(ctx.m()); expr_ref r(ctx.m());
elim_unused_vars(ctx.m(), to_quantifier(arg), r); elim_unused_vars(ctx.m(), to_quantifier(arg), gparams::get(), r);
SASSERT(!is_quantifier(r) || !to_quantifier(r)->may_have_unused_vars()); SASSERT(!is_quantifier(r) || !to_quantifier(r)->may_have_unused_vars());
ctx.display(ctx.regular_stream(), r); ctx.display(ctx.regular_stream(), r);
ctx.regular_stream() << std::endl; ctx.regular_stream() << std::endl;

View file

@ -348,7 +348,7 @@ namespace Duality {
expr expr::qe_lite() const { expr expr::qe_lite() const {
::qe_lite qe(m()); ::qe_lite qe(m(), params_ref());
expr_ref result(to_expr(raw()),m()); expr_ref result(to_expr(raw()),m());
proof_ref pf(m()); proof_ref pf(m());
qe(result,pf); qe(result,pf);
@ -356,7 +356,7 @@ namespace Duality {
} }
expr expr::qe_lite(const std::set<int> &idxs, bool index_of_bound) const { expr expr::qe_lite(const std::set<int> &idxs, bool index_of_bound) const {
::qe_lite qe(m()); ::qe_lite qe(m(), params_ref());
expr_ref result(to_expr(raw()),m()); expr_ref result(to_expr(raw()),m());
proof_ref pf(m()); proof_ref pf(m());
uint_set uis; uint_set uis;

View file

@ -54,7 +54,7 @@ namespace datalog {
m_head(m), m_head(m),
m_args(m), m_args(m),
m_hnf(m), m_hnf(m),
m_qe(m), m_qe(m, params_ref()),
m_rwr(m), m_rwr(m),
m_ufproc(m) {} m_ufproc(m) {}

View file

@ -2241,7 +2241,7 @@ namespace pdr {
vars.append(aux_vars.size(), aux_vars.c_ptr()); vars.append(aux_vars.size(), aux_vars.c_ptr());
scoped_ptr<expr_replacer> rep; scoped_ptr<expr_replacer> rep;
qe_lite qe(m); qe_lite qe(m, m_params.p);
expr_ref phi1 = m_pm.mk_and(Phi); expr_ref phi1 = m_pm.mk_and(Phi);
qe(vars, phi1); qe(vars, phi1);
TRACE("pdr", tout << "Eliminated\n" << mk_pp(phi1, m) << "\n";); TRACE("pdr", tout << "Eliminated\n" << mk_pp(phi1, m) << "\n";);

View file

@ -520,7 +520,7 @@ namespace tb {
m_matcher(m), m_matcher(m),
m_refs(m), m_refs(m),
m_subst(m), m_subst(m),
m_qe(m), m_qe(m, params_ref()),
m_rw(m), m_rw(m),
m_solver(m, m_fparams) {} m_solver(m, m_fparams) {}
@ -1067,7 +1067,7 @@ namespace tb {
} }
bool unify(clause const& tgt, unsigned idx, clause const& src, bool compute_subst, ref<clause>& result) { bool unify(clause const& tgt, unsigned idx, clause const& src, bool compute_subst, ref<clause>& result) {
qe_lite qe(m); qe_lite qe(m, params_ref());
reset(); reset();
SASSERT(tgt.get_predicate(idx)->get_decl() == src.get_decl()); SASSERT(tgt.get_predicate(idx)->get_decl() == src.get_decl());
unsigned var_cnt = std::max(tgt.get_num_vars(), src.get_num_vars()); unsigned var_cnt = std::max(tgt.get_num_vars(), src.get_num_vars());

View file

@ -5,6 +5,8 @@ def_module_params('opt',
('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres'"), ('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres'"),
('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', or 'box'"), ('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', or 'box'"),
('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'), ('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'),
('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'),
('rlimit', UINT, 0, 'resource limit (0 means no limit)'),
('print_model', BOOL, False, 'display model for satisfiable constraints'), ('print_model', BOOL, False, 'display model for satisfiable constraints'),
('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'), ('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'),
('enable_sat', BOOL, True, 'enable the new SAT core for propositional constraints'), ('enable_sat', BOOL, True, 'enable the new SAT core for propositional constraints'),

View file

@ -91,6 +91,7 @@ namespace eq {
expr_ref_vector m_subst_map; expr_ref_vector m_subst_map;
expr_ref_buffer m_new_args; expr_ref_buffer m_new_args;
th_rewriter m_rewriter; th_rewriter m_rewriter;
params_ref m_params;
void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsigned_vector & order) { void der_sort_vars(ptr_vector<var> & vars, ptr_vector<expr> & definitions, unsigned_vector & order) {
order.reset(); order.reset();
@ -563,7 +564,8 @@ namespace eq {
void elim_unused_vars(expr_ref& r, proof_ref &pr) { void elim_unused_vars(expr_ref& r, proof_ref &pr) {
if (is_quantifier(r)) { if (is_quantifier(r)) {
quantifier * q = to_quantifier(r); quantifier * q = to_quantifier(r);
::elim_unused_vars(m, q, r);
::elim_unused_vars(m, q, m_params, r);
if (m.proofs_enabled()) { if (m.proofs_enabled()) {
proof * p1 = m.mk_elim_unused_vars(q, r); proof * p1 = m.mk_elim_unused_vars(q, r);
pr = m.mk_transitivity(pr, p1); pr = m.mk_transitivity(pr, p1);
@ -744,7 +746,7 @@ namespace eq {
} }
public: public:
der(ast_manager & m): der(ast_manager & m, params_ref const & p):
m(m), m(m),
a(m), a(m),
dt(m), dt(m),
@ -753,7 +755,8 @@ namespace eq {
m_new_exprs(m), m_new_exprs(m),
m_subst_map(m), m_subst_map(m),
m_new_args(m), m_new_args(m),
m_rewriter(m) {} m_rewriter(m),
m_params(p) {}
void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;}
@ -2346,9 +2349,9 @@ private:
} }
public: public:
impl(ast_manager& m): impl(ast_manager & m, params_ref const & p):
m(m), m(m),
m_der(m), m_der(m, p),
m_fm(m), m_fm(m),
m_array_der(m), m_array_der(m),
m_elim_star(*this), m_elim_star(*this),
@ -2438,8 +2441,8 @@ public:
}; };
qe_lite::qe_lite(ast_manager& m) { qe_lite::qe_lite(ast_manager & m, params_ref const & p) {
m_impl = alloc(impl, m); m_impl = alloc(impl, m, p);
} }
qe_lite::~qe_lite() { qe_lite::~qe_lite() {
@ -2471,7 +2474,7 @@ class qe_lite_tactic : public tactic {
imp(ast_manager& m, params_ref const & p): imp(ast_manager& m, params_ref const & p):
m(m), m(m),
m_qe(m) m_qe(m, p)
{} {}
void checkpoint() { void checkpoint() {

View file

@ -31,7 +31,7 @@ class qe_lite {
class impl; class impl;
impl * m_impl; impl * m_impl;
public: public:
qe_lite(ast_manager& m); qe_lite(ast_manager & m, params_ref const & p);
~qe_lite(); ~qe_lite();

View file

@ -154,6 +154,8 @@ namespace sat {
if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution) if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution)
return; return;
// solver::scoped_disable_checkpoint _scoped_disable_checkpoint(s);
initialize(); initialize();
CASSERT("sat_solver", s.check_invariant()); CASSERT("sat_solver", s.check_invariant());
@ -167,7 +169,6 @@ namespace sat {
CASSERT("sat_solver", s.check_invariant()); CASSERT("sat_solver", s.check_invariant());
m_need_cleanup = false; m_need_cleanup = false;
m_use_list.init(s.num_vars()); m_use_list.init(s.num_vars());
init_visited();
m_learned_in_use_lists = false; m_learned_in_use_lists = false;
if (learned) { if (learned) {
register_clauses(s.m_learned); register_clauses(s.m_learned);

View file

@ -33,6 +33,7 @@ namespace sat {
solver::solver(params_ref const & p, reslimit& l, extension * ext): solver::solver(params_ref const & p, reslimit& l, extension * ext):
m_rlimit(l), m_rlimit(l),
m_checkpoint_enabled(true),
m_config(p), m_config(p),
m_ext(ext), m_ext(ext),
m_par(0), m_par(0),

View file

@ -72,6 +72,7 @@ namespace sat {
struct abort_solver {}; struct abort_solver {};
protected: protected:
reslimit& m_rlimit; reslimit& m_rlimit;
bool m_checkpoint_enabled;
config m_config; config m_config;
stats m_stats; stats m_stats;
extension * m_ext; extension * m_ext;
@ -214,6 +215,16 @@ namespace sat {
} }
} }
}; };
class scoped_disable_checkpoint {
solver& s;
public:
scoped_disable_checkpoint(solver& s): s(s) {
s.m_checkpoint_enabled = false;
}
~scoped_disable_checkpoint() {
s.m_checkpoint_enabled = true;
}
};
unsigned select_watch_lit(clause const & cls, unsigned starting_at) const; unsigned select_watch_lit(clause const & cls, unsigned starting_at) const;
unsigned select_learned_watch_lit(clause const & cls) const; unsigned select_learned_watch_lit(clause const & cls) const;
bool simplify_clause(unsigned & num_lits, literal * lits) const; bool simplify_clause(unsigned & num_lits, literal * lits) const;
@ -257,6 +268,7 @@ namespace sat {
lbool status(clause const & c) const; lbool status(clause const & c) const;
clause_offset get_offset(clause const & c) const { return m_cls_allocator.get_offset(&c); } clause_offset get_offset(clause const & c) const { return m_cls_allocator.get_offset(&c); }
void checkpoint() { void checkpoint() {
if (!m_checkpoint_enabled) return;
if (!m_rlimit.inc()) { if (!m_rlimit.inc()) {
m_mc.reset(); m_mc.reset();
m_model_is_current = false; m_model_is_current = false;

View file

@ -64,5 +64,6 @@ def_module_params(module_name='smt',
('core.validate', BOOL, False, 'validate unsat core produced by SMT context'), ('core.validate', BOOL, False, 'validate unsat core produced by SMT context'),
('core.minimize', BOOL, False, 'minimize unsat core produced by SMT context'), ('core.minimize', BOOL, False, 'minimize unsat core produced by SMT context'),
('core.extend_patterns', BOOL, False, 'extend unsat core with literals that trigger (potential) quantifier instances'), ('core.extend_patterns', BOOL, False, 'extend unsat core with literals that trigger (potential) quantifier instances'),
('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core') ('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core'),
('core.extend_nonlocal_patterns', BOOL, False, 'extend unsat cores with literals that have quantifiers with patterns that contain symbols which are not in the quantifier\'s body')
)) ))

View file

@ -3072,11 +3072,11 @@ namespace smt {
m_assumptions.reset(); m_assumptions.reset();
} }
void context::mk_unsat_core() { lbool context::mk_unsat_core() {
SASSERT(inconsistent()); SASSERT(inconsistent());
if (!tracking_assumptions()) { if (!tracking_assumptions()) {
SASSERT(m_assumptions.empty()); SASSERT(m_assumptions.empty());
return; return l_false;
} }
uint_set already_found_assumptions; uint_set already_found_assumptions;
literal_vector::const_iterator it = m_conflict_resolution->begin_unsat_core(); literal_vector::const_iterator it = m_conflict_resolution->begin_unsat_core();
@ -3102,6 +3102,16 @@ namespace smt {
tout << mk_pp(m_unsat_core.get(i), m_manager) << "\n"; tout << mk_pp(m_unsat_core.get(i), m_manager) << "\n";
}); });
validate_unsat_core(); validate_unsat_core();
// theory validation of unsat core
ptr_vector<theory>::iterator th_it = m_theory_set.begin();
ptr_vector<theory>::iterator th_end = m_theory_set.end();
for (; th_it != th_end; ++th_it) {
lbool theory_result = (*th_it)->validate_unsat_core(m_unsat_core);
if (theory_result == l_undef) {
return l_undef;
}
}
return l_false;
} }
/** /**
@ -3144,6 +3154,14 @@ namespace smt {
SASSERT(m_scope_lvl == 0); SASSERT(m_scope_lvl == 0);
SASSERT(!m_setup.already_configured()); SASSERT(!m_setup.already_configured());
setup_context(m_fparams.m_auto_config); setup_context(m_fparams.m_auto_config);
expr_ref_vector theory_assumptions(m_manager);
add_theory_assumptions(theory_assumptions);
if (!theory_assumptions.empty()) {
TRACE("search", tout << "Adding theory assumptions to context" << std::endl;);
return check(theory_assumptions.size(), theory_assumptions.c_ptr(), reset_cancel, true);
}
internalize_assertions(); internalize_assertions();
lbool r = l_undef; lbool r = l_undef;
if (m_asserted_formulas.inconsistent()) { if (m_asserted_formulas.inconsistent()) {
@ -3205,7 +3223,15 @@ namespace smt {
(*it)->setup(); (*it)->setup();
} }
lbool context::check(unsigned num_assumptions, expr * const * assumptions, bool reset_cancel) { void context::add_theory_assumptions(expr_ref_vector & theory_assumptions) {
ptr_vector<theory>::iterator it = m_theory_set.begin();
ptr_vector<theory>::iterator end = m_theory_set.end();
for (; it != end; ++it) {
(*it)->add_theory_assumptions(theory_assumptions);
}
}
lbool context::check(unsigned ext_num_assumptions, expr * const * ext_assumptions, bool reset_cancel, bool already_did_theory_assumptions) {
m_stats.m_num_checks++; m_stats.m_num_checks++;
TRACE("check_bug", tout << "STARTING check(num_assumptions, assumptions)\n"; TRACE("check_bug", tout << "STARTING check(num_assumptions, assumptions)\n";
tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n"; tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";
@ -3216,6 +3242,15 @@ namespace smt {
m_unsat_core.reset(); m_unsat_core.reset();
if (!check_preamble(reset_cancel)) if (!check_preamble(reset_cancel))
return l_undef; return l_undef;
expr_ref_vector all_assumptions(m_manager, ext_num_assumptions, ext_assumptions);
if (!already_did_theory_assumptions) {
add_theory_assumptions(all_assumptions);
}
unsigned num_assumptions = all_assumptions.size();
expr * const * assumptions = all_assumptions.c_ptr();
if (!validate_assumptions(num_assumptions, assumptions)) if (!validate_assumptions(num_assumptions, assumptions))
return l_undef; return l_undef;
TRACE("check_bug", tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";); TRACE("check_bug", tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";);
@ -3239,13 +3274,21 @@ namespace smt {
TRACE("after_internalization", display(tout);); TRACE("after_internalization", display(tout););
if (inconsistent()) { if (inconsistent()) {
VERIFY(!resolve_conflict()); // build the proof VERIFY(!resolve_conflict()); // build the proof
mk_unsat_core(); lbool result = mk_unsat_core();
if (result == l_undef) {
r = l_undef;
} else {
r = l_false; r = l_false;
} }
}
else { else {
r = search(); r = search();
if (r == l_false) if (r == l_false) {
mk_unsat_core(); lbool result = mk_unsat_core();
if (result == l_undef) {
r = l_undef;
}
}
} }
} }
} }

View file

@ -1059,7 +1059,9 @@ namespace smt {
void reset_assumptions(); void reset_assumptions();
void mk_unsat_core(); void add_theory_assumptions(expr_ref_vector & theory_assumptions);
lbool mk_unsat_core();
void validate_unsat_core(); void validate_unsat_core();
@ -1444,7 +1446,7 @@ namespace smt {
void pop(unsigned num_scopes); void pop(unsigned num_scopes);
lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true); lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true, bool already_did_theory_assumptions = false);
lbool get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq, expr_ref_vector& unfixed); lbool get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq, expr_ref_vector& unfixed);

View file

@ -433,6 +433,9 @@ namespace smt {
if (!is_ground(n)) { if (!is_ground(n)) {
continue; continue;
} }
if (is_quantifier(n) && m.is_rec_fun_def(to_quantifier(n))) {
continue;
}
switch (get_assignment(*it)) { switch (get_assignment(*it)) {
case l_undef: case l_undef:
break; break;

View file

@ -246,6 +246,7 @@ namespace smt {
simple_justification::simple_justification(region & r, unsigned num_lits, literal const * lits): simple_justification::simple_justification(region & r, unsigned num_lits, literal const * lits):
m_num_literals(num_lits) { m_num_literals(num_lits) {
if (num_lits != 0) {
m_literals = new (r) literal[num_lits]; m_literals = new (r) literal[num_lits];
memcpy(m_literals, lits, sizeof(literal) * num_lits); memcpy(m_literals, lits, sizeof(literal) * num_lits);
#ifdef Z3DEBUG #ifdef Z3DEBUG
@ -254,6 +255,7 @@ namespace smt {
} }
#endif #endif
} }
}
void simple_justification::get_antecedents(conflict_resolution & cr) { void simple_justification::get_antecedents(conflict_resolution & cr) {
for (unsigned i = 0; i < m_num_literals; i++) for (unsigned i = 0; i < m_num_literals; i++)

View file

@ -316,7 +316,7 @@ namespace smt {
return false; return false;
} }
bool model_checker::check_rec_fun(quantifier* q) { bool model_checker::check_rec_fun(quantifier* q, bool strict_rec_fun) {
TRACE("model_checker", tout << mk_pp(q, m) << "\n";); TRACE("model_checker", tout << mk_pp(q, m) << "\n";);
SASSERT(q->get_num_patterns() == 2); // first pattern is the function, second is the body. SASSERT(q->get_num_patterns() == 2); // first pattern is the function, second is the body.
expr* fn = to_app(q->get_pattern(0))->get_arg(0); expr* fn = to_app(q->get_pattern(0))->get_arg(0);
@ -340,7 +340,7 @@ namespace smt {
} }
sub(q->get_expr(), num_decls, args.c_ptr(), tmp); sub(q->get_expr(), num_decls, args.c_ptr(), tmp);
m_curr_model->eval(tmp, result, true); m_curr_model->eval(tmp, result, true);
if (m.is_false(result)) { if (strict_rec_fun ? !m.is_true(result) : m.is_false(result)) {
add_instance(q, args, 0); add_instance(q, args, 0);
return false; return false;
} }
@ -365,10 +365,10 @@ namespace smt {
bool model_checker::check(proto_model * md, obj_map<enode, app *> const & root2value) { bool model_checker::check(proto_model * md, obj_map<enode, app *> const & root2value) {
SASSERT(md != 0); SASSERT(md != 0);
m_root2value = &root2value; m_root2value = &root2value;
ptr_vector<quantifier>::const_iterator it = m_qm->begin_quantifiers();
ptr_vector<quantifier>::const_iterator end = m_qm->end_quantifiers(); if (m_qm->num_quantifiers() == 0)
if (it == end)
return true; return true;
if (m_iteration_idx >= m_params.m_mbqi_max_iterations) { if (m_iteration_idx >= m_params.m_mbqi_max_iterations) {
@ -393,6 +393,36 @@ namespace smt {
bool found_relevant = false; bool found_relevant = false;
unsigned num_failures = 0; unsigned num_failures = 0;
check_quantifiers(false, found_relevant, num_failures);
if (found_relevant)
m_iteration_idx++;
TRACE("model_checker", tout << "model after check:\n"; model_pp(tout, *md););
TRACE("model_checker", tout << "model checker result: " << (num_failures == 0) << "\n";);
m_max_cexs += m_params.m_mbqi_max_cexs;
if (num_failures == 0 && !m_context->validate_model()) {
num_failures = 1;
// this time force expanding recursive function definitions
// that are not forced true in the current model.
check_quantifiers(true, found_relevant, num_failures);
}
if (num_failures == 0)
m_curr_model->cleanup();
if (m_params.m_mbqi_trace) {
if (num_failures == 0)
verbose_stream() << "(smt.mbqi :succeeded true)\n";
else
verbose_stream() << "(smt.mbqi :num-failures " << num_failures << ")\n";
}
return num_failures == 0;
}
void model_checker::check_quantifiers(bool strict_rec_fun, bool& found_relevant, unsigned& num_failures) {
ptr_vector<quantifier>::const_iterator it = m_qm->begin_quantifiers();
ptr_vector<quantifier>::const_iterator end = m_qm->end_quantifiers();
for (; it != end; ++it) { for (; it != end; ++it) {
quantifier * q = *it; quantifier * q = *it;
if(!m_qm->mbqi_enabled(q)) continue; if(!m_qm->mbqi_enabled(q)) continue;
@ -406,7 +436,7 @@ namespace smt {
} }
found_relevant = true; found_relevant = true;
if (m.is_rec_fun_def(q)) { if (m.is_rec_fun_def(q)) {
if (!check_rec_fun(q)) { if (!check_rec_fun(q, strict_rec_fun)) {
TRACE("model_checker", tout << "checking recursive function failed\n";); TRACE("model_checker", tout << "checking recursive function failed\n";);
num_failures++; num_failures++;
} }
@ -420,26 +450,6 @@ namespace smt {
} }
} }
} }
if (found_relevant)
m_iteration_idx++;
TRACE("model_checker", tout << "model after check:\n"; model_pp(tout, *md););
TRACE("model_checker", tout << "model checker result: " << (num_failures == 0) << "\n";);
m_max_cexs += m_params.m_mbqi_max_cexs;
if (num_failures == 0 && !m_context->validate_model()) {
num_failures = 1;
}
if (num_failures == 0)
m_curr_model->cleanup();
if (m_params.m_mbqi_trace) {
if (num_failures == 0)
verbose_stream() << "(smt.mbqi :succeeded true)\n";
else
verbose_stream() << "(smt.mbqi :num-failures " << num_failures << ")\n";
}
return num_failures == 0;
} }
void model_checker::init_search_eh() { void model_checker::init_search_eh() {

View file

@ -59,7 +59,8 @@ namespace smt {
void assert_neg_q_m(quantifier * q, expr_ref_vector & sks); void assert_neg_q_m(quantifier * q, expr_ref_vector & sks);
bool add_blocking_clause(model * cex, expr_ref_vector & sks); bool add_blocking_clause(model * cex, expr_ref_vector & sks);
bool check(quantifier * q); bool check(quantifier * q);
bool check_rec_fun(quantifier* q); bool check_rec_fun(quantifier* q, bool strict_rec_fun);
void check_quantifiers(bool strict_rec_fun, bool& found_relevant, unsigned& num_failures);
struct instance { struct instance {
quantifier * m_q; quantifier * m_q;

View file

@ -397,6 +397,10 @@ namespace smt {
return m_imp->m_quantifiers.end(); return m_imp->m_quantifiers.end();
} }
unsigned quantifier_manager::num_quantifiers() const {
return m_imp->m_quantifiers.size();
}
// The default plugin uses E-matching, MBQI and quick-checker // The default plugin uses E-matching, MBQI and quick-checker
class default_qm_plugin : public quantifier_manager_plugin { class default_qm_plugin : public quantifier_manager_plugin {
quantifier_manager * m_qm; quantifier_manager * m_qm;

View file

@ -91,6 +91,8 @@ namespace smt {
ptr_vector<quantifier>::const_iterator begin_quantifiers() const; ptr_vector<quantifier>::const_iterator begin_quantifiers() const;
ptr_vector<quantifier>::const_iterator end_quantifiers() const; ptr_vector<quantifier>::const_iterator end_quantifiers() const;
unsigned num_quantifiers() const;
}; };
class quantifier_manager_plugin { class quantifier_manager_plugin {

View file

@ -38,6 +38,7 @@ namespace smt {
bool m_minimizing_core; bool m_minimizing_core;
bool m_core_extend_patterns; bool m_core_extend_patterns;
unsigned m_core_extend_patterns_max_distance; unsigned m_core_extend_patterns_max_distance;
bool m_core_extend_nonlocal_patterns;
obj_map<expr, expr*> m_name2assertion; obj_map<expr, expr*> m_name2assertion;
public: public:
@ -48,13 +49,15 @@ namespace smt {
m_context(m, m_smt_params), m_context(m, m_smt_params),
m_minimizing_core(false), m_minimizing_core(false),
m_core_extend_patterns(false), m_core_extend_patterns(false),
m_core_extend_patterns_max_distance(UINT_MAX) { m_core_extend_patterns_max_distance(UINT_MAX),
m_core_extend_nonlocal_patterns(false) {
m_logic = l; m_logic = l;
if (m_logic != symbol::null) if (m_logic != symbol::null)
m_context.set_logic(m_logic); m_context.set_logic(m_logic);
smt_params_helper smth(p); smt_params_helper smth(p);
m_core_extend_patterns = smth.core_extend_patterns(); m_core_extend_patterns = smth.core_extend_patterns();
m_core_extend_patterns_max_distance = smth.core_extend_patterns_max_distance(); m_core_extend_patterns_max_distance = smth.core_extend_patterns_max_distance();
m_core_extend_nonlocal_patterns = smth.core_extend_nonlocal_patterns();
} }
virtual solver * translate(ast_manager & m, params_ref const & p) { virtual solver * translate(ast_manager & m, params_ref const & p) {
@ -81,6 +84,8 @@ namespace smt {
m_context.updt_params(p); m_context.updt_params(p);
smt_params_helper smth(p); smt_params_helper smth(p);
m_core_extend_patterns = smth.core_extend_patterns(); m_core_extend_patterns = smth.core_extend_patterns();
m_core_extend_patterns_max_distance = smth.core_extend_patterns_max_distance();
m_core_extend_nonlocal_patterns = smth.core_extend_nonlocal_patterns();
} }
virtual void collect_param_descrs(param_descrs & r) { virtual void collect_param_descrs(param_descrs & r) {
@ -172,6 +177,8 @@ namespace smt {
if (m_core_extend_patterns) if (m_core_extend_patterns)
add_pattern_literals_to_core(r); add_pattern_literals_to_core(r);
if (m_core_extend_nonlocal_patterns)
add_nonlocal_pattern_literals_to_core(r);
} }
virtual void get_model(model_ref & m) { virtual void get_model(model_ref & m) {
@ -250,7 +257,7 @@ namespace smt {
} }
}; };
void collect_pattern_func_decls(expr_ref & e, func_decl_set & fds) { void collect_pattern_fds(expr_ref & e, func_decl_set & fds) {
collect_pattern_fds_proc p(get_manager(), fds); collect_pattern_fds_proc p(get_manager(), fds);
expr_mark visited; expr_mark visited;
for_each_expr(p, visited, e); for_each_expr(p, visited, e);
@ -295,7 +302,7 @@ namespace smt {
expr_ref name(core[i], m); expr_ref name(core[i], m);
SASSERT(m_name2assertion.contains(name)); SASSERT(m_name2assertion.contains(name));
expr_ref assrtn(m_name2assertion.find(name), m); expr_ref assrtn(m_name2assertion.find(name), m);
collect_pattern_func_decls(assrtn, pattern_fds); collect_pattern_fds(assrtn, pattern_fds);
} }
if (!pattern_fds.empty()) { if (!pattern_fds.empty()) {
@ -317,6 +324,55 @@ namespace smt {
break; break;
} }
} }
struct collect_body_fds_proc {
ast_manager & m;
func_decl_set & m_fds;
collect_body_fds_proc(ast_manager & m, func_decl_set & fds) :
m(m), m_fds(fds) {
}
void operator()(var * n) {}
void operator()(app * n) {}
void operator()(quantifier * n) {
collect_fds_proc p(m, m_fds);
expr_fast_mark1 visited;
quick_for_each_expr(p, visited, n->get_expr());
}
};
void collect_body_func_decls(expr_ref & e, func_decl_set & fds) {
ast_manager & m = get_manager();
collect_body_fds_proc p(m, fds);
expr_mark visited;
for_each_expr(p, visited, e);
}
void add_nonlocal_pattern_literals_to_core(ptr_vector<expr> & core) {
ast_manager & m = get_manager();
obj_map<expr, expr*>::iterator it = m_name2assertion.begin();
obj_map<expr, expr*>::iterator end = m_name2assertion.end();
for (unsigned i = 0; it != end; it++, i++) {
expr_ref name(it->m_key, m);
expr_ref assrtn(it->m_value, m);
if (!core.contains(name)) {
func_decl_set pattern_fds, body_fds;
collect_pattern_fds(assrtn, pattern_fds);
collect_body_func_decls(assrtn, body_fds);
func_decl_set::iterator pit = pattern_fds.begin();
func_decl_set::iterator pend= pattern_fds.end();
for (; pit != pend; pit++) {
func_decl * fd = *pit;
if (!body_fds.contains(fd)) {
core.insert(name);
break;
}
}
}
}
}
}; };
}; };

View file

@ -177,6 +177,22 @@ namespace smt {
virtual void restart_eh() { virtual void restart_eh() {
} }
/**
\brief This method is called by smt_context before the search starts
to get any extra assumptions the theory wants to use.
(See theory_str for an example)
*/
virtual void add_theory_assumptions(expr_ref_vector & assumptions) {
}
/**
\brief This method is called from smt_context when an unsat core is generated.
The theory may change the answer to UNKNOWN by returning l_undef from this method.
*/
virtual lbool validate_unsat_core(expr_ref_vector & unsat_core) {
return l_false;
}
/** /**
\brief This method is invoked before the search starts. \brief This method is invoked before the search starts.
*/ */

View file

@ -339,8 +339,13 @@ namespace smt {
tout << mk_pp(var, get_manager()) << "\n"; tout << mk_pp(var, get_manager()) << "\n";
tout << "power " << power << ": " << expt(i, power) << "\n"; tout << "power " << power << ": " << expt(i, power) << "\n";
display_interval(tout << "target before: ", target); tout << "\n";); display_interval(tout << "target before: ", target); tout << "\n";);
i.expt(power); i.expt(power);
target *= i; target *= i;
get_manager().limit().inc((target.is_lower_open() || target.minus_infinity()) ? 1 : target.get_lower_value().bitsize());
get_manager().limit().inc((target.is_upper_open() || target.plus_infinity()) ? 1 : target.get_upper_value().bitsize());
TRACE("non_linear", display_interval(tout << "target after: ", target); tout << "\n";); TRACE("non_linear", display_interval(tout << "target after: ", target); tout << "\n";);
} }

View file

@ -255,6 +255,11 @@ final_check_status theory_seq::final_check_eh() {
TRACE("seq", tout << ">>solve_eqs\n";); TRACE("seq", tout << ">>solve_eqs\n";);
return FC_CONTINUE; return FC_CONTINUE;
} }
if (check_contains()) {
++m_stats.m_propagate_contains;
TRACE("seq", tout << ">>propagate_contains\n";);
return FC_CONTINUE;
}
if (solve_nqs(0)) { if (solve_nqs(0)) {
++m_stats.m_solve_nqs; ++m_stats.m_solve_nqs;
TRACE("seq", tout << ">>solve_nqs\n";); TRACE("seq", tout << ">>solve_nqs\n";);
@ -290,11 +295,6 @@ final_check_status theory_seq::final_check_eh() {
TRACE("seq", tout << ">>propagate_automata\n";); TRACE("seq", tout << ">>propagate_automata\n";);
return FC_CONTINUE; return FC_CONTINUE;
} }
if (check_contains()) {
++m_stats.m_propagate_contains;
TRACE("seq", tout << ">>propagate_contains\n";);
return FC_CONTINUE;
}
if (is_solved()) { if (is_solved()) {
TRACE("seq", tout << ">>is_solved\n";); TRACE("seq", tout << ">>is_solved\n";);
return FC_DONE; return FC_DONE;
@ -1159,7 +1159,7 @@ bool theory_seq::check_extensionality() {
} }
/* /*
\brief check negated contains constriants. \brief check negated contains constraints.
*/ */
bool theory_seq::check_contains() { bool theory_seq::check_contains() {
context & ctx = get_context(); context & ctx = get_context();
@ -1199,6 +1199,11 @@ bool theory_seq::is_solved() {
IF_VERBOSE(10, display_disequation(verbose_stream() << "(seq.giveup ", m_nqs[0]); verbose_stream() << " is unsolved)\n";); IF_VERBOSE(10, display_disequation(verbose_stream() << "(seq.giveup ", m_nqs[0]); verbose_stream() << " is unsolved)\n";);
return false; return false;
} }
if (!m_ncs.empty()) {
TRACE("seq", display_nc(tout << "(seq.giveup ", m_ncs[0]); tout << " is unsolved)\n";);
IF_VERBOSE(10, display_nc(verbose_stream() << "(seq.giveup ", m_ncs[0]); verbose_stream() << " is unsolved)\n";);
return false;
}
return true; return true;
} }
@ -1984,6 +1989,22 @@ bool theory_seq::solve_nc(unsigned idx) {
m_new_propagation = true; m_new_propagation = true;
return true; return true;
} }
expr* e1, *e2;
if (m.is_eq(c, e1, e2)) {
literal eq = mk_eq(e1, e2, false);
propagate_lit(deps, 0, 0, ~eq);
return true;
}
if (m.is_or(c)) {
for (unsigned i = 0; i < to_app(c)->get_num_args(); ++i) {
expr_ref ci(to_app(c)->get_arg(i), m);
m_ncs.push_back(nc(ci, deps));
}
m_new_propagation = true;
return true;
}
return false; return false;
} }
@ -2345,6 +2366,17 @@ bool theory_seq::add_itos_axiom(expr* e) {
return false; return false;
} }
add_axiom(mk_eq(e2, n, false)); add_axiom(mk_eq(e2, n, false));
#if 1
expr_ref num_re(m), opt_re(m);
num_re = m_util.re.mk_range(m_util.str.mk_string(symbol("0")), m_util.str.mk_string(symbol("9")));
num_re = m_util.re.mk_plus(num_re);
opt_re = m_util.re.mk_opt(m_util.re.mk_to_re(m_util.str.mk_string(symbol("-"))));
num_re = m_util.re.mk_concat(opt_re, num_re);
app_ref in_re(m_util.re.mk_in_re(e, num_re), m);
internalize_term(in_re);
propagate_in_re(in_re, true);
#endif
m_trail_stack.push(push_replay(alloc(replay_axiom, m, e))); m_trail_stack.push(push_replay(alloc(replay_axiom, m, e)));
return true; return true;
} }
@ -2407,13 +2439,17 @@ void theory_seq::display(std::ostream & out) const {
if (!m_ncs.empty()) { if (!m_ncs.empty()) {
out << "Non contains:\n"; out << "Non contains:\n";
for (unsigned i = 0; i < m_ncs.size(); ++i) { for (unsigned i = 0; i < m_ncs.size(); ++i) {
out << "not " << mk_pp(m_ncs[i].contains(), m) << "\n"; display_nc(out, m_ncs[i]);
display_deps(out << " <- ", m_ncs[i].deps()); out << "\n";
} }
} }
} }
void theory_seq::display_nc(std::ostream& out, nc const& nc) const {
out << "not " << mk_pp(nc.contains(), m) << "\n";
display_deps(out << " <- ", nc.deps()); out << "\n";
}
void theory_seq::display_equations(std::ostream& out) const { void theory_seq::display_equations(std::ostream& out) const {
for (unsigned i = 0; i < m_eqs.size(); ++i) { for (unsigned i = 0; i < m_eqs.size(); ++i) {
display_equation(out, m_eqs[i]); display_equation(out, m_eqs[i]);

View file

@ -570,6 +570,7 @@ namespace smt {
void display_disequation(std::ostream& out, ne const& e) const; void display_disequation(std::ostream& out, ne const& e) const;
void display_deps(std::ostream& out, dependency* deps) const; void display_deps(std::ostream& out, dependency* deps) const;
void display_deps(std::ostream& out, literal_vector const& lits, enode_pair_vector const& eqs) const; void display_deps(std::ostream& out, literal_vector const& lits, enode_pair_vector const& eqs) const;
void display_nc(std::ostream& out, nc const& nc) const;
public: public:
theory_seq(ast_manager& m); theory_seq(ast_manager& m);
virtual ~theory_seq(); virtual ~theory_seq();

View file

@ -34,6 +34,7 @@ class elim_small_bv_tactic : public tactic {
struct rw_cfg : public default_rewriter_cfg { struct rw_cfg : public default_rewriter_cfg {
ast_manager & m; ast_manager & m;
params_ref m_params;
bv_util m_util; bv_util m_util;
simplifier m_simp; simplifier m_simp;
ref<filter_model_converter> m_mc; ref<filter_model_converter> m_mc;
@ -47,6 +48,7 @@ class elim_small_bv_tactic : public tactic {
rw_cfg(ast_manager & _m, params_ref const & p) : rw_cfg(ast_manager & _m, params_ref const & p) :
m(_m), m(_m),
m_params(p),
m_util(_m), m_util(_m),
m_simp(_m), m_simp(_m),
m_bindings(_m), m_bindings(_m),
@ -178,7 +180,7 @@ class elim_small_bv_tactic : public tactic {
quantifier_ref new_q(m); quantifier_ref new_q(m);
new_q = m.update_quantifier(q, body); new_q = m.update_quantifier(q, body);
unused_vars_eliminator el(m); unused_vars_eliminator el(m, m_params);
el(new_q, result); el(new_q, result);
TRACE("elim_small_bv", tout << "elimination result: " << mk_ismt2_pp(result, m) << std::endl; ); TRACE("elim_small_bv", tout << "elimination result: " << mk_ismt2_pp(result, m) << std::endl; );
@ -203,6 +205,7 @@ class elim_small_bv_tactic : public tactic {
} }
void updt_params(params_ref const & p) { void updt_params(params_ref const & p) {
m_params = p;
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
m_max_steps = p.get_uint("max_steps", UINT_MAX); m_max_steps = p.get_uint("max_steps", UINT_MAX);
m_max_bits = p.get_uint("max_bits", 4); m_max_bits = p.get_uint("max_bits", 4);

View file

@ -50,7 +50,7 @@ class distribute_forall_tactic : public tactic {
quantifier_ref tmp_q(m); quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, not_arg); tmp_q = m.update_quantifier(old_q, not_arg);
expr_ref new_q(m); expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q); elim_unused_vars(m, tmp_q, params_ref(), new_q);
new_args.push_back(new_q); new_args.push_back(new_q);
} }
result = m.mk_and(new_args.size(), new_args.c_ptr()); result = m.mk_and(new_args.size(), new_args.c_ptr());
@ -70,7 +70,7 @@ class distribute_forall_tactic : public tactic {
quantifier_ref tmp_q(m); quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, arg); tmp_q = m.update_quantifier(old_q, arg);
expr_ref new_q(m); expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q); elim_unused_vars(m, tmp_q, params_ref(), new_q);
new_args.push_back(new_q); new_args.push_back(new_q);
} }
result = m.mk_and(new_args.size(), new_args.c_ptr()); result = m.mk_and(new_args.size(), new_args.c_ptr());

View file

@ -34,19 +34,19 @@ Notes:
class bounded_int2bv_solver : public solver_na2as { class bounded_int2bv_solver : public solver_na2as {
ast_manager& m; ast_manager& m;
params_ref m_params; params_ref m_params;
bv_util m_bv; mutable bv_util m_bv;
arith_util m_arith; mutable arith_util m_arith;
expr_ref_vector m_assertions; mutable expr_ref_vector m_assertions;
ref<solver> m_solver; ref<solver> m_solver;
ptr_vector<bound_manager> m_bounds; mutable ptr_vector<bound_manager> m_bounds;
func_decl_ref_vector m_bv_fns; mutable func_decl_ref_vector m_bv_fns;
func_decl_ref_vector m_int_fns; mutable func_decl_ref_vector m_int_fns;
unsigned_vector m_bv_fns_lim; unsigned_vector m_bv_fns_lim;
obj_map<func_decl, func_decl*> m_int2bv; mutable obj_map<func_decl, func_decl*> m_int2bv;
obj_map<func_decl, func_decl*> m_bv2int; mutable obj_map<func_decl, func_decl*> m_bv2int;
obj_map<func_decl, rational> m_bv2offset; mutable obj_map<func_decl, rational> m_bv2offset;
bv2int_rewriter_ctx m_rewriter_ctx; mutable bv2int_rewriter_ctx m_rewriter_ctx;
bv2int_rewriter_star m_rewriter; mutable bv2int_rewriter_star m_rewriter;
public: public:
@ -78,7 +78,19 @@ public:
} }
virtual void assert_expr(expr * t) { virtual void assert_expr(expr * t) {
unsigned i = m_assertions.size();
m_assertions.push_back(t); m_assertions.push_back(t);
while (i < m_assertions.size()) {
t = m_assertions[i].get();
if (m.is_and(t)) {
m_assertions.append(to_app(t)->get_num_args(), to_app(t)->get_args());
m_assertions[i] = m_assertions.back();
m_assertions.pop_back();
}
else {
++i;
}
}
} }
virtual void push_core() { virtual void push_core() {
@ -184,7 +196,7 @@ private:
} }
filter_model_converter filter(m); filter_model_converter filter(m);
for (unsigned i = 0; i < m_bv_fns.size(); ++i) { for (unsigned i = 0; i < m_bv_fns.size(); ++i) {
filter.insert(m_bv_fns[i]); filter.insert(m_bv_fns[i].get());
} }
filter(mdl, 0); filter(mdl, 0);
} }
@ -205,13 +217,13 @@ private:
ext(mdl, 0); ext(mdl, 0);
} }
void accumulate_sub(expr_safe_replace& sub) { void accumulate_sub(expr_safe_replace& sub) const {
for (unsigned i = 0; i < m_bounds.size(); ++i) { for (unsigned i = 0; i < m_bounds.size(); ++i) {
accumulate_sub(sub, *m_bounds[i]); accumulate_sub(sub, *m_bounds[i]);
} }
} }
void accumulate_sub(expr_safe_replace& sub, bound_manager& bm) { void accumulate_sub(expr_safe_replace& sub, bound_manager& bm) const {
bound_manager::iterator it = bm.begin(), end = bm.end(); bound_manager::iterator it = bm.begin(), end = bm.end();
for (; it != end; ++it) { for (; it != end; ++it) {
expr* e = *it; expr* e = *it;
@ -252,19 +264,20 @@ private:
sub.insert(e, t); sub.insert(e, t);
} }
else { else {
IF_VERBOSE(1, TRACE("pb",
verbose_stream() << "unprocessed entry: " << mk_pp(e, m) << "\n"; tout << "unprocessed entry: " << mk_pp(e, m) << "\n";
if (bm.has_lower(e, lo, s1)) { if (bm.has_lower(e, lo, s1)) {
verbose_stream() << "lower: " << lo << " " << s1 << "\n"; tout << "lower: " << lo << " " << s1 << "\n";
} }
if (bm.has_upper(e, hi, s2)) { if (bm.has_upper(e, hi, s2)) {
verbose_stream() << "upper: " << hi << " " << s2 << "\n"; tout << "upper: " << hi << " " << s2 << "\n";
}); });
} }
} }
} }
unsigned get_num_bits(rational const& k) {
unsigned get_num_bits(rational const& k) const {
SASSERT(!k.is_neg()); SASSERT(!k.is_neg());
SASSERT(k.is_int()); SASSERT(k.is_int());
rational two(2); rational two(2);
@ -277,11 +290,13 @@ private:
return num_bits; return num_bits;
} }
void flush_assertions() { void flush_assertions() const {
if (m_assertions.empty()) return;
bound_manager& bm = *m_bounds.back(); bound_manager& bm = *m_bounds.back();
for (unsigned i = 0; i < m_assertions.size(); ++i) { for (unsigned i = 0; i < m_assertions.size(); ++i) {
bm(m_assertions[i].get()); bm(m_assertions[i].get());
} }
TRACE("int2bv", bm.display(tout););
expr_safe_replace sub(m); expr_safe_replace sub(m);
accumulate_sub(sub); accumulate_sub(sub);
proof_ref proof(m); proof_ref proof(m);
@ -304,6 +319,17 @@ private:
m_assertions.reset(); m_assertions.reset();
m_rewriter.reset(); m_rewriter.reset();
} }
virtual unsigned get_num_assertions() const {
flush_assertions();
return m_solver->get_num_assertions();
}
virtual expr * get_assertion(unsigned idx) const {
flush_assertions();
return m_solver->get_assertion(idx);
}
}; };
solver * mk_bounded_int2bv_solver(ast_manager & m, params_ref const & p, solver* s) { solver * mk_bounded_int2bv_solver(ast_manager & m, params_ref const & p, solver* s) {

View file

@ -163,6 +163,14 @@ public:
ext(mdl, 0); ext(mdl, 0);
} }
virtual unsigned get_num_assertions() const {
return m_solver->get_num_assertions();
}
virtual expr * get_assertion(unsigned idx) const {
return m_solver->get_assertion(idx);
}
}; };
solver * mk_enum2bv_solver(ast_manager & m, params_ref const & p, solver* s) { solver * mk_enum2bv_solver(ast_manager & m, params_ref const & p, solver* s) {

View file

@ -27,9 +27,9 @@ Notes:
class pb2bv_solver : public solver_na2as { class pb2bv_solver : public solver_na2as {
ast_manager& m; ast_manager& m;
params_ref m_params; params_ref m_params;
expr_ref_vector m_assertions; mutable expr_ref_vector m_assertions;
ref<solver> m_solver; mutable ref<solver> m_solver;
pb2bv_rewriter m_rewriter; mutable pb2bv_rewriter m_rewriter;
public: public:
@ -107,8 +107,19 @@ public:
filter(mdl, 0); filter(mdl, 0);
} }
virtual unsigned get_num_assertions() const {
flush_assertions();
return m_solver->get_num_assertions();
}
virtual expr * get_assertion(unsigned idx) const {
flush_assertions();
return m_solver->get_assertion(idx);
}
private: private:
void flush_assertions() { void flush_assertions() const {
proof_ref proof(m); proof_ref proof(m);
expr_ref fml(m); expr_ref fml(m);
expr_ref_vector fmls(m); expr_ref_vector fmls(m);

View file

@ -417,7 +417,7 @@ expr * ufbv_rewriter::rewrite(expr * n) {
q = m_manager.update_quantifier(to_quantifier(actual), new_body); q = m_manager.update_quantifier(to_quantifier(actual), new_body);
m_new_exprs.push_back(q); m_new_exprs.push_back(q);
expr_ref new_q(m_manager); expr_ref new_q(m_manager);
elim_unused_vars(m_manager, q, new_q); elim_unused_vars(m_manager, q, params_ref(), new_q);
m_new_exprs.push_back(new_q); m_new_exprs.push_back(new_q);
rewrite_cache(e, new_q, true); rewrite_cache(e, new_q, true);
m_rewrite_todo.pop_back(); m_rewrite_todo.pop_back();