summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compat/cvc3_compat.cpp54
-rw-r--r--src/context/Makefile.am4
-rw-r--r--src/context/cdhashmap.h41
-rw-r--r--src/context/cdhashmap_forward.h16
-rw-r--r--src/context/cdhashset.h57
-rw-r--r--src/context/cdinsert_hashmap.h402
-rw-r--r--src/context/cdinsert_hashmap_forward.h38
-rw-r--r--src/context/cdtrail_hashmap.h571
-rw-r--r--src/context/cdtrail_hashmap_forward.h38
-rw-r--r--src/decision/decision_engine.cpp23
-rw-r--r--src/decision/decision_engine.h14
-rw-r--r--src/decision/justification_heuristic.cpp11
-rw-r--r--src/decision/justification_heuristic.h21
-rw-r--r--src/decision/relevancy.h2
-rw-r--r--src/expr/attribute_internals.h2
-rw-r--r--src/expr/expr_manager_template.h2
-rw-r--r--src/expr/expr_template.h2
-rw-r--r--src/expr/kind_template.h2
-rw-r--r--src/expr/type.cpp127
-rw-r--r--src/expr/type.h121
-rw-r--r--src/expr/type.i18
-rw-r--r--src/include/cvc4_public.h14
-rw-r--r--src/lib/Makefile.am7
-rw-r--r--src/lib/clock_gettime.c34
-rw-r--r--src/lib/clock_gettime.h24
-rw-r--r--src/lib/ffs.c40
-rw-r--r--src/lib/ffs.h42
-rw-r--r--src/lib/strtok_r.c41
-rw-r--r--src/lib/strtok_r.h42
-rw-r--r--src/main/Makefile.am8
-rw-r--r--src/main/command_executor.cpp2
-rw-r--r--src/main/util.cpp20
-rw-r--r--src/options/options.h2
-rw-r--r--src/parser/antlr_input.cpp9
-rw-r--r--src/parser/memory_mapped_input_buffer.cpp17
-rw-r--r--src/parser/smt1/Smt1.g102
-rw-r--r--src/printer/smt2/smt2_printer.cpp7
-rw-r--r--src/printer/smt2/smt2_printer.h1
-rw-r--r--src/proof/proof_manager.cpp2
-rw-r--r--src/proof/proof_manager.h2
-rw-r--r--src/prop/bvminisat/core/Solver.cc2
-rw-r--r--src/prop/cnf_stream.cpp33
-rw-r--r--src/prop/cnf_stream.h5
-rw-r--r--src/prop/sat_solver.h3
-rw-r--r--src/smt/options_handlers.h1
-rw-r--r--src/smt/smt_engine.cpp459
-rw-r--r--src/smt/smt_engine.h4
-rw-r--r--src/theory/arith/Makefile.am1
-rw-r--r--src/theory/arith/arith_static_learner.cpp136
-rw-r--r--src/theory/arith/arith_static_learner.h23
-rw-r--r--src/theory/arith/arith_utilities.h53
-rw-r--r--src/theory/arith/arithvar.cpp13
-rw-r--r--src/theory/arith/arithvar.h17
-rw-r--r--src/theory/arith/arithvar_node_map.h31
-rw-r--r--src/theory/arith/congruence_manager.cpp2
-rw-r--r--src/theory/arith/constraint.cpp48
-rw-r--r--src/theory/arith/constraint.h20
-rw-r--r--src/theory/arith/linear_equality.cpp19
-rw-r--r--src/theory/arith/linear_equality.h7
-rw-r--r--src/theory/arith/matrix.cpp16
-rw-r--r--src/theory/arith/matrix.h76
-rw-r--r--src/theory/arith/options12
-rw-r--r--src/theory/arith/partial_model.cpp23
-rw-r--r--src/theory/arith/partial_model.h27
-rw-r--r--src/theory/arith/theory_arith.cpp290
-rw-r--r--src/theory/arith/theory_arith.h35
-rw-r--r--src/theory/arrays/theory_arrays.cpp6
-rw-r--r--src/theory/arrays/theory_arrays.h6
-rw-r--r--src/theory/arrays/theory_arrays_model.h8
-rw-r--r--src/theory/booleans/circuit_propagator.h20
-rw-r--r--src/theory/bv/theory_bv.h4
-rw-r--r--src/theory/bv/theory_bv_rewrite_rules_simplification.h4
-rw-r--r--src/theory/datatypes/options2
-rw-r--r--src/theory/quantifiers/first_order_model.cpp4
-rw-r--r--src/theory/quantifiers/first_order_model.h2
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_gen.cpp10
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_gen.h10
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_match_generator.cpp385
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_match_generator.h42
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_cbqi.cpp28
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_cbqi.h10
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_e_matching.cpp82
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/inst_strategy_e_matching.h14
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/macros.cpp8
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/macros.h8
-rw-r--r--src/theory/quantifiers/model_builder.cpp2
-rw-r--r--src/theory/quantifiers/options4
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/quant_util.cpp8
-rw-r--r--[-rwxr-xr-x]src/theory/quantifiers/quant_util.h10
-rw-r--r--src/theory/quantifiers/quantifiers_attributes.cpp8
-rw-r--r--src/theory/quantifiers/quantifiers_attributes.h8
-rw-r--r--src/theory/quantifiers/term_database.cpp35
-rw-r--r--src/theory/quantifiers/term_database.h2
-rw-r--r--src/theory/quantifiers/trigger.cpp88
-rw-r--r--src/theory/quantifiers/trigger.h4
-rw-r--r--src/theory/quantifiers_engine.cpp23
-rw-r--r--src/theory/quantifiers_engine.h4
-rw-r--r--src/theory/rep_set.cpp10
-rw-r--r--src/theory/rep_set.h8
-rw-r--r--[-rwxr-xr-x]src/theory/rewriterules/efficient_e_matching.cpp10
-rw-r--r--[-rwxr-xr-x]src/theory/rewriterules/efficient_e_matching.h10
-rw-r--r--src/theory/rewriterules/theory_rewriterules.cpp2
-rw-r--r--src/theory/shared_terms_database.h2
-rw-r--r--src/theory/theory.h26
-rw-r--r--src/theory/theory_engine.cpp12
-rw-r--r--src/theory/theory_engine.h7
-rw-r--r--src/theory/uf/options4
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp420
-rw-r--r--src/theory/uf/theory_uf_strong_solver.h39
-rw-r--r--src/util/dense_map.h22
-rw-r--r--src/util/node_visitor.h7
-rw-r--r--src/util/record.h2
-rw-r--r--[-rwxr-xr-x]src/util/sort_inference.cpp34
-rw-r--r--[-rwxr-xr-x]src/util/sort_inference.h12
-rw-r--r--src/util/statistics_registry.h11
115 files changed, 3281 insertions, 1544 deletions
diff --git a/src/compat/cvc3_compat.cpp b/src/compat/cvc3_compat.cpp
index 02d76d351..2a8673451 100644
--- a/src/compat/cvc3_compat.cpp
+++ b/src/compat/cvc3_compat.cpp
@@ -1107,23 +1107,38 @@ Type ValidityChecker::tupleType(const std::vector<Type>& types) {
}
Type ValidityChecker::recordType(const std::string& field, const Type& type) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ std::vector< std::pair<std::string, CVC4::Type> > fields;
+ fields.push_back(std::make_pair(field, (const CVC4::Type&) type));
+ return d_em->mkRecordType(CVC4::Record(fields));
}
Type ValidityChecker::recordType(const std::string& field0, const Type& type0,
const std::string& field1, const Type& type1) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ std::vector< std::pair<std::string, CVC4::Type> > fields;
+ fields.push_back(std::make_pair(field0, (const CVC4::Type&) type0));
+ fields.push_back(std::make_pair(field1, (const CVC4::Type&) type1));
+ return d_em->mkRecordType(CVC4::Record(fields));
}
Type ValidityChecker::recordType(const std::string& field0, const Type& type0,
const std::string& field1, const Type& type1,
const std::string& field2, const Type& type2) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ std::vector< std::pair<std::string, CVC4::Type> > fields;
+ fields.push_back(std::make_pair(field0, (const CVC4::Type&) type0));
+ fields.push_back(std::make_pair(field1, (const CVC4::Type&) type1));
+ fields.push_back(std::make_pair(field2, (const CVC4::Type&) type2));
+ return d_em->mkRecordType(CVC4::Record(fields));
}
Type ValidityChecker::recordType(const std::vector<std::string>& fields,
const std::vector<Type>& types) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ CVC4::CheckArgument(fields.size() == types.size() && fields.size() > 0,
+ "invalid vector length(s) in recordType()");
+ std::vector< std::pair<std::string, CVC4::Type> > fieldSpecs;
+ for(unsigned i = 0; i < fields.size(); ++i) {
+ fieldSpecs.push_back(std::make_pair(fields[i], (const CVC4::Type&) types[i]));
+ }
+ return d_em->mkRecordType(CVC4::Record(fieldSpecs));
}
Type ValidityChecker::dataType(const std::string& name,
@@ -1559,32 +1574,43 @@ Expr ValidityChecker::geExpr(const Expr& left, const Expr& right) {
}
Expr ValidityChecker::recordExpr(const std::string& field, const Expr& expr) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ CVC4::Type t = recordType(field, expr.getType());
+ return d_em->mkExpr(CVC4::kind::RECORD, d_em->mkConst(CVC4::RecordType(t).getRecord()), expr);
}
Expr ValidityChecker::recordExpr(const std::string& field0, const Expr& expr0,
const std::string& field1, const Expr& expr1) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ CVC4::Type t = recordType(field0, expr0.getType(),
+ field1, expr1.getType());
+ return d_em->mkExpr(CVC4::kind::RECORD, d_em->mkConst(CVC4::RecordType(t).getRecord()), expr0, expr1);
}
Expr ValidityChecker::recordExpr(const std::string& field0, const Expr& expr0,
const std::string& field1, const Expr& expr1,
const std::string& field2, const Expr& expr2) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ CVC4::Type t = recordType(field0, expr0.getType(),
+ field1, expr1.getType(),
+ field2, expr2.getType());
+ return d_em->mkExpr(CVC4::kind::RECORD, d_em->mkConst(CVC4::RecordType(t).getRecord()), expr0, expr1, expr2);
}
Expr ValidityChecker::recordExpr(const std::vector<std::string>& fields,
const std::vector<Expr>& exprs) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ std::vector<Type> types;
+ for(unsigned i = 0; i < exprs.size(); ++i) {
+ types.push_back(exprs[i].getType());
+ }
+ CVC4::Type t = recordType(fields, types);
+ return d_em->mkExpr(d_em->mkConst(CVC4::RecordType(t).getRecord()), *reinterpret_cast<const vector<CVC4::Expr>*>(&exprs));
}
Expr ValidityChecker::recSelectExpr(const Expr& record, const std::string& field) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ return d_em->mkExpr(d_em->mkConst(CVC4::RecordSelect(field)), record);
}
Expr ValidityChecker::recUpdateExpr(const Expr& record, const std::string& field,
const Expr& newValue) {
- Unimplemented("Records not supported by CVC4 yet (sorry!)");
+ return d_em->mkExpr(d_em->mkConst(CVC4::RecordUpdate(field)), record, newValue);
}
Expr ValidityChecker::readExpr(const Expr& array, const Expr& index) {
@@ -1935,12 +1961,16 @@ Expr ValidityChecker::tupleExpr(const std::vector<Expr>& exprs) {
}
Expr ValidityChecker::tupleSelectExpr(const Expr& tuple, int index) {
- Unimplemented("Tuples not supported by CVC4 yet (sorry!)");
+ CVC4::CheckArgument(index >= 0 && index < tuple.getNumChildren(),
+ "invalid index in tuple select");
+ return d_em->mkExpr(d_em->mkConst(CVC4::TupleSelect(index)), tuple);
}
Expr ValidityChecker::tupleUpdateExpr(const Expr& tuple, int index,
const Expr& newValue) {
- Unimplemented("Tuples not supported by CVC4 yet (sorry!)");
+ CVC4::CheckArgument(index >= 0 && index < tuple.getNumChildren(),
+ "invalid index in tuple update");
+ return d_em->mkExpr(d_em->mkConst(CVC4::TupleUpdate(index)), tuple, newValue);
}
Expr ValidityChecker::datatypeConsExpr(const std::string& constructor, const std::vector<Expr>& args) {
diff --git a/src/context/Makefile.am b/src/context/Makefile.am
index e7f1dc68b..a63c990cc 100644
--- a/src/context/Makefile.am
+++ b/src/context/Makefile.am
@@ -16,6 +16,10 @@ libcontext_la_SOURCES = \
cdlist_forward.h \
cdqueue.h \
cdtrail_queue.h \
+ cdtrail_hashmap.h \
+ cdtrail_hashmap_forward.h \
+ cdinsert_hashmap.h \
+ cdinsert_hashmap_forward.h \
cdhashmap.h \
cdhashmap_forward.h \
cdhashset.h \
diff --git a/src/context/cdhashmap.h b/src/context/cdhashmap.h
index a37fd2f23..e2ede0603 100644
--- a/src/context/cdhashmap.h
+++ b/src/context/cdhashmap.h
@@ -17,14 +17,19 @@
** and operator== for the key class. For key types that don't have a
** __gnu_cxx::hash<>, you should provide an explicit HashFcn.
**
+ ** See also:
+ ** CDInsertHashMap : An "insert-once" CD hash map.
+ ** CDTrailHashMap : A lightweight CD hash map with poor iteration
+ ** characteristics and some quirks in usage.
+ **
** Internal documentation:
**
- ** CDMap<> is something of a work in progress at present (26 May
+ ** CDHashMap<> is something of a work in progress at present (26 May
** 2010), due to some recent discoveries of problems with its
** internal state. Here are some notes on the internal use of
** CDOhash_maps that may be useful in figuring out this mess:
**
- ** So you have a CDMap<>.
+ ** So you have a CDHashMap<>.
**
** You insert some (key,value) pairs. Each allocates a CDOhash_map<>
** and goes on a doubly-linked list headed by map.d_first and
@@ -36,7 +41,7 @@
** map pointer at level 0, and a non-NULL map pointer in the
** current context level. (Remember that for later.)
**
- ** When a key is associated to a new value in a CDMap, its
+ ** When a key is associated to a new value in a CDHashMap, its
** associated CDOhash_map calls makeCurrent(), then sets the new
** value. The save object is also a CDOhash_map (allocated in context
** memory).
@@ -62,21 +67,21 @@
** obliterate() removes it from the map and frees the CDOhash_map's
** memory.
**
- ** Fourth, you might delete the cdhashmap(calling CDMap::~CDMap()).
+ ** Fourth, you might delete the cdhashmap(calling CDHashMap::~CDHashMap()).
** This first calls destroy(), as per ContextObj contract, but
** cdhashmapdoesn't save/restore itself, so that does nothing at the
- ** CDMap-level. Then it empties the trash. Then, for each
+ ** CDHashMap-level. Then it empties the trash. Then, for each
** element in the map, it marks it as being "part of a complete
** map destruction", which essentially short-circuits
** CDOhash_map::restore() (see CDOhash_map::restore()), then deallocates
** it. Finally it asserts that the trash is empty (which it
** should be, since restore() was short-circuited).
**
- ** Fifth, you might clear() the CDMap. This does exactly the
- ** same as CDMap::~CDMap(), except that it doesn't call destroy()
+ ** Fifth, you might clear() the CDHashMap. This does exactly the
+ ** same as CDHashMap::~CDHashMap(), except that it doesn't call destroy()
** on itself.
**
- ** CDMap::emptyTrash() simply goes through and calls
+ ** CDHashMap::emptyTrash() simply goes through and calls
** ->deleteSelf() on all elements in the trash.
** ContextObj::deleteSelf() calls the CDOhash_map destructor, then
** frees the memory associated to the CDOhash_map. CDOhash_map::~CDOhash_map()
@@ -87,8 +92,8 @@
#include "cvc4_private.h"
-#ifndef __CVC4__CONTEXT__CDMAP_H
-#define __CVC4__CONTEXT__CDMAP_H
+#ifndef __CVC4__CONTEXT__CDHASHMAP_H
+#define __CVC4__CONTEXT__CDHASHMAP_H
#include <vector>
#include <iterator>
@@ -148,9 +153,9 @@ class CDOhash_map : public ContextObj {
d_next->d_prev = d_prev;
d_prev->d_next = d_next;
if(d_noTrash) {
- Debug("gc") << "CDMap<> no-trash " << this << std::endl;
+ Debug("gc") << "CDHashMap<> no-trash " << this << std::endl;
} else {
- Debug("gc") << "CDMap<> trash push_back " << this << std::endl;
+ Debug("gc") << "CDHashMap<> trash push_back " << this << std::endl;
//this->deleteSelf();
d_map->d_trash.push_back(this);
}
@@ -190,7 +195,7 @@ public:
// "Initializing" map insertion: this entry will never be
// removed from the map, it's inserted at level 0 as an
// "initializing" element. See
- // CDMap<>::insertAtContextLevelZero().
+ // CDHashMap<>::insertAtContextLevelZero().
d_data = data;
} else {
// Normal map insertion: first makeCurrent(), then set the data
@@ -417,7 +422,7 @@ public:
}
/**
- * Version of insert() for CDMap<> that inserts data value d at
+ * Version of insert() for CDHashMap<> that inserts data value d at
* context level zero. This is a special escape hatch for inserting
* "initializing" data into the map. Imagine something happens at a
* deep context level L that causes insertion into a map, such that
@@ -538,7 +543,7 @@ public:
const std::pair<const Key, Data>& operator*() const {
return *d_pair;
}
- };/* class CDMap<>::iterator::Proxy */
+ };/* class CDHashMap<>::iterator::Proxy */
// Actual postfix increment: returns Proxy with the old value.
// Now, an expression like *i++ will return the current *i, and
@@ -549,7 +554,7 @@ public:
++(*this);
return e;
}
- };/* class CDMap<>::iterator */
+ };/* class CDHashMap<>::iterator */
typedef iterator const_iterator;
@@ -576,9 +581,9 @@ public:
return const_cast<const CDHashMap*>(this)->find(k);
}
-};/* class CDMap<> */
+};/* class CDHashMap<> */
}/* CVC4::context namespace */
}/* CVC4 namespace */
-#endif /* __CVC4__CONTEXT__CDMAP_H */
+#endif /* __CVC4__CONTEXT__CDHashMAP_H */
diff --git a/src/context/cdhashmap_forward.h b/src/context/cdhashmap_forward.h
index d81f5345d..60291af07 100644
--- a/src/context/cdhashmap_forward.h
+++ b/src/context/cdhashmap_forward.h
@@ -9,22 +9,22 @@
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief This is a forward declaration header to declare the CDMap<>
+ ** \brief This is a forward declaration header to declare the CDHashMap<>
** template
**
- ** This is a forward declaration header to declare the CDMap<>
- ** template. It's useful if you want to forward-declare CDMap<>
- ** without including the full cdmap.h header, for example, in a
+ ** This is a forward declaration header to declare the CDHashMap<>
+ ** template. It's useful if you want to forward-declare CDHashMap<>
+ ** without including the full cdhashmap.h header, for example, in a
** public header context.
**
- ** For CDMap<> in particular, it's difficult to forward-declare it
+ ** For CDHashMap<> in particular, it's difficult to forward-declare it
** yourself, because it has a default template argument.
**/
#include "cvc4_public.h"
-#ifndef __CVC4__CONTEXT__CDMAP_FORWARD_H
-#define __CVC4__CONTEXT__CDMAP_FORWARD_H
+#ifndef __CVC4__CONTEXT__CDHASHMAP_FORWARD_H
+#define __CVC4__CONTEXT__CDHASHMAP_FORWARD_H
/// \cond internals
@@ -41,4 +41,4 @@ namespace CVC4 {
/// \endcond
-#endif /* __CVC4__CONTEXT__CDMAP_FORWARD_H */
+#endif /* __CVC4__CONTEXT__CDHASHMAP_FORWARD_H */
diff --git a/src/context/cdhashset.h b/src/context/cdhashset.h
index e885b7729..d7957cf3f 100644
--- a/src/context/cdhashset.h
+++ b/src/context/cdhashset.h
@@ -20,16 +20,15 @@
#define __CVC4__CONTEXT__CDSET_H
#include "context/context.h"
-#include "context/cdhashset_forward.h"
-#include "context/cdhashmap.h"
+#include "context/cdinsert_hashmap.h"
#include "util/cvc4_assert.h"
namespace CVC4 {
namespace context {
template <class V, class HashFcn>
-class CDHashSet : protected CDHashMap<V, V, HashFcn> {
- typedef CDHashMap<V, V, HashFcn> super;
+class CDHashSet : protected CDInsertHashMap<V, bool, HashFcn> {
+ typedef CDInsertHashMap<V, bool, HashFcn> super;
public:
@@ -58,40 +57,30 @@ public:
return super::size();
}
- size_t count(const V& v) const {
- return super::count(v);
- }
-
bool insert(const V& v) {
- return super::insert(v, v);
- }
-
- void insertAtContextLevelZero(const V& v) {
- return super::insertAtContextLevelZero(v, v);
+ return super::insert_safe(v, true);
}
bool contains(const V& v) {
- return find(v) != end();
+ return super::contains(v);
}
- // FIXME: no erase(), too much hassle to implement efficiently...
-
- class iterator {
- typename super::iterator d_it;
+ class const_iterator {
+ typename super::const_iterator d_it;
public:
- iterator(const typename super::iterator& it) : d_it(it) {}
- iterator(const iterator& it) : d_it(it.d_it) {}
+ const_iterator(const typename super::const_iterator& it) : d_it(it) {}
+ const_iterator(const const_iterator& it) : d_it(it.d_it) {}
// Default constructor
- iterator() {}
+ const_iterator() {}
// (Dis)equality
- bool operator==(const iterator& i) const {
+ bool operator==(const const_iterator& i) const {
return d_it == i.d_it;
}
- bool operator!=(const iterator& i) const {
+ bool operator!=(const const_iterator& i) const {
return d_it != i.d_it;
}
@@ -101,7 +90,7 @@ public:
}
// Prefix increment
- iterator& operator++() {
+ const_iterator& operator++() {
++d_it;
return *this;
}
@@ -131,18 +120,28 @@ public:
}
};/* class CDSet<>::iterator */
- typedef iterator const_iterator;
-
const_iterator begin() const {
- return iterator(super::begin());
+ return const_iterator(super::begin());
}
const_iterator end() const {
- return iterator(super::end());
+ return const_iterator(super::end());
}
const_iterator find(const V& v) const {
- return iterator(super::find(v));
+ return const_iterator(super::find(v));
+ }
+
+ typedef typename super::key_iterator key_iterator;
+ key_iterator key_begin() const {
+ return super::key_begin();
+ }
+ key_iterator key_end() const {
+ return super::key_end();
+ }
+
+ void insertAtContextLevelZero(const V& v) {
+ return super::insertAtContextLevelZero(v, true);
}
};/* class CDSet */
diff --git a/src/context/cdinsert_hashmap.h b/src/context/cdinsert_hashmap.h
new file mode 100644
index 000000000..0c84eda80
--- /dev/null
+++ b/src/context/cdinsert_hashmap.h
@@ -0,0 +1,402 @@
+/********************* */
+/*! \file cdinsert_hashmap.h
+ ** \verbatim
+ ** Original author: taking
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Context-dependent insert only hashmap built using trail of edits
+ **
+ ** Context-dependent hashmap that only allows for one insertion per element.
+ ** This can be viewed as a highly restricted version of CDHashMap.
+ ** It is significantly lighter in memory usage than CDHashMap.
+ **
+ ** See also:
+ ** CDTrailHashMap : A lightweight CD hash map with poor iteration
+ ** characteristics and some quirks in usage.
+ ** CDHashMap : A fully featured CD hash map. (The closest to <ext/hash_map>)
+ **
+ ** Notes:
+ ** - To iterate efficiently over the elements use the key_iterators.
+ ** - operator[] is only supported as a const derefence (must succeed).
+ ** - insert(k) must always work.
+ ** - Use insert_safe if you want to check if the element has been inserted
+ ** and only insert if it has not yet been.
+ ** - Does not accept TNodes as keys.
+ ** - Supports insertAtContextLevelZero() if the element is not in the map.
+ **/
+
+
+#include "cvc4_private.h"
+
+#include "context/context.h"
+#include "context/cdinsert_hashmap_forward.h"
+#include <utility>
+#include <ext/hash_map>
+#include <deque>
+#include "util/cvc4_assert.h"
+#include "util/output.h"
+
+#include "expr/node.h"
+#include <boost/static_assert.hpp>
+
+#pragma once
+
+namespace CVC4 {
+namespace context {
+
+
+template <class Key, class Data, class HashFcn = __gnu_cxx::hash<Key> >
+class InsertHashMap {
+private:
+ typedef std::deque<Key> KeyVec;
+ /** A list of the keys in the map maintained as a stack. */
+ KeyVec d_keys;
+
+ typedef __gnu_cxx::hash_map<Key, Data, HashFcn> HashMap;
+ /** The hash_map used for element lookup. */
+ HashMap d_hashMap;
+
+public:
+ /**
+ * An iterator over a list of keys.
+ * Use this to efficiently iterate over the elements.
+ * (See std::deque<>::iterator).
+ */
+ typedef typename KeyVec::const_iterator key_iterator;
+
+ /**An iterator over the elements in the hash_map. */
+ typedef typename HashMap::const_iterator const_iterator;
+
+
+ /**
+ * Returns an iterator to the begining of the HashMap.
+ * Acts like a hash_map::const_iterator.
+ */
+ const_iterator begin() const{
+ return d_hashMap.begin();
+ }
+ /**
+ * Returns an iterator to the end of the HashMap.
+ * Acts like a hash_map::const_iterator.
+ */
+ const_iterator end() const{
+ return d_hashMap.end();
+ }
+
+ /**
+ * Returns an iterator to the Key k of the map.
+ * See hash_map::find()
+ */
+ const_iterator find(const Key& k) const{
+ return d_hashMap.find(k);
+ }
+
+ /** Returns an iterator to the start of the set of keys. */
+ key_iterator key_begin() const{
+ return d_keys.begin();
+ }
+ /** Returns an iterator to the end of the set of keys. */
+ key_iterator key_end() const{
+ return d_keys.end();
+ }
+
+ /** Returns true if the map is empty. */
+ bool empty() const { return d_keys.empty(); }
+ /** Returns the number of elements in the map. */
+ size_t size() const { return d_keys.size(); }
+
+ /** Returns true if k is a mapped key. */
+ bool contains(const Key& k) const {
+ return find(k) != end();
+ }
+
+ /**
+ * Returns a reference the data mapped by k.
+ * This must succeed.
+ */
+ const Data& operator[](const Key& k) const {
+ const_iterator ci = find(k);
+ Assert(ci != end());
+ return (*ci).second;
+ }
+
+ /**
+ * Inserts an element into the map, and pushes its key to the front
+ * of the stack. The key inserted must be not be currently mapped.
+ */
+ void push_front(const Key& k, const Data& d){
+ Assert(!contains(k));
+ d_hashMap.insert(std::make_pair(k, d));
+ d_keys.push_front(k);
+ }
+
+ /**
+ * Inserts an element into the map, and pushes its key onto the
+ * back on the stack. The key inserted must be not be currently mapped.
+ */
+ void push_back(const Key& k, const Data& d){
+ Assert(!contains(k));
+ d_hashMap.insert(std::make_pair(k, d));
+ d_keys.push_back(k);
+ }
+
+ /**
+ * Pops the key at the front of the list off and removes its key from the map.
+ */
+ void pop_front(){
+ Assert(!empty());
+ const Key& front = d_keys.front();
+ d_hashMap.erase(front);
+
+ Debug("TrailHashMap") <<"TrailHashMap pop_front " << size() << std::endl;
+ d_keys.pop_front();
+ }
+
+ /**
+ * Pops the key at the back of the stack off and removes its key from the map.
+ */
+ void pop_back(){
+ Assert(!empty());
+ const Key& back = d_keys.back();
+ d_hashMap.erase(back);
+
+ Debug("TrailHashMap") <<"TrailHashMap pop_back " << size() << std::endl;
+ d_keys.pop_back();
+ }
+
+ /**
+ * Pops the back of the stack until the size is below s.
+ */
+ void pop_to_size(size_t s){
+ while(size() > s){
+ pop_back();
+ }
+ }
+};/* class TrailHashMap<> */
+
+template <class Key, class Data, class HashFcn >
+class CDInsertHashMap : public ContextObj {
+private:
+ typedef InsertHashMap<Key, Data, HashFcn> IHM;
+
+ /** An InsertHashMap that backs all of the data. */
+ IHM* d_insertMap;
+
+ /** For restores, we need to keep track of the previous size. */
+ size_t d_size;
+
+ /**
+ * To support insertAtContextLevelZero() and restores,
+ * we have called d_insertMap->d_pushFront().
+ */
+ size_t d_pushFronts;
+
+ /**
+ * Private copy constructor used only by save(). d_insertMap is
+ * not copied: only the base class information and
+ * d_size and d_pushFronts are needed in restore.
+ */
+ CDInsertHashMap(const CDInsertHashMap<Key, Data, HashFcn>& l) :
+ ContextObj(l),
+ d_insertMap(NULL),
+ d_size(l.d_size),
+ d_pushFronts(l.d_pushFronts)
+ {
+ Debug("CDInsertHashMap") << "copy ctor: " << this
+ << " from " << &l
+ << " size " << d_size << std::endl;
+ }
+
+ /**
+ * Implementation of mandatory ContextObj method save: simply copies
+ * the current size information to a copy using the copy constructor (the
+ * pointer and the allocated size are *not* copied as they are not
+ * restored on a pop). The saved information is allocated using the
+ * ContextMemoryManager.
+ */
+ ContextObj* save(ContextMemoryManager* pCMM) {
+ ContextObj* data = new(pCMM) CDInsertHashMap<Key, Data, HashFcn>(*this);
+ Debug("CDInsertHashMap") << "save " << this
+ << " at level " << this->getContext()->getLevel()
+ << " size at " << this->d_size
+ << " d_list is " << this->d_insertMap
+ << " data:" << data << std::endl;
+ return data;
+ }
+protected:
+ /**
+ * Implementation of mandatory ContextObj method restore:
+ * restore to the previous size taking into account the number
+ * of new pushFront calls have happened since saving.
+ * The d_insertMap is untouched and d_pushFronts is also kept.
+ */
+ void restore(ContextObj* data) {
+ Debug("CDInsertHashMap") << "restore " << this
+ << " level " << this->getContext()->getLevel()
+ << " data == " << data
+ << " d_insertMap == " << this->d_insertMap << std::endl;
+ size_t oldSize = ((CDInsertHashMap<Key, Data, HashFcn>*)data)->d_size;
+ size_t oldPushFronts = ((CDInsertHashMap<Key, Data, HashFcn>*)data)->d_pushFronts;
+ Assert(oldPushFronts <= d_pushFronts);
+
+ // The size to restore to.
+ size_t restoreSize = oldSize + (d_pushFronts - oldPushFronts);
+ d_insertMap->pop_to_size(restoreSize);
+ d_size = restoreSize;
+ Assert(d_insertMap->size() == d_size);
+ Debug("CDInsertHashMap") << "restore " << this
+ << " level " << this->getContext()->getLevel()
+ << " size back to " << this->d_size << std::endl;
+ }
+public:
+
+ /**
+ * Main constructor: d_insertMap starts as an empty map, with the size is 0
+ */
+ CDInsertHashMap(Context* context) :
+ ContextObj(context),
+ d_insertMap(new IHM()),
+ d_size(0),
+ d_pushFronts(0){
+ Assert(d_insertMap->size() == d_size);
+ }
+
+ /**
+ * Destructor: delete the d_insertMap
+ */
+ ~CDInsertHashMap() throw(AssertionException) {
+ this->destroy();
+ delete d_insertMap;
+ }
+
+ /** An iterator over the elements in the hash_map. */
+ typedef typename IHM::const_iterator const_iterator;
+
+ /**
+ * An iterator over a list of keys.
+ * Use this to efficiently iterate over the elements.
+ * (See std::deque<>::iterator).
+ */
+ typedef typename IHM::key_iterator key_iterator;
+
+ /** Returns true if the map is empty in the current context. */
+ bool empty() const{
+ return d_size == 0;
+ }
+
+ /** Returns true the size of the map in the current context. */
+ size_t size() const {
+ return d_size;
+ }
+
+ /**
+ * Inserts an element into the map.
+ * The key inserted must be not be currently mapped.
+ * This is implemented using d_insertMap.push_back().
+ */
+ void insert(const Key& k, const Data& d){
+ makeCurrent();
+ ++d_size;
+ d_insertMap->push_back(k, d);
+ Assert(d_insertMap->size() == d_size);
+ }
+
+ /**
+ * Checks if the key k is mapped already.
+ * If it is, this returns false.
+ * Otherwise it is inserted and this returns true.
+ */
+ bool insert_safe(const Key& k, const Data& d){
+ if(contains(k)){
+ return false;
+ }else{
+ insert(k,d);
+ return true;
+ }
+ }
+
+ /**
+ * Version of insert() for CDMap<> that inserts data value d at
+ * context level zero.
+ *
+ * It is an error to insertAtContextLevelZero()
+ * a key that already is in the map.
+ */
+ void insertAtContextLevelZero(const Key& k, const Data& d){
+ makeCurrent();
+ ++d_size;
+ ++d_pushFronts;
+ d_insertMap->push_front(k, d);
+ }
+
+ /** Returns true if k is a mapped key in the context. */
+ bool contains(const Key& k) const {
+ return d_insertMap->contains(k);
+ }
+
+ /**
+ * Returns a reference the data mapped by k.
+ * k must be in the map in this context.
+ */
+ const Data& operator[](const Key& k) const {
+ return (*d_insertMap)[k];
+ }
+
+ /**
+ * Returns a const_iterator to the value_type if k is a mapped key in
+ * the context.
+ */
+ const_iterator find(const Key& k) const {
+ return d_insertMap->find(k);
+ }
+
+ /**
+ * Returns an iterator to the begining of the map.
+ * Acts like a hash_map::const_iterator.
+ */
+ const_iterator begin() const{
+ return d_insertMap->begin();
+ }
+
+ /**
+ * Returns an iterator to the end of the map.
+ * Acts like a hash_map::const_iterator.
+ */
+ const_iterator end() const{
+ return d_insertMap->end();
+ }
+
+ /** Returns an iterator to the start of the set of keys. */
+ key_iterator key_begin() const{
+ return d_insertMap->key_begin();
+ }
+ /** Returns an iterator to the end of the set of keys. */
+ key_iterator key_end() const{
+ return d_insertMap->key_end();
+ }
+};/* class CDInsertHashMap<> */
+
+
+template <class Data, class HashFcn>
+class CDInsertHashMap <TNode, Data, HashFcn > : public ContextObj {
+ /* CDInsertHashMap is challenging to get working with TNode.
+ * Consider using CDHashMap<TNode,...> instead.
+ *
+ * Explanation:
+ * CDInsertHashMap uses keys for deallocation.
+ * If the key is a TNode and the backing (the hard node reference)
+ * for the key in another data structure removes the key at the same context
+ * the ref count could drop to 0. The key would then not be eligible to be
+ * hashed. Getting the order right with a guarentee is to hard.
+ */
+
+ BOOST_STATIC_ASSERT(sizeof(Data) == 0);
+};
+
+}/* CVC4::context namespace */
+}/* CVC4 namespace */
diff --git a/src/context/cdinsert_hashmap_forward.h b/src/context/cdinsert_hashmap_forward.h
new file mode 100644
index 000000000..638607840
--- /dev/null
+++ b/src/context/cdinsert_hashmap_forward.h
@@ -0,0 +1,38 @@
+/********************* */
+/*! \file cdinsert_hashmap_forward.h
+ ** \verbatim
+ ** Original author: taking
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief This is a forward declaration header to declare the CDInsertHashMap<>
+ ** template
+ **
+ ** This is a forward declaration header to declare the CDInsertHashMap<>
+ ** template. It's useful if you want to forward-declare CDInsertHashMap<>
+ ** without including the full cdinsert_hashmap.h header, for example, in a
+ ** public header context.
+ **
+ ** For CDInsertHashMap<> in particular, it's difficult to forward-declare it
+ ** yourself, because it has a default template argument.
+ **/
+
+#include "cvc4_public.h"
+
+#pragma once
+
+namespace __gnu_cxx {
+ template <class Key> struct hash;
+}/* __gnu_cxx namespace */
+
+namespace CVC4 {
+ namespace context {
+ template <class Key, class Data, class HashFcn = __gnu_cxx::hash<Key> >
+ class CDInsertHashMap;
+ }/* CVC4::context namespace */
+}/* CVC4 namespace */
+
diff --git a/src/context/cdtrail_hashmap.h b/src/context/cdtrail_hashmap.h
new file mode 100644
index 000000000..5f090341d
--- /dev/null
+++ b/src/context/cdtrail_hashmap.h
@@ -0,0 +1,571 @@
+/********************* */
+/*! \file cdtrail_hashmap.h
+ ** \verbatim
+ ** Original author: taking
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Context-dependent hashmap built using trail of elements
+ **
+ ** Context-dependent hashmap that explicitly keeps track of its edit history.
+ ** This is similar in functionality to CDHashMap with fewer capabilites and
+ ** slight changes in the interface. It has the advantage of being lighter in
+ ** memory usage.
+ **
+ ** See also:
+ ** CDInsertHashMap : An "insert-once" CD hash map.
+ ** CDHashMap : A fully featured CD hash map. (The closest to <ext/hash_map>)
+ **
+ ** Notes:
+ ** - To iterate efficiently over the elements use the key_iterators.
+ ** - operator[] is only supported as a const derefence (must succeed).
+ ** - Insertions to the map are done with respect to a context.
+ ** - Insertions can be done in two manors either with insert() or
+ ** insert_no_overwrite().
+ ** - insert(k,d) inserts the key data pair into the hashtable and returns a
+ ** false if it overwrote the previous value.
+ ** - insert_no_overwrite(k,d) inserts key data pair into the hashtable only
+ ** if the value is not already there. It returns true, if an element was
+ ** added. This conditionally extends the trail length if it returns true.
+ ** - inserts are compacting. If there is another insert to the same key
+ ** at the same context, the memory is reused.
+ ** - Iterating over const_iterators has amortized time proportional to
+ ** O(trail length). (If this needs to be improved, please bug Tim.)
+ ** - contains() and operator[] are slightly faster than using stl style
+ ** iterator comparisons: find(), end(), etc.
+ **/
+
+
+#include "cvc4_private.h"
+
+#pragma once
+
+#include "context/context.h"
+#include "context/cdtrail_hashmap_forward.h"
+#include <utility>
+#include <ext/hash_map>
+#include <deque>
+#include "util/cvc4_assert.h"
+#include "util/output.h"
+
+#include "expr/node.h"
+#include <boost/static_assert.hpp>
+
+
+namespace CVC4 {
+namespace context {
+
+
+template <class Key, class Data, class HashFcn = __gnu_cxx::hash<Key> >
+class TrailHashMap {
+public:
+ /** A pair of Key and Data that mirrors hash_map::value_type. */
+ typedef std::pair<Key, Data> value_type;
+
+private:
+
+ /** The trail information from an insert. */
+ struct KDT {
+ /** The Key Data pair. */
+ value_type d_kd;
+
+ /**
+ * The previous trail entry with the same key.
+ * On a pop, this is the element to revert to.
+ * This value is a self loop if there is no previous entry.
+ */
+ size_t d_prevKey;
+
+ /** The whether the trail element is current. */
+ bool d_current;
+
+ KDT(const Key& key, const Data& data, size_t prev, bool cur = true):
+ d_kd(std::make_pair(key, data)), d_prevKey(prev), d_current(cur){ }
+ KDT(){}
+ };
+
+ typedef std::deque<KDT> KDTVec;
+ typedef typename KDTVec::const_iterator KDTVec_const_iterator;
+ /** The trail of elements. */
+ KDTVec d_kdts;
+
+
+ typedef __gnu_cxx::hash_map<Key, size_t, HashFcn> PositionMap;
+ typedef typename PositionMap::iterator PM_iterator;
+ typedef typename PositionMap::const_iterator PM_const_iterator;
+
+ /** A map of keys to their positions in the trail. */
+ PositionMap d_posMap;
+
+
+ /** The number of unique keys in the map. */
+ size_t d_uniqueKeys;
+
+ /** Internal utility class. NonConstant find on the position map.*/
+ inline PM_iterator ncfind(const Key& k) {
+ return d_posMap.find(k);
+ }
+
+ /** Internal utility class. Position Map Find.*/
+ inline PM_const_iterator pmfind(const Key& k) const{
+ return d_posMap.find(k);
+ }
+ /** Internal utility class. Position Map End.*/
+ inline PM_const_iterator pmend() const{
+ return d_posMap.end();
+ }
+
+ /** This is true if the previous entry in the trail points at itself.*/
+ inline bool selfLoop(size_t pos, const KDT& kdt) const {
+ return pos == kdt.d_prevKey;
+ }
+
+public:
+ /**
+ * Constant iterator for TrailHashMap.
+ * Only supports forward iteration.
+ * This always points at the end or a current element in the trail.
+ * This is done by iterating over the trail.
+ */
+ class const_iterator {
+ private:
+ /** A vector iterator. */
+ KDTVec_const_iterator d_it;
+
+ /** A pointer to the end of the vector.*/
+ KDTVec_const_iterator d_end;
+
+ /** Move the iterator to the end or the next current element.*/
+ void findCurrent(){
+ while(d_it != d_end && !(*d_it).d_current){
+ ++d_it;
+ }
+ }
+
+ public:
+
+ /** Constructs an iterator for a TrailHashMap. */
+ const_iterator(KDTVec_const_iterator it, KDTVec_const_iterator end) :
+ d_it(it),
+ d_end(end){
+ findCurrent();
+ }
+
+ /** Copy constructor for an iterator for a TrailHashMap. */
+ const_iterator(const const_iterator& other) :
+ d_it(other.d_it), d_end(other.d_end){
+ // Do not need to findCurrent()
+ }
+
+ /** Returns true if the iterators are the same. */
+ inline bool operator==(const const_iterator& other) const {
+ return d_it == other.d_it;
+ }
+
+ /** Returns true if the iterators are the same. */
+ inline bool operator!=(const const_iterator& other) const {
+ return d_it != other.d_it;
+ }
+
+ /** Returns a pair<Key,Data>. */
+ inline const value_type& operator*() const {
+ return (*d_it).d_kd;
+ }
+
+ /** Prefix increment */
+ const_iterator& operator++() {
+ ++d_it;
+ findCurrent();
+ return *this;
+ }
+ };
+
+ /** Returns a beginning iterator.*/
+ inline const_iterator begin() const{
+ return const_iterator(d_kdts.begin(), d_kdts.end());
+ }
+
+ /** Returns an end iterator.*/
+ inline const_iterator end() const{
+ return const_iterator(d_kdts.end(), d_kdts.end());
+ }
+
+ /** Returns true if the trail is empty.*/
+ inline bool empty() const { return d_kdts.empty(); }
+
+ /** Returns the size of the trail.*/
+ inline size_t trailSize() const { return d_kdts.size(); }
+
+ /** Returns the number of unique keys in the map.*/
+ inline size_t uniqueKeys() const { return d_uniqueKeys; }
+
+ /** Returns true if the key is in the map.*/
+ inline bool contains(const Key& k) const {
+ return pmfind(k) != pmend();
+ }
+
+ /**
+ * Returns a NON const reference to an element in the Map.
+ * k must be a key in the Map.
+ * DO NOT USE THIS UNLESS YOU ARE CONFIDENT THE CHANGES MAKE SENSE.
+ */
+ Data& lookup(const Key& k){
+ Assert(contains(k));
+ PM_iterator ci = ncfind(k);
+ KDT& kdt = d_kdts[(*ci).second];
+ return kdt.d_kd.second;
+ }
+
+ /**
+ * Returns a const reference to an element mapped by a Key k.
+ * k must be a key in the Map.
+ */
+ const Data& operator[](const Key& k) const {
+ PM_const_iterator pci = pmfind(k);
+ Assert(pci != pmend());
+ return d_kdts[(*pci).second].d_kd.second;
+ }
+
+ /**
+ * If the key k is in the map, this returns a const_iterator pointing at this
+ * element. Otherwise, this returns end().
+ */
+ const_iterator find(const Key& k) const {
+ PM_const_iterator pci = pmfind(k);
+ if(pci == pmend()){
+ return end();
+ }else{
+ size_t pos = (*pci).second;
+ return const_iterator(d_kdts.begin() + pos, d_kdts.end());
+ }
+ }
+
+ /**
+ * Similar to contains, but includes a notion of trail position.
+ * Returns <true, true> if contains(k) and the current position of k
+ * in the map is greater than or equal to pos.
+ * Returns <true, false> if it contains(k) but not the previous condition.
+ * Returns <false, false> if it does not contains(k).
+ */
+ std::pair<bool, bool> hasAfter(const Key& k, size_t pos) {
+ PM_iterator it = ncfind(k);
+ if(it != d_posMap.end()){
+ return std::make_pair(true, (*it).second >= pos );
+ }
+ return std::make_pair(false, false);
+ }
+
+ /**
+ * Inserts an element unconditionally.
+ * Always increases the trail size.
+ * Returns true if the key count increased.
+ */
+ bool push_back(const Key& k, const Data& d){
+ std::pair<bool, bool> res = compacting_push_back(k, d, trailSize());
+ return res.first;
+ }
+
+ /**
+ * This inserts an element into the trail.
+ * This insert can reuse the same trail element if the postion of the element
+ * is >= threshold.
+ *
+ * Return values:
+ * If pair<bool, bool> res = compacting_push_back(..),
+ * then res.first is true if this is a new unique key, and
+ * res.second is true if the trail length increased.
+ *
+ */
+ std::pair<bool, bool> compacting_push_back(const Key& k, const Data& d, size_t threshold){
+ size_t backPos = d_kdts.size();
+ std::pair<PM_iterator, bool> res = d_posMap.insert(std::make_pair(k, backPos));
+ if(!res.second){
+ size_t& prevPosInPM = (*res.first).second;
+
+ Assert(d_kdts[prevPosInPM].d_current);
+
+ if(prevPosInPM < threshold){
+ d_kdts.push_back(KDT(k,d, prevPosInPM));
+ d_kdts[prevPosInPM].d_current = false;
+ prevPosInPM = backPos;
+
+ return std::make_pair(false, true);
+ }else{
+ d_kdts[prevPosInPM].d_kd.second = d;
+ return std::make_pair(false, false);
+ }
+ }else{
+ d_kdts.push_back(KDT(k,d, backPos));
+ ++d_uniqueKeys;
+ return std::make_pair(true, true);
+ }
+ }
+
+ /**
+ * Inserts an element if the key is not already in the map.
+ * Returns true if the element was inserted.
+ */
+ bool insert_no_overwrite(const Key& k, const Data& d){
+ size_t backPos = d_kdts.size();
+ std::pair<PM_iterator, bool> res = d_posMap.insert(std::make_pair(k, backPos));
+ if(res.second){
+ d_kdts.push_back(KDT(k,d, backPos));
+ ++d_uniqueKeys;
+ }
+ Debug("TrailHashMap") <<"TrailHashMap insert" << k << " d " << d << " " << backPos << std::endl;
+ return res.second;
+ }
+
+ /** Pops the element at the back of the trail. */
+ void pop_back(){
+ Assert(!empty());
+ const KDT& back = d_kdts.back();
+ const Key& k = back.d_kd.first;
+ if(selfLoop(trailSize()-1, back)){
+ d_posMap.erase(k);
+ --d_uniqueKeys;
+ Debug("TrailHashMap") <<"TrailHashMap pop_back erase " << trailSize() <<" " << std::endl;
+
+ }else{
+ Debug("TrailHashMap") <<"TrailHashMap reset " << trailSize() <<" " << " " << back.d_prevKey << std::endl;
+ d_posMap[k] = back.d_prevKey;
+ d_kdts[back.d_prevKey].d_current = true;
+ }
+ d_kdts.pop_back();
+ }
+
+ /** Pops the element at the back of the trail until the trailSize is <= s. */
+ void pop_to_size(size_t s){
+ while(trailSize() > s){
+ pop_back();
+ }
+ }
+};/* class TrailHashMap<> */
+
+template <class Key, class Data, class HashFcn >
+class CDTrailHashMap : public ContextObj {
+private:
+ /** A short name for the templatized TrailMap that backs the CDTrailMap. */
+ typedef TrailHashMap<Key, Data, HashFcn> THM;
+
+ /** The trail map that backs the CDTrailMap. */
+ THM* d_trailMap;
+public:
+ /** Iterator for the CDTrailHashMap. */
+ typedef typename THM::const_iterator const_iterator;
+
+ /** Return value of operator* on a const_iterator (pair<Key,Data>).*/
+ typedef typename THM::value_type value_type;
+
+private:
+ /**
+ * The length of the trail in the current context.
+ * This is used to support reverting.
+ */
+ size_t d_trailSize;
+
+ /**
+ * The length of the trail immediately after the previous makeCurrent().
+ * This is used to support compacting inserts.
+ */
+ size_t d_prevTrailSize;
+
+ /**
+ * Private copy constructor used only by save(). d_trailMap is not copied:
+ * only the base class information, d_trailSize, and d_prevTrailSize
+ * are needed in restore.
+ */
+ CDTrailHashMap(const CDTrailHashMap<Key, Data, HashFcn>& l) :
+ ContextObj(l),
+ d_trailMap(NULL),
+ d_trailSize(l.d_trailSize),
+ d_prevTrailSize(l.d_prevTrailSize){
+ Debug("CDTrailHashMap") << "copy ctor: " << this
+ << " from " << &l
+ << " size " << d_trailSize << std::endl;
+ }
+
+ /**
+ * Implementation of mandatory ContextObj method save: simply copies
+ * the current sizes to a copy using the copy constructor,
+ * The saved information is allocated using the ContextMemoryManager.
+ */
+ ContextObj* save(ContextMemoryManager* pCMM) {
+ ContextObj* data = new(pCMM) CDTrailHashMap<Key, Data, HashFcn>(*this);
+ Debug("CDTrailHashMap") << "save " << this
+ << " at level " << this->getContext()->getLevel()
+ << " size at " << this->d_trailSize
+ << " d_list is " << this->d_trailMap
+ << " data:" << data << std::endl;
+ return data;
+ }
+protected:
+ /**
+ * Implementation of mandatory ContextObj method restore: simply
+ * restores the previous size. Note that the list pointer and the
+ * allocated size are not changed.
+ */
+ void restore(ContextObj* data) {
+ Debug("CDTrailHashMap") << "restore " << this
+ << " level " << this->getContext()->getLevel()
+ << " data == " << data
+ << " d_trailMap == " << this->d_trailMap << std::endl;
+ size_t oldSize = ((CDTrailHashMap<Key, Data, HashFcn>*)data)->d_trailSize;
+ d_trailMap->pop_to_size(oldSize);
+ d_trailSize = oldSize;
+ Assert(d_trailMap->trailSize() == d_trailSize);
+
+ d_prevTrailSize = ((CDTrailHashMap<Key, Data, HashFcn>*)data)->d_prevTrailSize;
+ Debug("CDTrailHashMap") << "restore " << this
+ << " level " << this->getContext()->getLevel()
+ << " size back to " << this->d_trailSize << std::endl;
+ }
+
+ /**
+ * We need to save the d_trailSize immediately after a successful makeCurrent.
+ * So this version needs to be used everywhere instead of maekCurrent()
+ * internally.
+ */
+ void internalMakeCurrent () {
+ if(!isCurrent()){
+ makeCurrent();
+ d_prevTrailSize = d_trailSize;
+ }
+ }
+
+public:
+
+ /**
+ * Main constructor: d_trailMap starts as an empty map, with the sizes are 0
+ */
+ CDTrailHashMap(Context* context) :
+ ContextObj(context),
+ d_trailMap(new THM()),
+ d_trailSize(0),
+ d_prevTrailSize(0){
+ Assert(d_trailMap->trailSize() == d_trailSize);
+ }
+
+ /**
+ * Destructor: delete the map
+ */
+ ~CDTrailHashMap() throw(AssertionException) {
+ this->destroy();
+ delete d_trailMap;
+ }
+
+ /** Returns true if the map is empty in the current context. */
+ bool empty() const{
+ return d_trailSize == 0;
+ }
+
+ /** Returns true the size of the map in the current context. */
+ size_t size() const {
+ return d_trailMap->uniqueKeys();
+ }
+
+ /**
+ * Inserts an element into the map.
+ * This always succeeds.
+ * Returns true if the key is new.
+ */
+ bool insert(const Key& k, const Data& d){
+ internalMakeCurrent();
+ std::pair<bool, bool> res = d_trailMap->compacting_push_back(k, d, d_prevTrailSize);
+ if(res.second){
+ ++d_trailSize;
+ }
+ Assert(d_trailMap->trailSize() == d_trailSize);
+ return res.first;
+ }
+
+ /**
+ * Inserts an element into the map if the key is not already there.
+ * This has no side effects if the insert does not happen.
+ * Returns true if the element was inserted.
+ */
+ bool insert_no_overwrite(const Key& k, const Data& d){
+ bool res = d_trailMap->insert_no_overwrite(k, d);
+ if(res){
+ internalMakeCurrent();
+ ++d_trailSize;
+ }
+ Assert(d_trailMap->trailSize() == d_trailSize);
+ return res;
+ }
+
+ /** Returns true if k is a mapped key in the context. */
+ bool contains(const Key& k) const {
+ return d_trailMap->contains(k);
+ }
+
+ /**
+ * Returns a reference the data mapped by k.
+ * k must be in the map in this context.
+ */
+ const Data& operator[](const Key& k) const {
+ return (*d_trailMap)[k];
+ }
+ /*
+// While the following code "works", I wonder if it is not better to disable it?
+// Non-const operator[] has strange semantics for a context-dependent
+// data structure.
+ Data& operator[](const Key& k) {
+ internalMakeCurrent();
+ std::pair<bool, bool> res = d_trailMap->hasAfter(k, d_prevTrailSize);
+ if(!res.first){
+ std::pair<bool, bool> res = d_trailMap->compacting_push_back(k, Data(), d_prevTrailSize);
+ if(res.second){
+ ++d_trailSize;
+ }
+ }else if(!res.second){
+ std::pair<bool, bool> res = d_trailMap->compacting_push_back(k, (*d_trailMap)[k], d_prevTrailSize);
+ if(res.second){
+ ++d_trailSize;
+ }
+ }
+ return d_trailMap->lookup(k);
+ }
+ */
+
+ /**
+ * Returns a const_iterator to the value_type if k is a mapped key in
+ * the context.
+ */
+ const_iterator find(const Key& k) const {
+ return d_trailMap->find(k);
+ }
+
+ /** Returns an iterator to the begining of the map. */
+ const_iterator begin() const{
+ return d_trailMap->begin();
+ }
+ /** Returns an iterator to the end of the map. */
+ const_iterator end() const{
+ return d_trailMap->end();
+ }
+
+};/* class CDTrailHashMap<> */
+
+template <class Data, class HashFcn>
+class CDTrailHashMap <TNode, Data, HashFcn > : public ContextObj {
+ /* CDTrailHashMap is challenging to get working with TNode.
+ * Consider using CDHashMap<TNode,...> instead.
+ *
+ * Explanation:
+ * CDTrailHashMap uses keys during deallocation.
+ * If the key is a TNode and the backing (the hard node reference)
+ * for the key in another data structure removes the key at the same context
+ * the ref count could drop to 0. The key would then not be eligible to be
+ * hashed. Getting the order right with a guarentee is to hard.
+ */
+
+ BOOST_STATIC_ASSERT(sizeof(Data) == 0);
+};
+
+}/* CVC4::context namespace */
+}/* CVC4 namespace */
diff --git a/src/context/cdtrail_hashmap_forward.h b/src/context/cdtrail_hashmap_forward.h
new file mode 100644
index 000000000..549ecd738
--- /dev/null
+++ b/src/context/cdtrail_hashmap_forward.h
@@ -0,0 +1,38 @@
+/********************* */
+/*! \file cdtrail_hashmap_forward.h
+ ** \verbatim
+ ** Original author: taking
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 prototype.
+ ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief This is a forward declaration header to declare the
+ ** CDTrailHashMap<> template
+ **
+ ** This is a forward declaration header to declare the CDTrailHashMap<>
+ ** template. It's useful if you want to forward-declare CDTrailHashMap<>
+ ** without including the full cdtrail_hash_map.h header, for example, in a
+ ** public header context.
+ **
+ ** For CDTrailHashMap<> in particular, it's difficult to forward-declare it
+ ** yourself, because it has a default template argument.
+ **/
+
+#include "cvc4_public.h"
+
+#pragma once
+
+namespace __gnu_cxx {
+ template <class Key> struct hash;
+}/* __gnu_cxx namespace */
+
+namespace CVC4 {
+ namespace context {
+ template <class Key, class Data, class HashFcn = __gnu_cxx::hash<Key> >
+ class CDTrailHashMap;
+ }/* CVC4::context namespace */
+}/* CVC4 namespace */
+
diff --git a/src/decision/decision_engine.cpp b/src/decision/decision_engine.cpp
index 22c70eb6d..9e8add752 100644
--- a/src/decision/decision_engine.cpp
+++ b/src/decision/decision_engine.cpp
@@ -33,7 +33,7 @@ DecisionEngine::DecisionEngine(context::Context *sc,
d_enabledStrategies(),
d_needIteSkolemMap(),
d_relevancyStrategy(NULL),
- d_assertions(),
+ d_assertions(uc),
d_cnfStream(NULL),
d_satSolver(NULL),
d_satContext(sc),
@@ -50,18 +50,6 @@ void DecisionEngine::init()
d_engineState = 1;
Trace("decision-init") << "DecisionEngine::init()" << std::endl;
- if(options::incrementalSolving()) {
- if(options::decisionMode() != decision::DECISION_STRATEGY_INTERNAL) {
- if(options::decisionMode.wasSetByUser()) {
- Warning() << "Ignorning decision option since using incremental mode (currently not supported together)"
- << std::endl;
- } else {
- Notice() << "Using internal decision heuristic since using incremental mode (not supported currently)"
- << std::endl;
- }
- }
- return;
- }
Trace("decision-init") << " * options->decisionMode: "
<< options::decisionMode() << std:: endl;
Trace("decision-init") << " * options->decisionStopOnly: "
@@ -70,11 +58,16 @@ void DecisionEngine::init()
if(options::decisionMode() == decision::DECISION_STRATEGY_INTERNAL) { }
if(options::decisionMode() == decision::DECISION_STRATEGY_JUSTIFICATION) {
ITEDecisionStrategy* ds =
- new decision::JustificationHeuristic(this, d_satContext);
+ new decision::JustificationHeuristic(this, d_userContext, d_satContext);
enableStrategy(ds);
d_needIteSkolemMap.push_back(ds);
}
if(options::decisionMode() == decision::DECISION_STRATEGY_RELEVANCY) {
+ if(options::incrementalSolving()) {
+ Warning() << "Relevancy decision heuristic and incremental not supported together"
+ << std::endl;
+ return; // Currently not supported with incremental
+ }
RelevancyStrategy* ds =
new decision::Relevancy(this, d_satContext);
enableStrategy(ds);
@@ -137,7 +130,7 @@ void DecisionEngine::addAssertions(const vector<Node> &assertions,
// new assertions, reset whatever result we knew
d_result = SAT_VALUE_UNKNOWN;
- d_assertions.reserve(assertions.size());
+ // d_assertions.reserve(assertions.size());
for(unsigned i = 0; i < assertions.size(); ++i)
d_assertions.push_back(assertions[i]);
diff --git a/src/decision/decision_engine.h b/src/decision/decision_engine.h
index 4d354af2a..ea16cec16 100644
--- a/src/decision/decision_engine.h
+++ b/src/decision/decision_engine.h
@@ -42,7 +42,8 @@ class DecisionEngine {
vector <ITEDecisionStrategy* > d_needIteSkolemMap;
RelevancyStrategy* d_relevancyStrategy;
- vector <Node> d_assertions;
+ typedef context::CDList<Node> AssertionsList;
+ AssertionsList d_assertions;
// PropEngine* d_propEngine;
CnfStream* d_cnfStream;
@@ -55,7 +56,7 @@ class DecisionEngine {
context::CDO<SatValue> d_result;
// Disable creating decision engine without required parameters
- DecisionEngine() : d_result(NULL) {}
+ DecisionEngine();
// init/shutdown state
unsigned d_engineState; // 0=pre-init; 1=init,pre-shutdown; 2=shutdown
@@ -68,8 +69,6 @@ public:
/** Destructor, currently does nothing */
~DecisionEngine() {
Trace("decision") << "Destroying decision engine" << std::endl;
- for(unsigned i = 0; i < d_enabledStrategies.size(); ++i)
- delete d_enabledStrategies[i];
}
// void setPropEngine(PropEngine* pe) {
@@ -99,14 +98,15 @@ public:
/**
* This is called by SmtEngine, at shutdown time, just before
* destruction. It is important because there are destruction
- * ordering issues between some parts of the system. For now,
- * there's nothing to do here in the DecisionEngine.
+ * ordering issues between some parts of the system.
*/
void shutdown() {
Assert(d_engineState == 1);
d_engineState = 2;
Trace("decision") << "Shutting down decision engine" << std::endl;
+ for(unsigned i = 0; i < d_enabledStrategies.size(); ++i)
+ delete d_enabledStrategies[i];
}
// Interface for External World to use our services
@@ -191,7 +191,7 @@ public:
/**
* Get the assertions. Strategies are notified when these are available.
*/
- const vector<Node>& getAssertions() {
+ AssertionsList& getAssertions() {
return d_assertions;
}
diff --git a/src/decision/justification_heuristic.cpp b/src/decision/justification_heuristic.cpp
index 4ec4588f3..46ec6f09f 100644
--- a/src/decision/justification_heuristic.cpp
+++ b/src/decision/justification_heuristic.cpp
@@ -74,7 +74,7 @@ void JustificationHeuristic::computeITEs(TNode n, IteList &l)
for(unsigned i=0; i<n.getNumChildren(); ++i) {
SkolemMap::iterator it2 = d_iteAssertions.find(n[i]);
if(it2 != d_iteAssertions.end()) {
- l.push_back(make_pair(n[i], it2->second));
+ l.push_back(make_pair(n[i], (*it2).second));
Assert(n[i].getNumChildren() == 0);
}
if(d_visitedComputeITE.find(n[i]) ==
@@ -103,6 +103,15 @@ bool JustificationHeuristic::findSplitterRec(TNode node,
SatValue desiredVal,
SatLiteral* litDecision)
{
+ /**
+ * Main idea
+ *
+ * Given a boolean formula "node", the goal is to try to make it
+ * evaluate to "desiredVal" (true/false). for instance if "node" is a AND
+ * formula we want to make it evaluate to true, we'd like one of the
+ * children to be true. this is done recursively.
+ */
+
Trace("jh-findSplitterRec")
<< "findSplitterRec(" << node << ", "
<< desiredVal << ", .. )" << std::endl;
diff --git a/src/decision/justification_heuristic.h b/src/decision/justification_heuristic.h
index 5d13d2dd2..272dffc88 100644
--- a/src/decision/justification_heuristic.h
+++ b/src/decision/justification_heuristic.h
@@ -27,6 +27,8 @@
#include "decision_strategy.h"
#include "context/cdhashset.h"
+#include "context/cdlist.h"
+#include "context/cdhashmap.h"
#include "expr/node.h"
#include "prop/sat_solver_types.h"
@@ -44,10 +46,10 @@ public:
class JustificationHeuristic : public ITEDecisionStrategy {
typedef std::vector<pair<TNode,TNode> > IteList;
typedef hash_map<TNode,IteList,TNodeHashFunction> IteCache;
- typedef hash_map<TNode,TNode,TNodeHashFunction> SkolemMap;
+ typedef context::CDHashMap<TNode,TNode,TNodeHashFunction> SkolemMap;
// being 'justified' is monotonic with respect to decisions
- typedef context::CDHashSet<TNode,TNodeHashFunction> JustifiedSet;
+ typedef context::CDHashSet<Node,NodeHashFunction> JustifiedSet;
JustifiedSet d_justified;
context::CDO<unsigned> d_prvsIndex;
@@ -59,7 +61,7 @@ class JustificationHeuristic : public ITEDecisionStrategy {
* A copy of the assertions that need to be justified
* directly. Doesn't have ones introduced during during ITE-removal.
*/
- std::vector<TNode> d_assertions;
+ context::CDList<TNode> d_assertions;
//TNode is fine since decisionEngine has them too
/** map from ite-rewrite skolem to a boolean-ite assertion */
@@ -83,13 +85,17 @@ class JustificationHeuristic : public ITEDecisionStrategy {
*/
hash_set<TNode,TNodeHashFunction> d_visitedComputeITE;
public:
- JustificationHeuristic(CVC4::DecisionEngine* de, context::Context *c):
+ JustificationHeuristic(CVC4::DecisionEngine* de,
+ context::Context *uc,
+ context::Context *c):
ITEDecisionStrategy(de, c),
d_justified(c),
d_prvsIndex(c, 0),
d_helfulness("decision::jh::helpfulness", 0),
d_giveup("decision::jh::giveup", 0),
- d_timestat("decision::jh::time") {
+ d_timestat("decision::jh::time"),
+ d_assertions(uc),
+ d_iteAssertions(uc) {
StatisticsRegistry::registerStat(&d_helfulness);
StatisticsRegistry::registerStat(&d_giveup);
StatisticsRegistry::registerStat(&d_timestat);
@@ -97,6 +103,7 @@ public:
}
~JustificationHeuristic() {
StatisticsRegistry::unregisterStat(&d_helfulness);
+ StatisticsRegistry::unregisterStat(&d_giveup);
StatisticsRegistry::unregisterStat(&d_timestat);
}
prop::SatLiteral getNext(bool &stopSearch) {
@@ -106,8 +113,8 @@ public:
d_visited.clear();
if(Trace.isOn("justified")) {
- for(JustifiedSet::iterator i = d_justified.begin();
- i != d_justified.end(); ++i) {
+ for(JustifiedSet::key_iterator i = d_justified.key_begin();
+ i != d_justified.key_end(); ++i) {
TNode n = *i;
SatLiteral l = d_decisionEngine->hasSatLiteral(n) ?
d_decisionEngine->getSatLiteral(n) : -1;
diff --git a/src/decision/relevancy.h b/src/decision/relevancy.h
index 8a6eb54ef..bfd30ddde 100644
--- a/src/decision/relevancy.h
+++ b/src/decision/relevancy.h
@@ -60,7 +60,7 @@ class Relevancy : public RelevancyStrategy {
typedef hash_map<TNode,SatValue,TNodeHashFunction> PolarityCache;
// being 'justified' is monotonic with respect to decisions
- context::CDHashSet<TNode,TNodeHashFunction> d_justified;
+ context::CDHashSet<Node, NodeHashFunction> d_justified;
context::CDO<unsigned> d_prvsIndex;
IntStat d_helfulness;
diff --git a/src/expr/attribute_internals.h b/src/expr/attribute_internals.h
index a085161bc..9a14caec5 100644
--- a/src/expr/attribute_internals.h
+++ b/src/expr/attribute_internals.h
@@ -752,7 +752,7 @@ public:
table_value_type table_value_type;
typedef attr::AttributeTraits<table_value_type, context_dep> traits;
uint64_t id = attr::LastAttributeId<table_value_type, context_dep>::s_id++;
- Assert(traits::cleanup.size() == id);// sanity check
+ //Assert(traits::cleanup.size() == id);// sanity check
traits::cleanup.push_back(attr::getCleanupStrategy<value_t,
CleanupStrategy>::fn);
return id;
diff --git a/src/expr/expr_manager_template.h b/src/expr/expr_manager_template.h
index b9cae9431..09018cbfd 100644
--- a/src/expr/expr_manager_template.h
+++ b/src/expr/expr_manager_template.h
@@ -43,7 +43,7 @@ class SmtEngine;
class NodeManager;
class Options;
class IntStat;
-class ExprManagerMapCollection;
+struct ExprManagerMapCollection;
class StatisticsRegistry;
namespace expr {
diff --git a/src/expr/expr_template.h b/src/expr/expr_template.h
index a52bc00ac..f5df63f8c 100644
--- a/src/expr/expr_template.h
+++ b/src/expr/expr_template.h
@@ -67,7 +67,7 @@ namespace prop {
class TheoryProxy;
}/* CVC4::prop namespace */
-class ExprManagerMapCollection;
+struct ExprManagerMapCollection;
struct ExprHashFunction;
diff --git a/src/expr/kind_template.h b/src/expr/kind_template.h
index 47504b0e4..0cab4e628 100644
--- a/src/expr/kind_template.h
+++ b/src/expr/kind_template.h
@@ -27,7 +27,7 @@
namespace CVC4 {
namespace kind {
-enum Kind_t {
+enum CVC4_PUBLIC Kind_t {
UNDEFINED_KIND = -1, /**< undefined */
NULL_EXPR, /**< Null kind */
${kind_decls}
diff --git a/src/expr/type.cpp b/src/expr/type.cpp
index cc52b11b9..4e95c0fe2 100644
--- a/src/expr/type.cpp
+++ b/src/expr/type.cpp
@@ -204,111 +204,48 @@ bool Type::isBoolean() const {
return d_typeNode->isBoolean();
}
-/** Cast to a Boolean type */
-Type::operator BooleanType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isBoolean(), this);
- return BooleanType(*this);
-}
-
/** Is this the integer type? */
bool Type::isInteger() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isInteger();
}
-/** Cast to a integer type */
-Type::operator IntegerType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isInteger(), this);
- return IntegerType(*this);
-}
-
/** Is this the real type? */
bool Type::isReal() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isReal();
}
-/** Cast to a real type */
-Type::operator RealType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isReal(), this);
- return RealType(*this);
-}
-
/** Is this the string type? */
bool Type::isString() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isString();
}
-/** Cast to a string type */
-Type::operator StringType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isString(), this);
- return StringType(*this);
-}
-
/** Is this the bit-vector type? */
bool Type::isBitVector() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isBitVector();
}
-/** Cast to a bit-vector type */
-Type::operator BitVectorType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isBitVector(), this);
- return BitVectorType(*this);
-}
-
-/** Cast to a Constructor type */
-Type::operator DatatypeType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isDatatype(), this);
- return DatatypeType(*this);
-}
-
/** Is this a datatype type? */
bool Type::isDatatype() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isDatatype() || d_typeNode->isParametricDatatype();
}
-/** Cast to a Constructor type */
-Type::operator ConstructorType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isConstructor(), this);
- return ConstructorType(*this);
-}
-
/** Is this the Constructor type? */
bool Type::isConstructor() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isConstructor();
}
-/** Cast to a Selector type */
-Type::operator SelectorType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isSelector(), this);
- return SelectorType(*this);
-}
-
/** Is this the Selector type? */
bool Type::isSelector() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isSelector();
}
-/** Cast to a Tester type */
-Type::operator TesterType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isTester(), this);
- return TesterType(*this);
-}
-
/** Is this the Tester type? */
bool Type::isTester() const {
NodeManagerScope nms(d_nodeManager);
@@ -330,64 +267,30 @@ bool Type::isPredicate() const {
return d_typeNode->isPredicate();
}
-/** Cast to a function type */
-Type::operator FunctionType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isFunction(), this);
- return FunctionType(*this);
-}
-
/** Is this a tuple type? */
bool Type::isTuple() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isTuple();
}
-/** Cast to a tuple type */
-Type::operator TupleType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isTuple(), this);
- return TupleType(*this);
-}
-
/** Is this a record type? */
bool Type::isRecord() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isRecord();
}
-/** Cast to a record type */
-Type::operator RecordType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isRecord(), this);
- return RecordType(*this);
-}
-
/** Is this a symbolic expression type? */
bool Type::isSExpr() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isSExpr();
}
-/** Cast to a symbolic expression type */
-Type::operator SExprType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isSExpr(), this);
- return SExprType(*this);
-}
-
/** Is this an array type? */
bool Type::isArray() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isArray();
}
-/** Cast to an array type */
-Type::operator ArrayType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- return ArrayType(*this);
-}
-
/** Is this a sort kind */
bool Type::isSort() const {
NodeManagerScope nms(d_nodeManager);
@@ -395,25 +298,11 @@ bool Type::isSort() const {
}
/** Cast to a sort type */
-Type::operator SortType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isSort(), this);
- return SortType(*this);
-}
-
-/** Is this a sort constructor kind */
bool Type::isSortConstructor() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isSortConstructor();
}
-/** Cast to a sort constructor type */
-Type::operator SortConstructorType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isSortConstructor(), this);
- return SortConstructorType(*this);
-}
-
/** Is this a predicate subtype */
/* - not in release 1.0
bool Type::isPredicateSubtype() const {
@@ -422,28 +311,12 @@ bool Type::isPredicateSubtype() const {
}
*/
-/** Cast to a predicate subtype */
-/* - not in release 1.0
-Type::operator PredicateSubtype() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isPredicateSubtype(), this);
- return PredicateSubtype(*this);
-}
-*/
-
/** Is this an integer subrange */
bool Type::isSubrange() const {
NodeManagerScope nms(d_nodeManager);
return d_typeNode->isSubrange();
}
-/** Cast to a predicate subtype */
-Type::operator SubrangeType() const throw(IllegalArgumentException) {
- NodeManagerScope nms(d_nodeManager);
- CheckArgument(isNull() || isSubrange(), this);
- return SubrangeType(*this);
-}
-
vector<Type> FunctionType::getArgTypes() const {
NodeManagerScope nms(d_nodeManager);
vector<Type> args;
diff --git a/src/expr/type.h b/src/expr/type.h
index 4223d71ab..ce6291cd8 100644
--- a/src/expr/type.h
+++ b/src/expr/type.h
@@ -30,15 +30,15 @@
namespace CVC4 {
class NodeManager;
-class ExprManager;
-class Expr;
+class CVC4_PUBLIC ExprManager;
+class CVC4_PUBLIC Expr;
class TypeNode;
-class ExprManagerMapCollection;
+struct CVC4_PUBLIC ExprManagerMapCollection;
-class SmtEngine;
+class CVC4_PUBLIC SmtEngine;
-class Datatype;
-class Record;
+class CVC4_PUBLIC Datatype;
+class CVC4_PUBLIC Record;
template <bool ref_count>
class NodeTemplate;
@@ -240,60 +240,30 @@ public:
bool isBoolean() const;
/**
- * Cast this type to a Boolean type
- * @return the BooleanType
- */
- operator BooleanType() const throw(IllegalArgumentException);
-
- /**
* Is this the integer type?
* @return true if the type is a integer type
*/
bool isInteger() const;
/**
- * Cast this type to a integer type
- * @return the IntegerType
- */
- operator IntegerType() const throw(IllegalArgumentException);
-
- /**
* Is this the real type?
* @return true if the type is a real type
*/
bool isReal() const;
/**
- * Cast this type to a real type
- * @return the RealType
- */
- operator RealType() const throw(IllegalArgumentException);
-
- /**
* Is this the string type?
* @return true if the type is the string type
*/
bool isString() const;
/**
- * Cast this type to a string type
- * @return the StringType
- */
- operator StringType() const throw(IllegalArgumentException);
-
- /**
* Is this the bit-vector type?
* @return true if the type is a bit-vector type
*/
bool isBitVector() const;
/**
- * Cast this type to a bit-vector type
- * @return the BitVectorType
- */
- operator BitVectorType() const throw(IllegalArgumentException);
-
- /**
* Is this a function type?
* @return true if the type is a function type
*/
@@ -307,132 +277,66 @@ public:
bool isPredicate() const;
/**
- * Cast this type to a function type
- * @return the FunctionType
- */
- operator FunctionType() const throw(IllegalArgumentException);
-
- /**
* Is this a tuple type?
* @return true if the type is a tuple type
*/
bool isTuple() const;
/**
- * Cast this type to a tuple type
- * @return the TupleType
- */
- operator TupleType() const throw(IllegalArgumentException);
-
- /**
* Is this a record type?
* @return true if the type is a record type
*/
bool isRecord() const;
/**
- * Cast this type to a record type
- * @return the RecordType
- */
- operator RecordType() const throw(IllegalArgumentException);
-
- /**
* Is this a symbolic expression type?
* @return true if the type is a symbolic expression type
*/
bool isSExpr() const;
/**
- * Cast this type to a symbolic expression type
- * @return the SExprType
- */
- operator SExprType() const throw(IllegalArgumentException);
-
- /**
* Is this an array type?
* @return true if the type is a array type
*/
bool isArray() const;
/**
- * Cast this type to an array type
- * @return the ArrayType
- */
- operator ArrayType() const throw(IllegalArgumentException);
-
- /**
* Is this a datatype type?
* @return true if the type is a datatype type
*/
bool isDatatype() const;
/**
- * Cast this type to a datatype type
- * @return the DatatypeType
- */
- operator DatatypeType() const throw(IllegalArgumentException);
-
- /**
* Is this a constructor type?
* @return true if the type is a constructor type
*/
bool isConstructor() const;
/**
- * Cast this type to a constructor type
- * @return the ConstructorType
- */
- operator ConstructorType() const throw(IllegalArgumentException);
-
- /**
* Is this a selector type?
* @return true if the type is a selector type
*/
bool isSelector() const;
/**
- * Cast this type to a selector type
- * @return the SelectorType
- */
- operator SelectorType() const throw(IllegalArgumentException);
-
- /**
* Is this a tester type?
* @return true if the type is a tester type
*/
bool isTester() const;
/**
- * Cast this type to a tester type
- * @return the TesterType
- */
- operator TesterType() const throw(IllegalArgumentException);
-
- /**
* Is this a sort kind?
* @return true if this is a sort kind
*/
bool isSort() const;
/**
- * Cast this type to a sort type
- * @return the sort type
- */
- operator SortType() const throw(IllegalArgumentException);
-
- /**
* Is this a sort constructor kind?
* @return true if this is a sort constructor kind
*/
bool isSortConstructor() const;
/**
- * Cast this type to a sort constructor type
- * @return the sort constructor type
- */
- operator SortConstructorType() const throw(IllegalArgumentException);
-
- /**
* Is this a predicate subtype?
* @return true if this is a predicate subtype
*/
@@ -440,25 +344,12 @@ public:
//bool isPredicateSubtype() const;
/**
- * Cast this type to a predicate subtype
- * @return the predicate subtype
- */
- // not in release 1.0
- //operator PredicateSubtype() const throw(IllegalArgumentException);
-
- /**
* Is this an integer subrange type?
* @return true if this is an integer subrange type
*/
bool isSubrange() const;
/**
- * Cast this type to an integer subrange type
- * @return the integer subrange type
- */
- operator SubrangeType() const throw(IllegalArgumentException);
-
- /**
* Outputs a string representation of this type to the stream.
* @param out the stream to output to
*/
diff --git a/src/expr/type.i b/src/expr/type.i
index 870cb228c..e227cca23 100644
--- a/src/expr/type.i
+++ b/src/expr/type.i
@@ -14,24 +14,6 @@
%rename(greater) CVC4::Type::operator>(const Type&) const;
%rename(greaterEqual) CVC4::Type::operator>=(const Type&) const;
-%rename(toBooleanType) CVC4::Type::operator BooleanType() const;
-%rename(toIntegerType) CVC4::Type::operator IntegerType() const;
-%rename(toRealType) CVC4::Type::operator RealType() const;
-%rename(toStringType) CVC4::Type::operator StringType() const;
-%rename(toBitVectorType) CVC4::Type::operator BitVectorType() const;
-%rename(toFunctionType) CVC4::Type::operator FunctionType() const;
-%rename(toTupleType) CVC4::Type::operator TupleType() const;
-%rename(toSExprType) CVC4::Type::operator SExprType() const;
-%rename(toArrayType) CVC4::Type::operator ArrayType() const;
-%rename(toDatatypeType) CVC4::Type::operator DatatypeType() const;
-%rename(toConstructorType) CVC4::Type::operator ConstructorType() const;
-%rename(toSelectorType) CVC4::Type::operator SelectorType() const;
-%rename(toTesterType) CVC4::Type::operator TesterType() const;
-%rename(toSortType) CVC4::Type::operator SortType() const;
-%rename(toSortConstructorType) CVC4::Type::operator SortConstructorType() const;
-%rename(toPredicateSubtype) CVC4::Type::operator PredicateSubtype() const;
-%rename(toSubrangeType) CVC4::Type::operator SubrangeType() const;
-
namespace CVC4 {
namespace expr {
%ignore exportTypeInternal;
diff --git a/src/include/cvc4_public.h b/src/include/cvc4_public.h
index 6c546a147..9993e5f18 100644
--- a/src/include/cvc4_public.h
+++ b/src/include/cvc4_public.h
@@ -22,19 +22,7 @@
#include <stdint.h>
#if defined _WIN32 || defined __CYGWIN__
-# ifdef BUILDING_DLL
-# ifdef __GNUC__
-# define CVC4_PUBLIC __attribute__((__dllexport__))
-# else /* ! __GNUC__ */
-# define CVC4_PUBLIC __declspec(dllexport)
-# endif /* __GNUC__ */
-# else /* BUILDING_DLL */
-# ifdef __GNUC__
-# define CVC4_PUBLIC __attribute__((__dllimport__))
-# else /* ! __GNUC__ */
-# define CVC4_PUBLIC __declspec(dllimport)
-# endif /* __GNUC__ */
-# endif /* BUILDING_DLL */
+# define CVC4_PUBLIC
#else /* !( defined _WIN32 || defined __CYGWIN__ ) */
# if __GNUC__ >= 4
# define CVC4_PUBLIC __attribute__ ((__visibility__("default")))
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index a6ea59e95..61f9e2d70 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -15,5 +15,8 @@ libreplacements_la_LIBADD = \
EXTRA_DIST = \
replacements.h \
clock_gettime.c \
- clock_gettime.h
-
+ clock_gettime.h \
+ strtok_r.c \
+ strtok_r.h \
+ ffs.c \
+ ffs.h
diff --git a/src/lib/clock_gettime.c b/src/lib/clock_gettime.c
index 77409c71a..054a8c112 100644
--- a/src/lib/clock_gettime.c
+++ b/src/lib/clock_gettime.c
@@ -18,25 +18,25 @@
#include "cvc4_private.h"
-#include <stdio.h>
-#include <errno.h>
-#include <time.h>
-
#include "lib/clock_gettime.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-#ifndef __APPLE__
-# warning This code assumes you're on Mac OS X, and you don't seem to be. You'll likely have problems.
-#endif /* __APPLE__ */
+#if !(defined(__APPLE__) || defined(__WIN32__))
+# warning "This code assumes you're on Mac OS X or Win32, and you don't seem to be. You'll likely have problems."
+#endif /* !(__APPLE__ || __WIN32__) */
+#ifdef __APPLE__
+
+#include <stdio.h>
+#include <errno.h>
#include <mach/mach_time.h>
static double s_clockconv = 0.0;
-long clock_gettime(clockid_t which_clock, struct timespec *tp) {
+long clock_gettime(clockid_t which_clock, struct timespec* tp) {
if( s_clockconv == 0.0 ) {
mach_timebase_info_data_t tb;
kern_return_t err = mach_timebase_info(&tb);
@@ -64,6 +64,24 @@ long clock_gettime(clockid_t which_clock, struct timespec *tp) {
return 0;
}
+#else /* else we're __WIN32__ */
+
+#include <time.h>
+#include <windows.h>
+
+long clock_gettime(clockid_t which_clock, struct timespec* tp) {
+ if(tp != NULL) {
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ uint64_t nanos = ((((uint64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime) * 100;
+ tp->tv_sec = nanos / 1000000000ul;
+ tp->tv_nsec = nanos % 1000000000ul;
+ }
+ return 0;
+}
+
+#endif /* __APPLE__ / __WIN32__ */
+
#ifdef __cplusplus
}/* extern "C" */
#endif /* __cplusplus */
diff --git a/src/lib/clock_gettime.h b/src/lib/clock_gettime.h
index ac4ca1f85..6a8dd57ff 100644
--- a/src/lib/clock_gettime.h
+++ b/src/lib/clock_gettime.h
@@ -30,13 +30,34 @@
/* otherwise, we have to define it */
+#ifdef __WIN32__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+struct timespec {
+ uint64_t tv_sec;
+ int32_t tv_nsec;
+};/* struct timespec */
+
+#ifdef __cplusplus
+}/* extern "C" */
+#endif /* __cplusplus */
+
+#else /* ! __WIN32__ */
+
/* get timespec from <time.h> */
#include <time.h>
+#endif /* __WIN32__ */
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
+struct timespec;
+
typedef enum {
CLOCK_REALTIME,
CLOCK_MONOTONIC,
@@ -44,7 +65,7 @@ typedef enum {
CLOCK_MONOTONIC_HR
} clockid_t;
-long clock_gettime(clockid_t which_clock, struct timespec *tp);
+long clock_gettime(clockid_t which_clock, struct timespec* tp);
#ifdef __cplusplus
}/* extern "C" */
@@ -52,4 +73,3 @@ long clock_gettime(clockid_t which_clock, struct timespec *tp);
#endif /* HAVE_CLOCK_GETTIME */
#endif /*__CVC4__LIB__CLOCK_GETTIME_H */
-
diff --git a/src/lib/ffs.c b/src/lib/ffs.c
new file mode 100644
index 000000000..5c25211ce
--- /dev/null
+++ b/src/lib/ffs.c
@@ -0,0 +1,40 @@
+/********************* */
+/*! \file ffs.c
+ ** \verbatim
+ ** Original author: mdeters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Replacement for ffs() for systems without it (like Win32)
+ **
+ ** Replacement for ffs() for systems without it (like Win32).
+ **/
+
+#include "cvc4_private.h"
+
+#include "lib/ffs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int ffs(int i) {
+ long mask = 0x1;
+ int pos = 1;
+ while(pos <= sizeof(int) * 8) {
+ if((mask & i) != 0) {
+ return pos;
+ }
+ ++pos;
+ mask <<= 1;
+ }
+ return 0;
+}
+
+#ifdef __cplusplus
+}/* extern "C" */
+#endif /* __cplusplus */
diff --git a/src/lib/ffs.h b/src/lib/ffs.h
new file mode 100644
index 000000000..9b038d429
--- /dev/null
+++ b/src/lib/ffs.h
@@ -0,0 +1,42 @@
+/********************* */
+/*! \file ffs.h
+ ** \verbatim
+ ** Original author: mdeters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Replacement for ffs() for systems without it (like Win32)
+ **
+ ** Replacement for ffs() for systems without it (like Win32).
+ **/
+
+#include "cvc4_public.h"
+
+#ifndef __CVC4__LIB__FFS_H
+#define __CVC4__LIB__FFS_H
+
+#ifdef HAVE_FFS
+
+// available in strings.h
+#include <strings.h>
+
+#else /* ! HAVE_FFS */
+
+#include "lib/replacements.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int ffs(int i);
+
+#ifdef __cplusplus
+}/* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* HAVE_FFS */
+#endif /* __CVC4__LIB__FFS_H */
diff --git a/src/lib/strtok_r.c b/src/lib/strtok_r.c
new file mode 100644
index 000000000..b8df95359
--- /dev/null
+++ b/src/lib/strtok_r.c
@@ -0,0 +1,41 @@
+/********************* */
+/*! \file strtok_r.c
+ ** \verbatim
+ ** Original author: mdeters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Replacement for strtok_r() for systems without it (like Win32)
+ **
+ ** Replacement for strtok_r() for systems without it (like Win32).
+ **/
+
+#include "cvc4_private.h"
+
+#include "lib/strtok_r.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+char* strtok_r(char *str, const char *delim, char **saveptr) {
+ if(str == NULL) {
+ char* retval = strtok(*saveptr, delim);
+ *saveptr = retval + strlen(retval) + 1;
+ return retval;
+ } else {
+ char* retval = strtok(str, delim);
+ *saveptr = retval + strlen(retval) + 1;
+ return retval;
+ }
+}
+
+#ifdef __cplusplus
+}/* extern "C" */
+#endif /* __cplusplus */
diff --git a/src/lib/strtok_r.h b/src/lib/strtok_r.h
new file mode 100644
index 000000000..6b3387e6b
--- /dev/null
+++ b/src/lib/strtok_r.h
@@ -0,0 +1,42 @@
+/********************* */
+/*! \file strtok_r.h
+ ** \verbatim
+ ** Original author: mdeters
+ ** Major contributors: none
+ ** Minor contributors (to current version): none
+ ** This file is part of CVC4.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** \brief Replacement for strtok_r() for systems without it (like Win32)
+ **
+ ** Replacement for strtok_r() for systems without it (like Win32).
+ **/
+
+#include "cvc4_public.h"
+
+#ifndef __CVC4__LIB__STRTOK_R_H
+#define __CVC4__LIB__STRTOK_R_H
+
+#ifdef HAVE_STRTOK_R
+
+// available in string.h
+#include <string.h>
+
+#else /* ! HAVE_STRTOK_R */
+
+#include "lib/replacements.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+char* strtok_r(char *str, const char *delim, char **saveptr);
+
+#ifdef __cplusplus
+}/* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* HAVE_STRTOK_R */
+#endif /* __CVC4__LIB__STRTOK_R_H */
diff --git a/src/main/Makefile.am b/src/main/Makefile.am
index 952951655..64a43eb02 100644
--- a/src/main/Makefile.am
+++ b/src/main/Makefile.am
@@ -41,9 +41,9 @@ pcvc4_LDADD += $(BOOST_THREAD_LIBS) -lpthread
pcvc4_LDADD += $(BOOST_THREAD_LDFLAGS)
if STATIC_BINARY
-pcvc4_LINK = $(CXXLINK) -all-static
+pcvc4_LINK = $(CXXLINK) -all-static $(pcvc4_LDFLAGS)
else
-pcvc4_LINK = $(CXXLINK)
+pcvc4_LINK = $(CXXLINK) $(pcvc4_LDFLAGS)
endif
endif
@@ -87,8 +87,8 @@ clean-local:
rm -f $(BUILT_SOURCES)
if STATIC_BINARY
-cvc4_LINK = $(CXXLINK) -all-static
+cvc4_LINK = $(CXXLINK) -all-static $(cvc4_LDFLAGS)
else
-cvc4_LINK = $(CXXLINK)
+cvc4_LINK = $(CXXLINK) $(cvc4_LDFLAGS)
endif
diff --git a/src/main/command_executor.cpp b/src/main/command_executor.cpp
index 14625f1d8..010d4a6f4 100644
--- a/src/main/command_executor.cpp
+++ b/src/main/command_executor.cpp
@@ -48,7 +48,7 @@ bool CommandExecutor::doCommand(Command* cmd)
return status;
} else {
- if(d_options[options::verbosity] > 0) {
+ if(d_options[options::verbosity] > 2) {
*d_options[options::out] << "Invoking: " << *cmd << std::endl;
}
diff --git a/src/main/util.cpp b/src/main/util.cpp
index d4d3e96d8..a6fcddf3b 100644
--- a/src/main/util.cpp
+++ b/src/main/util.cpp
@@ -19,10 +19,15 @@
#include <cerrno>
#include <exception>
#include <string.h>
+
+#ifndef __WIN32__
+
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>
+#endif /* __WIN32__ */
+
#include "util/exception.h"
#include "options/options.h"
#include "util/statistics.h"
@@ -44,9 +49,6 @@ namespace CVC4 {
namespace main {
-size_t cvc4StackSize;
-void* cvc4StackBase;
-
/**
* If true, will not spin on segfault even when CVC4_DEBUG is on.
* Useful for nightly regressions, noninteractive performance runs
@@ -54,6 +56,11 @@ void* cvc4StackBase;
*/
bool segvNoSpin = false;
+#ifndef __WIN32__
+
+size_t cvc4StackSize;
+void* cvc4StackBase;
+
/** Handler for SIGXCPU, i.e., timeout. */
void timeout_handler(int sig, siginfo_t* info, void*) {
fprintf(stderr, "CVC4 interrupted by timeout.\n");
@@ -150,10 +157,12 @@ void ill_handler(int sig, siginfo_t* info, void*) {
#endif /* CVC4_DEBUG */
}
+#endif /* __WIN32__ */
+
static terminate_handler default_terminator;
void cvc4unexpected() {
-#ifdef CVC4_DEBUG
+#if defined(CVC4_DEBUG) && !defined(__WIN32__)
fprintf(stderr, "\n"
"CVC4 threw an \"unexpected\" exception (one that wasn't properly "
"specified\nin the throws() specifier for the throwing function)."
@@ -214,6 +223,7 @@ void cvc4terminate() {
/** Initialize the driver. Sets signal handlers for SIGINT and SIGSEGV. */
void cvc4_init() throw(Exception) {
+#ifndef __WIN32__
stack_t ss;
ss.ss_sp = malloc(SIGSTKSZ);
if(ss.ss_sp == NULL) {
@@ -272,6 +282,8 @@ void cvc4_init() throw(Exception) {
throw Exception(string("sigaction(SIGILL) failure: ") + strerror(errno));
}
+#endif /* __WIN32__ */
+
set_unexpected(cvc4unexpected);
default_terminator = set_terminate(cvc4terminate);
}
diff --git a/src/options/options.h b/src/options/options.h
index 2d49765f3..5f17f5a5c 100644
--- a/src/options/options.h
+++ b/src/options/options.h
@@ -31,7 +31,7 @@
namespace CVC4 {
namespace options {
- class OptionsHolder;
+ struct OptionsHolder;
}/* CVC4::options namespace */
class ExprStream;
diff --git a/src/parser/antlr_input.cpp b/src/parser/antlr_input.cpp
index 8987a7572..fbf2b8650 100644
--- a/src/parser/antlr_input.cpp
+++ b/src/parser/antlr_input.cpp
@@ -63,8 +63,13 @@ AntlrInputStream*
AntlrInputStream::newFileInputStream(const std::string& name,
bool useMmap)
throw (InputStreamException) {
+#ifdef _WIN32
+ if(useMmap) {
+ useMmap = false;
+ }
+#endif
pANTLR3_INPUT_STREAM input = NULL;
- if( useMmap ) {
+ if(useMmap) {
input = MemoryMappedInputBufferNew(name);
} else {
// libantlr3c v3.2 isn't source-compatible with v3.4
@@ -74,7 +79,7 @@ AntlrInputStream::newFileInputStream(const std::string& name,
input = antlr3FileStreamNew((pANTLR3_UINT8) name.c_str(), ANTLR3_ENC_8BIT);
#endif /* CVC4_ANTLR3_OLD_INPUT_STREAM */
}
- if( input == NULL ) {
+ if(input == NULL) {
throw InputStreamException("Couldn't open file: " + name);
}
return new AntlrInputStream( name, input );
diff --git a/src/parser/memory_mapped_input_buffer.cpp b/src/parser/memory_mapped_input_buffer.cpp
index 9f72ac51c..f110b1145 100644
--- a/src/parser/memory_mapped_input_buffer.cpp
+++ b/src/parser/memory_mapped_input_buffer.cpp
@@ -18,10 +18,15 @@
#include <stdio.h>
#include <stdint.h>
+#include <antlr3input.h>
+
+#ifndef _WIN32
+
#include <cerrno>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <antlr3input.h>
+
+#endif /* _WIN32 */
#include "parser/memory_mapped_input_buffer.h"
#include "util/exception.h"
@@ -31,6 +36,14 @@ namespace parser {
extern "C" {
+#ifdef _WIN32
+
+pANTLR3_INPUT_STREAM MemoryMappedInputBufferNew(const std::string& filename) {
+ return 0;
+}
+
+#else /* ! _WIN32 */
+
static ANTLR3_UINT32
MemoryMapFile(pANTLR3_INPUT_STREAM input, const std::string& filename);
@@ -112,6 +125,8 @@ void UnmapFile(pANTLR3_INPUT_STREAM input) {
input->close(input);
}
+#endif /* _WIN32 */
+
}/* extern "C" */
}/* CVC4::parser namespace */
diff --git a/src/parser/smt1/Smt1.g b/src/parser/smt1/Smt1.g
index 6dade9530..e3c36cf91 100644
--- a/src/parser/smt1/Smt1.g
+++ b/src/parser/smt1/Smt1.g
@@ -1,4 +1,3 @@
-/* ******************* */
/*! \file Smt1.g
** \verbatim
** Original author: cconway
@@ -235,10 +234,10 @@ annotatedFormula[CVC4::Expr& expr]
Expr op; /* Operator expression FIXME: move away kill it */
}
: /* a built-in operator application */
- LPAREN_TOK builtinOp[kind] annotatedFormulas[args,expr] RPAREN_TOK
+ LPAREN_TOK builtinOp[kind] annotatedFormulas[args,expr]
{ if((kind == CVC4::kind::AND || kind == CVC4::kind::OR) && args.size() == 1) {
/* Unary AND/OR can be replaced with the argument.
- It just so happens expr should already by the only argument. */
+ * It just so happens expr should already be the only argument. */
assert( expr == args[0] );
} else if( CVC4::kind::isAssociative(kind) &&
args.size() > EXPR_MANAGER->maxArity(kind) ) {
@@ -253,6 +252,7 @@ annotatedFormula[CVC4::Expr& expr]
expr = MK_EXPR(kind, args);
}
}
+ termAnnotation[expr]* RPAREN_TOK
| /* A quantifier */
LPAREN_TOK
@@ -261,12 +261,13 @@ annotatedFormula[CVC4::Expr& expr]
( LPAREN_TOK let_identifier[name,CHECK_NONE] t=sortSymbol RPAREN_TOK
{ args.push_back(PARSER_STATE->mkBoundVar(name, t)); }
)+
- annotatedFormula[expr] RPAREN_TOK
+ annotatedFormula[expr]
{ args2.push_back( MK_EXPR( kind::BOUND_VAR_LIST, args ) );
args2.push_back(expr);
expr = MK_EXPR(kind, args2);
- PARSER_STATE->popScope();
}
+ termAnnotation[expr]* RPAREN_TOK
+ { PARSER_STATE->popScope(); }
| /* A non-built-in function application */
@@ -275,9 +276,10 @@ annotatedFormula[CVC4::Expr& expr]
// { isFunction(LT(2)->getText()) }?
LPAREN_TOK
parameterizedOperator[op]
- annotatedFormulas[args,expr] RPAREN_TOK
+ annotatedFormulas[args,expr]
// TODO: check arity
{ expr = MK_EXPR(op,args); }
+ termAnnotation[expr]* RPAREN_TOK
| /* An ite expression */
LPAREN_TOK ITE_TOK
@@ -286,9 +288,9 @@ annotatedFormula[CVC4::Expr& expr]
annotatedFormula[expr]
{ args.push_back(expr); }
annotatedFormula[expr]
- { args.push_back(expr); }
- RPAREN_TOK
- { expr = MK_EXPR(CVC4::kind::ITE, args); }
+ { args.push_back(expr);
+ expr = MK_EXPR(CVC4::kind::ITE, args); }
+ termAnnotation[expr]* RPAREN_TOK
| /* a let/flet binding */
LPAREN_TOK
@@ -298,7 +300,7 @@ annotatedFormula[CVC4::Expr& expr]
{ PARSER_STATE->pushScope();
PARSER_STATE->defineVar(name,expr); }
annotatedFormula[expr]
- RPAREN_TOK
+ termAnnotation[expr]* RPAREN_TOK
{ PARSER_STATE->popScope(); }
/* constants */
@@ -310,7 +312,7 @@ annotatedFormula[CVC4::Expr& expr]
{ // FIXME: This doesn't work because an SMT rational is not a
// valid GMP rational string
expr = MK_CONST( AntlrInput::tokenToRational($RATIONAL_TOK) ); }
- | n = BITVECTOR_BV_CONST '[' size = NUMERAL_TOK ']'
+ | n = BITVECTOR_BV_CONST '[' size = NUMERAL_TOK ']'
{ expr = MK_CONST( AntlrInput::tokenToBitvector($n, $size) ); }
// NOTE: Theory constants go here
/* TODO: quantifiers, arithmetic constants */
@@ -320,7 +322,6 @@ annotatedFormula[CVC4::Expr& expr]
| let_identifier[name,CHECK_DECLARED]
| flet_identifier[name,CHECK_DECLARED] )
{ expr = PARSER_STATE->getVariable(name); }
-
;
/**
@@ -458,7 +459,7 @@ functionSymbol[CVC4::Expr& fun]
* Matches an attribute name from the input (:attribute_name).
*/
attribute[std::string& s]
- : ATTR_IDENTIFIER
+ : ATTR_IDENTIFIER
{ s = AntlrInput::tokenText($ATTR_IDENTIFIER); }
;
@@ -555,28 +556,56 @@ status[ CVC4::BenchmarkStatus& status ]
/**
* Matches an annotation, which is an attribute name, with an optional user
+ * value.
*/
annotation[CVC4::Command*& smt_command]
@init {
- std::string key;
+ std::string key, value;
smt_command = NULL;
+ std::vector<Expr> pats;
+ Expr pat;
+}
+ : PATTERN_ANNOTATION_BEGIN
+ { PARSER_STATE->warning(":pat not supported here; ignored"); }
+ annotatedFormulas[pats,pat] '}'
+ | attribute[key]
+ ( userValue[value]
+ { smt_command = new SetInfoCommand(key.c_str() + 1, value); }
+ | { smt_command = new EmptyCommand(std::string("annotation: ") + key); }
+ )
+ ;
+
+/**
+ * Matches an annotation, which is an attribute name, with an optional user
+ * value.
+ */
+termAnnotation[CVC4::Expr& expr]
+@init {
+ std::string key, value;
+ std::vector<Expr> pats;
+ Expr pat;
}
- : attribute[key]
- ( USER_VALUE
- { std::string value = AntlrInput::tokenText($USER_VALUE);
- assert(*value.begin() == '{');
- assert(*value.rbegin() == '}');
- // trim whitespace
- value.erase(value.begin(), value.begin() + 1);
- value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
- value.erase(value.end() - 1);
- value.erase(std::find_if(value.rbegin(), value.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), value.end());
- smt_command = new SetInfoCommand(key.c_str() + 1, value); }
- )?
- { if(smt_command == NULL) {
- smt_command = new EmptyCommand(std::string("annotation: ") + key);
+ : PATTERN_ANNOTATION_BEGIN annotatedFormulas[pats,pat] '}'
+ { if(expr.getKind() == kind::FORALL || expr.getKind() == kind::EXISTS) {
+ pat = MK_EXPR(kind::INST_PATTERN, pats);
+ if(expr.getNumChildren() == 3) {
+ // we have other user patterns attached to the quantifier
+ // already; add this one to the existing list
+ pats = expr[2].getChildren();
+ pats.push_back(pat);
+ expr = MK_EXPR(expr.getKind(), expr[0], expr[1], MK_EXPR(kind::INST_PATTERN_LIST, pats));
+ } else {
+ // this is the only user pattern for the quantifier
+ expr = MK_EXPR(expr.getKind(), expr[0], expr[1], MK_EXPR(kind::INST_PATTERN_LIST, pat));
+ }
+ } else {
+ PARSER_STATE->warning(":pat only supported on quantifiers");
}
}
+ | ':pat'
+ { PARSER_STATE->warning("expected an instantiation pattern after :pat"); }
+ | attribute[key] userValue[value]?
+ { PARSER_STATE->attributeNotSupported(key); }
;
/**
@@ -752,6 +781,23 @@ FLET_IDENTIFIER
* only constraint imposed on a user-defined value is that it start
* with an open brace and end with closed brace.
*/
+userValue[std::string& s]
+ : USER_VALUE
+ { s = AntlrInput::tokenText($USER_VALUE);
+ assert(*s.begin() == '{');
+ assert(*s.rbegin() == '}');
+ // trim whitespace
+ s.erase(s.begin(), s.begin() + 1);
+ s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
+ s.erase(s.end() - 1);
+ s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
+ }
+ ;
+
+PATTERN_ANNOTATION_BEGIN
+ : ':pat' (' ' | '\t' | '\f' | '\r' | '\n')* '{'
+ ;
+
USER_VALUE
: '{' ('\\{' | '\\}' | ~('{' | '}'))* '}'
;
diff --git a/src/printer/smt2/smt2_printer.cpp b/src/printer/smt2/smt2_printer.cpp
index 5821fbc77..000fd2fbf 100644
--- a/src/printer/smt2/smt2_printer.cpp
+++ b/src/printer/smt2/smt2_printer.cpp
@@ -541,6 +541,13 @@ void Smt2Printer::toStream(std::ostream& out, const CommandStatus* s) const thro
}/* Smt2Printer::toStream(CommandStatus*) */
+void Smt2Printer::toStream(std::ostream& out, Model& m) const throw() {
+ out << "(model" << std::endl;
+ this->Printer::toStream(out, m);
+ out << ")" << std::endl;
+}
+
+
void Smt2Printer::toStream(std::ostream& out, Model& m, const Command* c) const throw() {
theory::TheoryModel& tm = (theory::TheoryModel&) m;
if(dynamic_cast<const DeclareTypeCommand*>(c) != NULL) {
diff --git a/src/printer/smt2/smt2_printer.h b/src/printer/smt2/smt2_printer.h
index c6d932457..32a0c94ba 100644
--- a/src/printer/smt2/smt2_printer.h
+++ b/src/printer/smt2/smt2_printer.h
@@ -30,6 +30,7 @@ namespace smt2 {
class Smt2Printer : public CVC4::Printer {
void toStream(std::ostream& out, TNode n, int toDepth, bool types) const throw();
void toStream(std::ostream& out, Model& m, const Command* c) const throw();
+ void toStream(std::ostream& out, Model& m) const throw();
public:
void toStream(std::ostream& out, TNode n, int toDepth, bool types, size_t dag) const throw();
void toStream(std::ostream& out, const Command* c, int toDepth, bool types, size_t dag) const throw();
diff --git a/src/proof/proof_manager.cpp b/src/proof/proof_manager.cpp
index d05fe24a7..c1351c6a2 100644
--- a/src/proof/proof_manager.cpp
+++ b/src/proof/proof_manager.cpp
@@ -26,7 +26,7 @@ namespace CVC4 {
bool ProofManager::isInitialized = false;
ProofManager* ProofManager::proofManager = NULL;
-ProofManager::ProofManager(ProofFormat format = LFSC):
+ProofManager::ProofManager(ProofFormat format):
d_satProof(NULL),
d_cnfProof(NULL),
d_format(format)
diff --git a/src/proof/proof_manager.h b/src/proof/proof_manager.h
index 3bfff1456..91eb2ed99 100644
--- a/src/proof/proof_manager.h
+++ b/src/proof/proof_manager.h
@@ -52,7 +52,7 @@ class ProofManager {
static ProofManager* proofManager;
static bool isInitialized;
- ProofManager(ProofFormat format);
+ ProofManager(ProofFormat format = LFSC);
public:
static ProofManager* currentPM();
diff --git a/src/prop/bvminisat/core/Solver.cc b/src/prop/bvminisat/core/Solver.cc
index 978ac8d7b..68969c78b 100644
--- a/src/prop/bvminisat/core/Solver.cc
+++ b/src/prop/bvminisat/core/Solver.cc
@@ -32,7 +32,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
#include "theory/interrupted.h"
using namespace BVMinisat;
-namespace CVC4 {
+namespace BVMinisat {
#define OUTPUT_TAG "bvminisat: [a=" << assumptions.size() << ",l=" << decisionLevel() << "] "
diff --git a/src/prop/cnf_stream.cpp b/src/prop/cnf_stream.cpp
index 9f2138e9d..89cd731e9 100644
--- a/src/prop/cnf_stream.cpp
+++ b/src/prop/cnf_stream.cpp
@@ -108,11 +108,10 @@ void TseitinCnfStream::ensureLiteral(TNode n) {
Debug("cnf") << "ensureLiteral(" << n << ")" << endl;
if(hasLiteral(n)) {
SatLiteral lit = getLiteral(n);
- LiteralToNodeMap::iterator i = d_literalToNodeMap.find(lit);
- if(i == d_literalToNodeMap.end()) {
+ if(!d_literalToNodeMap.contains(lit)){
// Store backward-mappings
- d_literalToNodeMap[lit] = n;
- d_literalToNodeMap[~lit] = n.notNode();
+ d_literalToNodeMap.insert(lit, n);
+ d_literalToNodeMap.insert(~lit, n.notNode());
}
return;
}
@@ -140,8 +139,9 @@ void TseitinCnfStream::ensureLiteral(TNode n) {
lit = toCNF(n, false);
// Store backward-mappings
- d_literalToNodeMap[lit] = n;
- d_literalToNodeMap[~lit] = n.notNode();
+ // These may already exist
+ d_literalToNodeMap.insert_safe(lit, n);
+ d_literalToNodeMap.insert_safe(~lit, n.notNode());
} else {
// We have a theory atom or variable.
lit = convertAtom(n);
@@ -168,8 +168,8 @@ SatLiteral CnfStream::newLiteral(TNode node, bool theoryLiteral) {
} else {
lit = SatLiteral(d_satSolver->newVar(theoryLiteral));
}
- d_nodeToLiteralMap[node] = lit;
- d_nodeToLiteralMap[node.notNode()] = ~lit;
+ d_nodeToLiteralMap.insert(node, lit);
+ d_nodeToLiteralMap.insert(node.notNode(), ~lit);
} else {
lit = getLiteral(node);
}
@@ -178,8 +178,9 @@ SatLiteral CnfStream::newLiteral(TNode node, bool theoryLiteral) {
if ( theoryLiteral || d_fullLitToNodeMap ||
( CVC4_USE_REPLAY && options::replayLog() != NULL ) ||
(Dump.isOn("clauses")) ) {
- d_literalToNodeMap[lit] = node;
- d_literalToNodeMap[~lit] = node.notNode();
+
+ d_literalToNodeMap.insert_safe(lit, node);
+ d_literalToNodeMap.insert_safe(~lit, node.notNode());
}
// If a theory literal, we pre-register it
@@ -197,11 +198,8 @@ SatLiteral CnfStream::newLiteral(TNode node, bool theoryLiteral) {
TNode CnfStream::getNode(const SatLiteral& literal) {
Debug("cnf") << "getNode(" << literal << ")" << endl;
- LiteralToNodeMap::iterator find = d_literalToNodeMap.find(literal);
- Assert(find != d_literalToNodeMap.end());
- Assert(d_nodeToLiteralMap.find((*find).second) != d_nodeToLiteralMap.end());
- Debug("cnf") << "getNode(" << literal << ") => " << (*find).second << endl;
- return (*find).second;
+ Debug("cnf") << "getNode(" << literal << ") => " << d_literalToNodeMap[literal] << endl;
+ return d_literalToNodeMap[literal];
}
void CnfStream::getBooleanVariables(std::vector<TNode>& outputVariables) const {
@@ -229,10 +227,9 @@ SatLiteral CnfStream::convertAtom(TNode node) {
}
SatLiteral CnfStream::getLiteral(TNode node) {
- NodeToLiteralMap::iterator find = d_nodeToLiteralMap.find(node);
Assert(!node.isNull(), "CnfStream: can't getLiteral() of null node");
- Assert(find != d_nodeToLiteralMap.end(), "Literal not in the CNF Cache: %s\n", node.toString().c_str());
- SatLiteral literal = (*find).second;
+ Assert(d_nodeToLiteralMap.contains(node), "Literal not in the CNF Cache: %s\n", node.toString().c_str());
+ SatLiteral literal = d_nodeToLiteralMap[node];
Debug("cnf") << "CnfStream::getLiteral(" << node << ") => " << literal << std::endl;
return literal;
}
diff --git a/src/prop/cnf_stream.h b/src/prop/cnf_stream.h
index 6ab639712..042cccd56 100644
--- a/src/prop/cnf_stream.h
+++ b/src/prop/cnf_stream.h
@@ -29,6 +29,7 @@
#include "prop/theory_proxy.h"
#include "prop/registrar.h"
#include "context/cdlist.h"
+#include "context/cdinsert_hashmap.h"
#include <ext/hash_map>
@@ -47,10 +48,10 @@ class CnfStream {
public:
/** Cache of what nodes have been registered to a literal. */
- typedef context::CDHashMap<SatLiteral, TNode, SatLiteralHashFunction> LiteralToNodeMap;
+ typedef context::CDInsertHashMap<SatLiteral, TNode, SatLiteralHashFunction> LiteralToNodeMap;
/** Cache of what literals have been registered to a node. */
- typedef context::CDHashMap<Node, SatLiteral, NodeHashFunction> NodeToLiteralMap;
+ typedef context::CDInsertHashMap<Node, SatLiteral, NodeHashFunction> NodeToLiteralMap;
protected:
diff --git a/src/prop/sat_solver.h b/src/prop/sat_solver.h
index e5d876b48..b4807b021 100644
--- a/src/prop/sat_solver.h
+++ b/src/prop/sat_solver.h
@@ -130,8 +130,6 @@ public:
};/* class DPLLSatSolverInterface */
-}/* CVC4::prop namespace */
-
inline std::ostream& operator <<(std::ostream& out, prop::SatLiteral lit) {
out << lit.toString();
return out;
@@ -167,6 +165,7 @@ inline std::ostream& operator <<(std::ostream& out, prop::SatValue val) {
return out;
}
+}/* CVC4::prop namespace */
}/* CVC4 namespace */
#endif /* __CVC4__PROP__SAT_MODULE_H */
diff --git a/src/smt/options_handlers.h b/src/smt/options_handlers.h
index a3065f29b..a0a6429a8 100644
--- a/src/smt/options_handlers.h
+++ b/src/smt/options_handlers.h
@@ -23,6 +23,7 @@
#include "util/dump.h"
#include "smt/modal_exception.h"
#include "smt/smt_engine.h"
+#include "lib/strtok_r.h"
#include <cerrno>
#include <cstring>
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 09fed4f9f..ca65ab1df 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -36,6 +36,7 @@
#include "expr/metakind.h"
#include "expr/node_builder.h"
#include "expr/node.h"
+#include "expr/node_self_iterator.h"
#include "prop/prop_engine.h"
#include "smt/modal_exception.h"
#include "smt/smt_engine.h"
@@ -111,7 +112,11 @@ struct SmtEngineStatistics {
TimerStat d_rewriteBooleanTermsTime;
/** time spent in non-clausal simplification */
TimerStat d_nonclausalSimplificationTime;
- /** Num of constant propagations found during nonclausal simp */
+ /** time spent in miplib pass */
+ TimerStat d_miplibPassTime;
+ /** number of assertions removed by miplib pass */
+ IntStat d_numMiplibAssertionsRemoved;
+ /** number of constant propagations found during nonclausal simp */
IntStat d_numConstantProps;
/** time spent in static learning */
TimerStat d_staticLearningTime;
@@ -136,6 +141,8 @@ struct SmtEngineStatistics {
d_definitionExpansionTime("smt::SmtEngine::definitionExpansionTime"),
d_rewriteBooleanTermsTime("smt::SmtEngine::rewriteBooleanTermsTime"),
d_nonclausalSimplificationTime("smt::SmtEngine::nonclausalSimplificationTime"),
+ d_miplibPassTime("smt::SmtEngine::miplibPassTime"),
+ d_numMiplibAssertionsRemoved("smt::SmtEngine::numMiplibAssertionsRemoved", 0),
d_numConstantProps("smt::SmtEngine::numConstantProps", 0),
d_staticLearningTime("smt::SmtEngine::staticLearningTime"),
d_simpITETime("smt::SmtEngine::simpITETime"),
@@ -150,6 +157,8 @@ struct SmtEngineStatistics {
StatisticsRegistry::registerStat(&d_definitionExpansionTime);
StatisticsRegistry::registerStat(&d_rewriteBooleanTermsTime);
StatisticsRegistry::registerStat(&d_nonclausalSimplificationTime);
+ StatisticsRegistry::registerStat(&d_miplibPassTime);
+ StatisticsRegistry::registerStat(&d_numMiplibAssertionsRemoved);
StatisticsRegistry::registerStat(&d_numConstantProps);
StatisticsRegistry::registerStat(&d_staticLearningTime);
StatisticsRegistry::registerStat(&d_simpITETime);
@@ -166,6 +175,8 @@ struct SmtEngineStatistics {
StatisticsRegistry::unregisterStat(&d_definitionExpansionTime);
StatisticsRegistry::unregisterStat(&d_rewriteBooleanTermsTime);
StatisticsRegistry::unregisterStat(&d_nonclausalSimplificationTime);
+ StatisticsRegistry::unregisterStat(&d_miplibPassTime);
+ StatisticsRegistry::unregisterStat(&d_numMiplibAssertionsRemoved);
StatisticsRegistry::unregisterStat(&d_numConstantProps);
StatisticsRegistry::unregisterStat(&d_staticLearningTime);
StatisticsRegistry::unregisterStat(&d_simpITETime);
@@ -210,6 +221,8 @@ class SmtEnginePrivate : public NodeManagerListener {
/** A circuit propagator for non-clausal propositional deduction */
booleans::CircuitPropagator d_propagator;
+ bool d_propagatorNeedsFinish;
+ std::vector<Node> d_boolVars;
/** Assertions to push to sat */
vector<Node> d_assertionsToCheck;
@@ -333,6 +346,14 @@ private:
void constrainSubtypes(TNode n, std::vector<Node>& assertions)
throw();
+ // trace nodes back to their assertions using CircuitPropagator's BackEdgesMap
+ void traceBackToAssertions(const std::vector<Node>& nodes, std::vector<TNode>& assertions);
+ // remove conjuncts in toRemove from conjunction n; return # of removed conjuncts
+ size_t removeFromConjunction(Node& n, const std::hash_set<unsigned>& toRemove);
+
+ // scrub miplib encodings
+ void doMiplibTrick();
+
/**
* Perform non-clausal simplification of a Node. This involves
* Theory implementations, but does NOT involve the SAT solver in
@@ -351,6 +372,7 @@ public:
d_realAssertionsEnd(0),
d_booleanTermConverter(d_smt),
d_propagator(d_nonClausalLearnedLiterals, true, true),
+ d_propagatorNeedsFinish(false),
d_assertionsToCheck(),
d_fakeContext(),
d_abstractValueMap(&d_fakeContext),
@@ -365,6 +387,13 @@ public:
d_smt.d_nodeManager->subscribeEvents(this);
}
+ ~SmtEnginePrivate() {
+ if(d_propagatorNeedsFinish) {
+ d_propagator.finish();
+ d_propagatorNeedsFinish = false;
+ }
+ }
+
void nmNotifyNewSort(TypeNode tn) {
DeclareTypeCommand c(tn.getAttribute(expr::VarNameAttr()),
0,
@@ -389,6 +418,9 @@ public:
n.toExpr(),
n.getType().toType());
d_smt.addToModelCommandAndDump(c, isGlobal);
+ if(n.getType().isBoolean() && !options::incrementalSolving()) {
+ d_boolVars.push_back(n);
+ }
}
void nmNotifyNewSkolem(TNode n, const std::string& comment, bool isGlobal) {
@@ -400,6 +432,9 @@ public:
Dump("skolems") << CommentCommand(id + " is " + comment);
}
d_smt.addToModelCommandAndDump(c, isGlobal, false, "skolems");
+ if(n.getType().isBoolean() && !options::incrementalSolving()) {
+ d_boolVars.push_back(n);
+ }
}
Node applySubstitutions(TNode node) const {
@@ -1558,6 +1593,10 @@ bool SmtEnginePrivate::nonClausalSimplify() {
Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify()" << endl;
+ if(d_propagatorNeedsFinish) {
+ d_propagator.finish();
+ d_propagatorNeedsFinish = false;
+ }
d_propagator.initialize();
// Assert all the assertions to the propagator
@@ -1577,7 +1616,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
<< "conflict in non-clausal propagation" << endl;
d_assertionsToPreprocess.clear();
d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return false;
}
@@ -1612,7 +1651,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
<< d_nonClausalLearnedLiterals[i] << endl;
d_assertionsToPreprocess.clear();
d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return false;
}
}
@@ -1644,7 +1683,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
<< learnedLiteral << endl;
d_assertionsToPreprocess.clear();
d_assertionsToCheck.push_back(NodeManager::currentNM()->mkConst<bool>(false));
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return false;
default:
if (d_doConstantProp && learnedLiteral.getKind() == kind::EQUAL && (learnedLiteral[0].isConst() || learnedLiteral[1].isConst())) {
@@ -1714,6 +1753,17 @@ bool SmtEnginePrivate::nonClausalSimplify() {
// Resize the learnt
d_nonClausalLearnedLiterals.resize(j);
+ //must add substitutions to model
+ TheoryModel* m = d_smt.d_theoryEngine->getModel();
+ if(m != NULL) {
+ for( SubstitutionMap::iterator pos = d_topLevelSubstitutions.begin(); pos != d_topLevelSubstitutions.end(); ++pos) {
+ Node n = (*pos).first;
+ Node v = (*pos).second;
+ Trace("model") << "Add substitution : " << n << " " << v << std::endl;
+ m->addSubstitution( n, v );
+ }
+ }
+
hash_set<TNode, TNodeHashFunction> s;
for (unsigned i = 0; i < d_assertionsToPreprocess.size(); ++ i) {
Node assertion = d_assertionsToPreprocess[i];
@@ -1812,7 +1862,7 @@ bool SmtEnginePrivate::nonClausalSimplify() {
Rewriter::rewrite(Node(learnedBuilder));
}
- d_propagator.finish();
+ d_propagatorNeedsFinish = true;
return true;
}
@@ -1894,6 +1944,366 @@ void SmtEnginePrivate::constrainSubtypes(TNode top, std::vector<Node>& assertion
} while(! worklist.empty());
}
+void SmtEnginePrivate::traceBackToAssertions(const std::vector<Node>& nodes, std::vector<TNode>& assertions) {
+ const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
+ for(vector<Node>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
+ booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
+ // term must appear in map, otherwise how did we get here?!
+ Assert(j != backEdges.end());
+ // if term maps to empty, that means it's a top-level assertion
+ if(!(*j).second.empty()) {
+ traceBackToAssertions((*j).second, assertions);
+ } else {
+ assertions.push_back(*i);
+ }
+ }
+}
+
+size_t SmtEnginePrivate::removeFromConjunction(Node& n, const std::hash_set<unsigned>& toRemove) {
+ Assert(n.getKind() == kind::AND);
+ Node trueNode = NodeManager::currentNM()->mkConst(true);
+ size_t removals = 0;
+ for(Node::iterator j = n.begin(); j != n.end(); ++j) {
+ size_t subremovals = 0;
+ Node sub = *j;
+ if(toRemove.find(sub.getId()) != toRemove.end() ||
+ (sub.getKind() == kind::AND && (subremovals = removeFromConjunction(sub, toRemove)) > 0)) {
+ NodeBuilder<> b(kind::AND);
+ b.append(n.begin(), j);
+ if(subremovals > 0) {
+ removals += subremovals;
+ b << sub;
+ } else {
+ ++removals;
+ }
+ for(++j; j != n.end(); ++j) {
+ if(toRemove.find((*j).getId()) != toRemove.end()) {
+ ++removals;
+ } else if((*j).getKind() == kind::AND) {
+ sub = *j;
+ if((subremovals = removeFromConjunction(sub, toRemove)) > 0) {
+ removals += subremovals;
+ b << sub;
+ } else {
+ b << *j;
+ }
+ } else {
+ b << *j;
+ }
+ }
+ if(b.getNumChildren() == 0) {
+ n = trueNode;
+ b.clear();
+ } else if(b.getNumChildren() == 1) {
+ n = b[0];
+ b.clear();
+ } else {
+ n = b;
+ }
+ n = Rewriter::rewrite(n);
+ return removals;
+ }
+ }
+
+ Assert(removals == 0);
+ return 0;
+}
+
+void SmtEnginePrivate::doMiplibTrick() {
+ Assert(d_assertionsToPreprocess.empty());
+ Assert(d_realAssertionsEnd == d_assertionsToCheck.size());
+ Assert(!options::incrementalSolving());
+
+ const booleans::CircuitPropagator::BackEdgesMap& backEdges = d_propagator.getBackEdges();
+ hash_set<unsigned> removeAssertions;
+
+ NodeManager* nm = NodeManager::currentNM();
+ Node zero = nm->mkConst(Rational(0)), one = nm->mkConst(Rational(1));
+
+ hash_map<TNode, Node, TNodeHashFunction> intVars;
+ for(vector<Node>::const_iterator i = d_boolVars.begin(); i != d_boolVars.end(); ++i) {
+ if(d_propagator.isAssigned(*i)) {
+ Debug("miplib") << "ineligible: " << *i << " because assigned " << d_propagator.getAssignment(*i) << endl;
+ continue;
+ }
+
+ vector<TNode> assertions;
+ booleans::CircuitPropagator::BackEdgesMap::const_iterator j = backEdges.find(*i);
+ // if not in back edges map, the bool var is unconstrained, showing up in no assertions.
+ // if maps to an empty vector, that means the bool var was asserted itself.
+ if(j != backEdges.end()) {
+ if(!(*j).second.empty()) {
+ traceBackToAssertions((*j).second, assertions);
+ } else {
+ assertions.push_back(*i);
+ }
+ }
+ Debug("miplib") << "for " << *i << endl;
+ bool eligible = true;
+ map<pair<Node, Node>, uint64_t> marks;
+ map<pair<Node, Node>, vector<Rational> > coef;
+ map<pair<Node, Node>, vector<Rational> > checks;
+ map<pair<Node, Node>, vector<TNode> > asserts;
+ for(vector<TNode>::const_iterator j = assertions.begin(); j != assertions.end(); ++j) {
+ Debug("miplib") << " found: " << *j << endl;
+ if((*j).getKind() != kind::IMPLIES) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (not =>)" << endl;
+ break;
+ }
+ Node conj = BooleanSimplification::simplify((*j)[0]);
+ if(conj.getKind() == kind::AND && conj.getNumChildren() > 6) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (N-ary /\\ too big)" << endl;
+ break;
+ }
+ if(conj.getKind() != kind::AND && !conj.isVar() && !(conj.getKind() == kind::NOT && conj[0].isVar())) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (not /\\ or literal)" << endl;
+ break;
+ }
+ if((*j)[1].getKind() != kind::EQUAL ||
+ !( ( (*j)[1][0].isVar() &&
+ (*j)[1][1].getKind() == kind::CONST_RATIONAL ) ||
+ ( (*j)[1][0].getKind() == kind::CONST_RATIONAL &&
+ (*j)[1][1].isVar() ) )) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (=> (and X X) X)" << endl;
+ break;
+ }
+ if(conj.getKind() == kind::AND) {
+ vector<Node> posv;
+ bool found_x = false;
+ map<TNode, bool> neg;
+ for(Node::iterator ii = conj.begin(); ii != conj.end(); ++ii) {
+ if((*ii).isVar()) {
+ posv.push_back(*ii);
+ neg[*ii] = false;
+ found_x = found_x || *i == *ii;
+ } else if((*ii).getKind() == kind::NOT && (*ii)[0].isVar()) {
+ posv.push_back((*ii)[0]);
+ neg[(*ii)[0]] = true;
+ found_x = found_x || *i == (*ii)[0];
+ } else {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (non-var: " << *ii << ")" << endl;
+ break;
+ }
+ if(d_propagator.isAssigned(posv.back())) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (" << posv.back() << " asserted)" << endl;
+ break;
+ }
+ }
+ if(!eligible) {
+ break;
+ }
+ if(!found_x) {
+ eligible = false;
+ Debug("miplib") << " --INELIGIBLE -- (couldn't find " << *i << " in conjunction)" << endl;
+ break;
+ }
+ sort(posv.begin(), posv.end());
+ const Node pos = NodeManager::currentNM()->mkNode(kind::AND, posv);
+ const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
+ const pair<Node, Node> pos_var(pos, var);
+ const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
+ uint64_t mark = 0;
+ unsigned countneg = 0, thepos = 0;
+ for(unsigned ii = 0; ii < pos.getNumChildren(); ++ii) {
+ if(neg[pos[ii]]) {
+ ++countneg;
+ } else {
+ thepos = ii;
+ mark |= (0x1 << ii);
+ }
+ }
+ if((marks[pos_var] & (1lu << mark)) != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
+ break;
+ }
+ Debug("miplib") << "mark is " << mark << " -- " << (1lu << mark) << endl;
+ marks[pos_var] |= (1lu << mark);
+ Debug("miplib") << "marks[" << pos << "," << var << "] now " << marks[pos_var] << endl;
+ if(countneg == pos.getNumChildren()) {
+ if(constant != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
+ break;
+ }
+ } else if(countneg == pos.getNumChildren() - 1) {
+ Assert(coef[pos_var].size() <= 6 && thepos < 6);
+ coef[pos_var].resize(6);
+ coef[pos_var][thepos] = constant;
+ } else {
+ if(checks[pos_var].size() <= mark) {
+ checks[pos_var].resize(mark + 1);
+ }
+ checks[pos_var][mark] = constant;
+ }
+ asserts[pos_var].push_back(*j);
+ } else {
+ TNode x = conj;
+ if(x != *i && x != (*i).notNode()) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (x not present where I expect it)" << endl;
+ break;
+ }
+ const bool xneg = (x.getKind() == kind::NOT);
+ x = xneg ? x[0] : x;
+ Debug("miplib") << " x:" << x << " " << xneg << endl;
+ const TNode var = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][1] : (*j)[1][0];
+ const pair<Node, Node> x_var(x, var);
+ const Rational& constant = ((*j)[1][0].getKind() == kind::CONST_RATIONAL) ? (*j)[1][0].getConst<Rational>() : (*j)[1][1].getConst<Rational>();
+ unsigned mark = (xneg ? 0 : 1);
+ if((marks[x_var] & (1u << mark)) != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (remarked)" << endl;
+ break;
+ }
+ marks[x_var] |= (1u << mark);
+ if(xneg) {
+ if(constant != 0) {
+ eligible = false;
+ Debug("miplib") << " -- INELIGIBLE -- (nonzero constant)" << endl;
+ break;
+ }
+ } else {
+ Assert(coef[x_var].size() <= 6);
+ coef[x_var].resize(6);
+ coef[x_var][0] = constant;
+ if(checks[x_var].size() <= mark) {
+ checks[x_var].resize(mark + 1);
+ }
+ checks[x_var][mark] = constant;
+ }
+ asserts[x_var].push_back(*j);
+ }
+ }
+ if(eligible) {
+ for(map<pair<Node, Node>, uint64_t>::const_iterator j = marks.begin(); j != marks.end(); ++j) {
+ const TNode pos = (*j).first.first;
+ const TNode var = (*j).first.second;
+ const pair<Node, Node>& pos_var = (*j).first;
+ const uint64_t mark = (*j).second;
+ const unsigned numVars = pos.getKind() == kind::AND ? pos.getNumChildren() : 1;
+ uint64_t expected = (uint64_t(1) << (1 << numVars)) - 1;
+ expected = (expected == 0) ? -1 : expected;// fix for overflow
+ Debug("miplib") << "[" << pos << "] => " << hex << mark << " expect " << expected << dec << endl;
+ Assert(pos.getKind() == kind::AND || pos.isVar());
+ if(mark != expected) {
+ Debug("miplib") << " -- INELIGIBLE " << pos << " -- (insufficiently marked, got " << mark << " for " << numVars << " vars, expected " << expected << endl;
+ } else {
+ if(false) { //checks[pos] != coef[pos][0] + coef[pos][1]) {
+ Debug("miplib") << " -- INELIGIBLE " << pos << " -- (not linear combination)" << endl;
+ } else {
+ Debug("miplib") << " -- ELIGIBLE " << *i << " , " << pos << " --" << endl;
+ vector<Node> newVars;
+ expr::NodeSelfIterator ii, iiend;
+ if(pos.getKind() == kind::AND) {
+ ii = pos.begin();
+ iiend = pos.end();
+ } else {
+ ii = expr::NodeSelfIterator::self(pos);
+ iiend = expr::NodeSelfIterator::selfEnd(pos);
+ }
+ for(; ii != iiend; ++ii) {
+ Node& varRef = intVars[*ii];
+ if(varRef.isNull()) {
+ stringstream ss;
+ ss << "mipvar_" << *ii;
+ Node newVar = nm->mkSkolem(ss.str(), nm->integerType(), "a variable introduced due to scrubbing a miplib encoding", NodeManager::SKOLEM_EXACT_NAME);
+ Node geq = Rewriter::rewrite(nm->mkNode(kind::GEQ, newVar, zero));
+ Node leq = Rewriter::rewrite(nm->mkNode(kind::LEQ, newVar, one));
+ d_assertionsToCheck.push_back(Rewriter::rewrite(geq.andNode(leq)));
+ SubstitutionMap nullMap(&d_fakeContext);
+ Theory::PPAssertStatus status CVC4_UNUSED;// just for assertions
+ status = d_smt.d_theoryEngine->solve(geq, nullMap);
+ Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
+ "unexpected solution from arith's ppAssert()");
+ Assert(nullMap.empty(),
+ "unexpected substitution from arith's ppAssert()");
+ status = d_smt.d_theoryEngine->solve(leq, nullMap);
+ Assert(status == Theory::PP_ASSERT_STATUS_UNSOLVED,
+ "unexpected solution from arith's ppAssert()");
+ Assert(nullMap.empty(),
+ "unexpected substitution from arith's ppAssert()");
+ d_smt.d_theoryEngine->getModel()->addSubstitution(*ii, newVar.eqNode(one));
+ newVars.push_back(newVar);
+ varRef = newVar;
+ } else {
+ newVars.push_back(varRef);
+ }
+ if(!d_smt.d_logic.areIntegersUsed()) {
+ d_smt.d_logic = d_smt.d_logic.getUnlockedCopy();
+ d_smt.d_logic.enableIntegers();
+ d_smt.d_logic.lock();
+ }
+ }
+ Node sum;
+ if(pos.getKind() == kind::AND) {
+ NodeBuilder<> sumb(kind::PLUS);
+ for(size_t ii = 0; ii < pos.getNumChildren(); ++ii) {
+ sumb << nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][ii]), newVars[ii]);
+ }
+ sum = sumb;
+ } else {
+ sum = nm->mkNode(kind::MULT, nm->mkConst(coef[pos_var][0]), newVars[0]);
+ }
+ Debug("miplib") << "vars[] " << var << endl
+ << " eq " << Rewriter::rewrite(sum) << endl;
+ Node newAssertion = var.eqNode(Rewriter::rewrite(sum));
+ if(d_topLevelSubstitutions.hasSubstitution(newAssertion[0])) {
+ //Warning() << "RE-SUBSTITUTION " << newAssertion[0] << endl;
+ //Warning() << "REPLACE " << newAssertion[1] << endl;
+ //Warning() << "ORIG " << d_topLevelSubstitutions.getSubstitution(newAssertion[0]) << endl;
+ Assert(d_topLevelSubstitutions.getSubstitution(newAssertion[0]) == newAssertion[1]);
+ } else if(pos.getNumChildren() <= options::arithMLTrickSubstitutions()) {
+ d_topLevelSubstitutions.addSubstitution(newAssertion[0], newAssertion[1]);
+ Debug("miplib") << "addSubs: " << newAssertion[0] << " to " << newAssertion[1] << endl;
+ } else {
+ Debug("miplib") << "skipSubs: " << newAssertion[0] << " to " << newAssertion[1] << " (threshold is " << options::arithMLTrickSubstitutions() << ")" << endl;
+ }
+ newAssertion = Rewriter::rewrite(newAssertion);
+ Debug("miplib") << " " << newAssertion << endl;
+ d_assertionsToCheck.push_back(newAssertion);
+ Debug("miplib") << " assertions to remove: " << endl;
+ for(vector<TNode>::const_iterator k = asserts[pos_var].begin(), k_end = asserts[pos_var].end(); k != k_end; ++k) {
+ Debug("miplib") << " " << *k << endl;
+ removeAssertions.insert((*k).getId());
+ }
+ }
+ }
+ }
+ }
+ }
+ if(!removeAssertions.empty()) {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): scrubbing miplib encoding..." << endl;
+ Node trueNode = nm->mkConst(true);
+ for(size_t i = 0; i < d_realAssertionsEnd; ++i) {
+ if(removeAssertions.find(d_assertionsToCheck[i].getId()) != removeAssertions.end()) {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): - removing " << d_assertionsToCheck[i] << endl;
+ d_assertionsToCheck[i] = trueNode;
+ ++d_smt.d_stats->d_numMiplibAssertionsRemoved;
+ } else if(d_assertionsToCheck[i].getKind() == kind::AND) {
+ size_t removals = removeFromConjunction(d_assertionsToCheck[i], removeAssertions);
+ if(removals > 0) {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): - reduced " << d_assertionsToCheck[i] << endl;
+ Debug("miplib") << "SmtEnginePrivate::simplify(): - by " << removals << " conjuncts" << endl;
+ d_smt.d_stats->d_numMiplibAssertionsRemoved += removals;
+ }
+ }
+ Debug("miplib") << "had: " << d_assertionsToCheck[i] << endl;
+ d_assertionsToCheck[i] = Rewriter::rewrite(d_topLevelSubstitutions.apply(d_assertionsToCheck[i]));
+ Debug("miplib") << "now: " << d_assertionsToCheck[i] << endl;
+ }
+ } else {
+ Debug("miplib") << "SmtEnginePrivate::simplify(): miplib pass found nothing." << endl;
+ }
+ d_realAssertionsEnd = d_assertionsToCheck.size();
+}
+
// returns false if simplification led to "false"
bool SmtEnginePrivate::simplifyAssertions()
throw(TypeCheckingException, LogicException) {
@@ -1904,10 +2314,37 @@ bool SmtEnginePrivate::simplifyAssertions()
if(options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
// Perform non-clausal simplification
+ Chat() << "...performing nonclausal simplification..." << endl;
Trace("simplify") << "SmtEnginePrivate::simplify(): "
<< "performing non-clausal simplification" << endl;
bool noConflict = nonClausalSimplify();
- if(!noConflict) return false;
+ if(!noConflict) {
+ return false;
+ }
+
+ // We piggy-back off of the BackEdgesMap in the CircuitPropagator to
+ // do the miplib trick.
+ if( // check that option is on
+ options::arithMLTrick() &&
+ // miplib rewrites aren't safe in incremental mode
+ ! options::incrementalSolving() &&
+ // only useful in arith
+ d_smt.d_logic.isTheoryEnabled(theory::THEORY_ARITH) &&
+ // we add new assertions and need this (in practice, this
+ // restriction only disables miplib processing during
+ // re-simplification, which we don't expect to be useful anyway)
+ d_realAssertionsEnd == d_assertionsToCheck.size() ) {
+ Chat() << "...fixing miplib encodings..." << endl;
+ Trace("simplify") << "SmtEnginePrivate::simplify(): "
+ << "looking for miplib pseudobooleans..." << endl;
+
+ TimerStat::CodeTimer miplibTimer(d_smt.d_stats->d_miplibPassTime);
+
+ doMiplibTrick();
+ } else {
+ Trace("simplify") << "SmtEnginePrivate::simplify(): "
+ << "skipping miplib pseudobooleans pass (either incrementalSolving is on, or miplib pbs are turned off)..." << endl;
+ }
} else {
Assert(d_assertionsToCheck.empty());
d_assertionsToCheck.swap(d_assertionsToPreprocess);
@@ -1919,6 +2356,7 @@ bool SmtEnginePrivate::simplifyAssertions()
// Theory preprocessing
if (d_smt.d_earlyTheoryPP) {
+ Chat() << "...doing early theory preprocessing..." << endl;
TimerStat::CodeTimer codeTimer(d_smt.d_stats->d_theoryPreprocessTime);
// Call the theory preprocessors
d_smt.d_theoryEngine->preprocessStart();
@@ -1935,6 +2373,7 @@ bool SmtEnginePrivate::simplifyAssertions()
// ITE simplification
if(options::doITESimp()) {
+ Chat() << "...doing ITE simplification..." << endl;
simpITE();
}
@@ -1944,6 +2383,7 @@ bool SmtEnginePrivate::simplifyAssertions()
// Unconstrained simplification
if(options::unconstrainedSimp()) {
+ Chat() << "...doing unconstrained simplification..." << endl;
unconstrainedSimp();
}
@@ -1952,6 +2392,7 @@ bool SmtEnginePrivate::simplifyAssertions()
Debug("smt") << " d_assertionsToCheck : " << d_assertionsToCheck.size() << endl;
if(options::repeatSimp() && options::simplificationMode() != SIMPLIFICATION_MODE_NONE) {
+ Chat() << "...doing another round of nonclausal simplification..." << endl;
Trace("simplify") << "SmtEnginePrivate::simplify(): "
<< " doing repeated simplification" << std::endl;
d_assertionsToCheck.swap(d_assertionsToPreprocess);
@@ -2012,6 +2453,7 @@ Result SmtEngine::check() {
resource = d_resourceBudgetPerCall;
}
+ Chat() << "solving..." << endl;
Trace("smt") << "SmtEngine::check(): running check" << endl;
Result result = d_propEngine->checkSat(millis, resource);
@@ -2209,8 +2651,7 @@ void SmtEnginePrivate::processAssertions() {
if( options::sortInference() ){
//sort inference technique
- SortInference si;
- si.simplify( d_assertionsToPreprocess );
+ d_smt.d_theoryEngine->getSortInference()->simplify( d_assertionsToPreprocess );
}
dumpAssertions("pre-simplify", d_assertionsToPreprocess);
@@ -2242,7 +2683,7 @@ void SmtEnginePrivate::processAssertions() {
dumpAssertions("pre-repeat-simplify", d_assertionsToCheck);
if(options::repeatSimp()) {
d_assertionsToCheck.swap(d_assertionsToPreprocess);
- Chat() << "simplifying assertions..." << endl;
+ Chat() << "re-simplifying assertions..." << endl;
noConflict &= simplifyAssertions();
if (noConflict) {
// Need to fix up assertion list to maintain invariants:
diff --git a/src/smt/smt_engine.h b/src/smt/smt_engine.h
index 3edcd6872..cdae68d96 100644
--- a/src/smt/smt_engine.h
+++ b/src/smt/smt_engine.h
@@ -47,7 +47,7 @@ namespace CVC4 {
template <bool ref_count> class NodeTemplate;
typedef NodeTemplate<true> Node;
typedef NodeTemplate<false> TNode;
-class NodeHashFunction;
+struct NodeHashFunction;
class Command;
class GetModelCommand;
@@ -77,7 +77,7 @@ namespace smt {
*/
class DefinedFunction;
- class SmtEngineStatistics;
+ struct SmtEngineStatistics;
class SmtEnginePrivate;
class SmtScope;
class BooleanTermConverter;
diff --git a/src/theory/arith/Makefile.am b/src/theory/arith/Makefile.am
index b2d1b9f09..76d8d9083 100644
--- a/src/theory/arith/Makefile.am
+++ b/src/theory/arith/Makefile.am
@@ -9,6 +9,7 @@ libarith_la_SOURCES = \
theory_arith_type_rules.h \
type_enumerator.h \
arithvar.h \
+ arithvar.cpp \
arith_rewriter.h \
arith_rewriter.cpp \
arith_static_learner.h \
diff --git a/src/theory/arith/arith_static_learner.cpp b/src/theory/arith/arith_static_learner.cpp
index 5b8d3befc..124fa8e2a 100644
--- a/src/theory/arith/arith_static_learner.cpp
+++ b/src/theory/arith/arith_static_learner.cpp
@@ -19,8 +19,7 @@
#include "theory/arith/arith_utilities.h"
#include "theory/arith/arith_static_learner.h"
-
-#include "util/propositional_query.h"
+#include "theory/arith/options.h"
#include "expr/expr.h"
#include "expr/convenience_node_builders.h"
@@ -36,7 +35,6 @@ namespace arith {
ArithStaticLearner::ArithStaticLearner(context::Context* userContext) :
- d_miplibTrick(userContext),
d_minMap(userContext),
d_maxMap(userContext),
d_statistics()
@@ -44,21 +42,15 @@ ArithStaticLearner::ArithStaticLearner(context::Context* userContext) :
ArithStaticLearner::Statistics::Statistics():
d_iteMinMaxApplications("theory::arith::iteMinMaxApplications", 0),
- d_iteConstantApplications("theory::arith::iteConstantApplications", 0),
- d_miplibtrickApplications("theory::arith::miplibtrickApplications", 0),
- d_avgNumMiplibtrickValues("theory::arith::avgNumMiplibtrickValues")
+ d_iteConstantApplications("theory::arith::iteConstantApplications", 0)
{
StatisticsRegistry::registerStat(&d_iteMinMaxApplications);
StatisticsRegistry::registerStat(&d_iteConstantApplications);
- StatisticsRegistry::registerStat(&d_miplibtrickApplications);
- StatisticsRegistry::registerStat(&d_avgNumMiplibtrickValues);
}
ArithStaticLearner::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_iteMinMaxApplications);
StatisticsRegistry::unregisterStat(&d_iteConstantApplications);
- StatisticsRegistry::unregisterStat(&d_miplibtrickApplications);
- StatisticsRegistry::unregisterStat(&d_avgNumMiplibtrickValues);
}
void ArithStaticLearner::staticLearning(TNode n, NodeBuilder<>& learned){
@@ -103,8 +95,6 @@ void ArithStaticLearner::staticLearning(TNode n, NodeBuilder<>& learned){
process(n,learned, defTrue);
}
-
- postProcess(learned);
}
@@ -126,27 +116,10 @@ void ArithStaticLearner::process(TNode n, NodeBuilder<>& learned, const TNodeSet
iteConstant(n, learned);
}
break;
- case IMPLIES:
- // == 3-FINITE VALUE SET : Collect information ==
- if(n[1].getKind() == EQUAL &&
- n[1][0].isVar() &&
- defTrue.find(n) != defTrue.end()){
- Node eqTo = n[1][1];
- Node rewriteEqTo = Rewriter::rewrite(eqTo);
- if(rewriteEqTo.getKind() == CONST_RATIONAL){
-
- TNode var = n[1][0];
- Node current = (d_miplibTrick.find(var) == d_miplibTrick.end()) ?
- mkBoolNode(false) : d_miplibTrick[var];
- d_miplibTrick.insert(var, n.orNode(current));
- Debug("arith::miplib") << "insert " << var << " const " << n << endl;
- }
- }
- break;
case CONST_RATIONAL:
// Mark constants as minmax
- d_minMap[n] = n.getConst<Rational>();
- d_maxMap[n] = n.getConst<Rational>();
+ d_minMap.insert(n, n.getConst<Rational>());
+ d_maxMap.insert(n, n.getConst<Rational>());
break;
case OR: {
// Look for things like "x = 0 OR x = 1" (that are defTrue) and
@@ -248,7 +221,7 @@ void ArithStaticLearner::iteConstant(TNode n, NodeBuilder<>& learned){
DeltaRational min = std::min(first, second);
CDNodeToMinMaxMap::const_iterator minFind = d_minMap.find(n);
if (minFind == d_minMap.end() || (*minFind).second < min) {
- d_minMap[n] = min;
+ d_minMap.insert(n, min);
Node nGeqMin;
if (min.getInfinitesimalPart() == 0) {
nGeqMin = NodeBuilder<2>(kind::GEQ) << n << mkRationalNode(min.getNoninfinitesimalPart());
@@ -267,7 +240,7 @@ void ArithStaticLearner::iteConstant(TNode n, NodeBuilder<>& learned){
DeltaRational max = std::max(first, second);
CDNodeToMinMaxMap::const_iterator maxFind = d_maxMap.find(n);
if (maxFind == d_maxMap.end() || (*maxFind).second > max) {
- d_maxMap[n] = max;
+ d_maxMap.insert(n, max);
Node nLeqMax;
if (max.getInfinitesimalPart() == 0) {
nLeqMax = NodeBuilder<2>(kind::LEQ) << n << mkRationalNode(max.getNoninfinitesimalPart());
@@ -291,99 +264,6 @@ std::set<Node> listToSet(TNode l){
return ret;
}
-void ArithStaticLearner::postProcess(NodeBuilder<>& learned){
- // == 3-FINITE VALUE SET ==
- CDNodeToNodeListMap::const_iterator keyIter = d_miplibTrick.begin();
- CDNodeToNodeListMap::const_iterator endKeys = d_miplibTrick.end();
- while(keyIter != endKeys) {
- TNode var = (*keyIter).first;
- Node list = (*keyIter).second;
- const set<Node> imps = listToSet(list);
-
- if(imps.empty()){
- ++keyIter;
- continue;
- }
-
- Assert(!imps.empty());
- vector<Node> conditions;
- set<Rational> values;
- set<Node>::const_iterator j=imps.begin(), impsEnd=imps.end();
- for(; j != impsEnd; ++j){
- TNode imp = *j;
- Assert(imp.getKind() == IMPLIES);
- Assert(imp[1].getKind() == EQUAL);
-
- Node eqTo = imp[1][1];
- Node rewriteEqTo = Rewriter::rewrite(eqTo);
- Assert(rewriteEqTo.getKind() == CONST_RATIONAL);
-
- conditions.push_back(imp[0]);
- values.insert(rewriteEqTo.getConst<Rational>());
- }
-
- Node possibleTaut = Node::null();
- if(conditions.size() == 1){
- possibleTaut = conditions.front();
- }else{
- NodeBuilder<> orBuilder(OR);
- orBuilder.append(conditions);
- possibleTaut = orBuilder;
- }
-
-
- Debug("arith::miplib") << "var: " << var << endl;
- Debug("arith::miplib") << "possibleTaut: " << possibleTaut << endl;
-
- Result isTaut = PropositionalQuery::isTautology(possibleTaut);
- if(isTaut == Result(Result::VALID)){
- miplibTrick(var, values, learned);
- d_miplibTrick.insert(var, mkBoolNode(false));
- }
- ++keyIter;
- }
-}
-
-
-void ArithStaticLearner::miplibTrick(TNode var, set<Rational>& values, NodeBuilder<>& learned){
-
- Debug("arith::miplib") << var << " found a tautology!"<< endl;
-
- const Rational& min = *(values.begin());
- const Rational& max = *(values.rbegin());
-
- Debug("arith::miplib") << "min: " << min << endl;
- Debug("arith::miplib") << "max: " << max << endl;
-
- Assert(min <= max);
- ++(d_statistics.d_miplibtrickApplications);
- (d_statistics.d_avgNumMiplibtrickValues).addEntry(values.size());
-
- Node nGeqMin = NodeBuilder<2>(GEQ) << var << mkRationalNode(min);
- Node nLeqMax = NodeBuilder<2>(LEQ) << var << mkRationalNode(max);
- Debug("arith::miplib") << nGeqMin << nLeqMax << endl;
- learned << nGeqMin << nLeqMax;
- set<Rational>::iterator valuesIter = values.begin();
- set<Rational>::iterator valuesEnd = values.end();
- set<Rational>::iterator valuesPrev = valuesIter;
- ++valuesIter;
- for(; valuesIter != valuesEnd; valuesPrev = valuesIter, ++valuesIter){
- const Rational& prev = *valuesPrev;
- const Rational& curr = *valuesIter;
- Assert(prev < curr);
-
- //The interval (last,curr) can be excluded:
- //(not (and (> var prev) (< var curr))
- //<=> (or (not (> var prev)) (not (< var curr)))
- //<=> (or (<= var prev) (>= var curr))
- Node leqPrev = NodeBuilder<2>(LEQ) << var << mkRationalNode(prev);
- Node geqCurr = NodeBuilder<2>(GEQ) << var << mkRationalNode(curr);
- Node excludedMiddle = NodeBuilder<2>(OR) << leqPrev << geqCurr;
- Debug("arith::miplib") << excludedMiddle << endl;
- learned << excludedMiddle;
- }
-}
-
void ArithStaticLearner::addBound(TNode n) {
CDNodeToMinMaxMap::const_iterator minFind = d_minMap.find(n[0]);
@@ -398,7 +278,7 @@ void ArithStaticLearner::addBound(TNode n) {
/* fall through */
case kind::LEQ:
if (maxFind == d_maxMap.end() || (*maxFind).second > bound) {
- d_maxMap[n[0]] = bound;
+ d_maxMap.insert(n[0], bound);
Debug("arith::static") << "adding bound " << n << endl;
}
break;
@@ -407,7 +287,7 @@ void ArithStaticLearner::addBound(TNode n) {
/* fall through */
case kind::GEQ:
if (minFind == d_minMap.end() || (*minFind).second < bound) {
- d_minMap[n[0]] = bound;
+ d_minMap.insert(n[0], bound);
Debug("arith::static") << "adding bound " << n << endl;
}
break;
diff --git a/src/theory/arith/arith_static_learner.h b/src/theory/arith/arith_static_learner.h
index b047018e8..48ee6a3bb 100644
--- a/src/theory/arith/arith_static_learner.h
+++ b/src/theory/arith/arith_static_learner.h
@@ -27,7 +27,7 @@
#include "context/context.h"
#include "context/cdlist.h"
-#include "context/cdhashmap.h"
+#include "context/cdtrail_hashmap.h"
#include <set>
namespace CVC4 {
@@ -37,21 +37,10 @@ namespace arith {
class ArithStaticLearner {
private:
- /* Maps a variable, x, to the set of defTrue nodes of the form
- * (=> _ (= x c))
- * where c is a constant.
- */
- //typedef __gnu_cxx::hash_map<Node, std::set<Node>, NodeHashFunction> VarToNodeSetMap;
- typedef context::CDHashMap<Node, Node, NodeHashFunction> CDNodeToNodeListMap;
- // The domain is an implicit list OR(x, OR(y, ..., FALSE ))
- // or FALSE
- CDNodeToNodeListMap d_miplibTrick;
-
/**
* Map from a node to it's minimum and maximum.
*/
- //typedef __gnu_cxx::hash_map<Node, DeltaRational, NodeHashFunction> NodeToMinMaxMap;
- typedef context::CDHashMap<Node, DeltaRational, NodeHashFunction> CDNodeToMinMaxMap;
+ typedef context::CDTrailHashMap<Node, DeltaRational, NodeHashFunction> CDNodeToMinMaxMap;
CDNodeToMinMaxMap d_minMap;
CDNodeToMinMaxMap d_maxMap;
@@ -64,23 +53,15 @@ public:
private:
void process(TNode n, NodeBuilder<>& learned, const TNodeSet& defTrue);
- void postProcess(NodeBuilder<>& learned);
-
void iteMinMax(TNode n, NodeBuilder<>& learned);
void iteConstant(TNode n, NodeBuilder<>& learned);
- void miplibTrick(TNode var, std::set<Rational>& values, NodeBuilder<>& learned);
-
-
/** These fields are designed to be accessible to ArithStaticLearner methods. */
class Statistics {
public:
IntStat d_iteMinMaxApplications;
IntStat d_iteConstantApplications;
- IntStat d_miplibtrickApplications;
- AverageStat d_avgNumMiplibtrickValues;
-
Statistics();
~Statistics();
};
diff --git a/src/theory/arith/arith_utilities.h b/src/theory/arith/arith_utilities.h
index c7f511a98..76210fc7c 100644
--- a/src/theory/arith/arith_utilities.h
+++ b/src/theory/arith/arith_utilities.h
@@ -168,59 +168,6 @@ inline int deltaCoeff(Kind k){
}
}
-
-// template <bool selectLeft>
-// inline TNode getSide(TNode assertion, Kind simpleKind){
-// switch(simpleKind){
-// case kind::LT:
-// case kind::GT:
-// case kind::DISTINCT:
-// return selectLeft ? (assertion[0])[0] : (assertion[0])[1];
-// case kind::LEQ:
-// case kind::GEQ:
-// case kind::EQUAL:
-// return selectLeft ? assertion[0] : assertion[1];
-// default:
-// Unreachable();
-// return TNode::null();
-// }
-// }
-
-// inline DeltaRational determineRightConstant(TNode assertion, Kind simpleKind){
-// TNode right = getSide<false>(assertion, simpleKind);
-
-// Assert(right.getKind() == kind::CONST_RATIONAL);
-// const Rational& noninf = right.getConst<Rational>();
-
-// Rational inf = Rational(Integer(deltaCoeff(simpleKind)));
-// return DeltaRational(noninf, inf);
-// }
-
-// inline DeltaRational asDeltaRational(TNode n){
-// Kind simp = simplifiedKind(n);
-// return determineRightConstant(n, simp);
-// }
-
-// /**
-// * Takes two nodes with exactly 2 children,
-// * the second child of both are of kind CONST_RATIONAL,
-// * and compares value of the two children.
-// * This is for comparing inequality nodes.
-// * RightHandRationalLT((<= x 50), (< x 75)) == true
-// */
-// struct RightHandRationalLT
-// {
-// bool operator()(TNode s1, TNode s2) const
-// {
-// TNode rh1 = s1[1];
-// TNode rh2 = s2[1];
-// const Rational& c1 = rh1.getConst<Rational>();
-// const Rational& c2 = rh2.getConst<Rational>();
-// int cmpRes = c1.cmp(c2);
-// return cmpRes < 0;
-// }
-// };
-
inline Node negateConjunctionAsClause(TNode conjunction){
Assert(conjunction.getKind() == kind::AND);
NodeBuilder<> orBuilder(kind::OR);
diff --git a/src/theory/arith/arithvar.cpp b/src/theory/arith/arithvar.cpp
new file mode 100644
index 000000000..76b143fff
--- /dev/null
+++ b/src/theory/arith/arithvar.cpp
@@ -0,0 +1,13 @@
+
+#include "theory/arith/arithvar.h"
+#include <limits>
+
+namespace CVC4 {
+namespace theory {
+namespace arith {
+
+const ArithVar ARITHVAR_SENTINEL = std::numeric_limits<ArithVar>::max();
+
+}/* CVC4::theory::arith namespace */
+}/* CVC4::theory namespace */
+}/* CVC4 namespace */
diff --git a/src/theory/arith/arithvar.h b/src/theory/arith/arithvar.h
index 7cb6c6e99..95614a011 100644
--- a/src/theory/arith/arithvar.h
+++ b/src/theory/arith/arithvar.h
@@ -22,24 +22,23 @@
#ifndef __CVC4__THEORY__ARITH__ARITHVAR_H
#define __CVC4__THEORY__ARITH__ARITHVAR_H
-#include <limits>
#include <ext/hash_map>
#include "expr/node.h"
#include "context/cdhashset.h"
-#include "context/cdhashset.h"
#include "util/index.h"
+#include "util/dense_map.h"
namespace CVC4 {
namespace theory {
namespace arith {
typedef Index ArithVar;
-const ArithVar ARITHVAR_SENTINEL = std::numeric_limits<ArithVar>::max();
+extern const ArithVar ARITHVAR_SENTINEL;
//Maps from Nodes -> ArithVars, and vice versa
typedef __gnu_cxx::hash_map<Node, ArithVar, NodeHashFunction> NodeToArithVarMap;
-typedef __gnu_cxx::hash_map<ArithVar, Node> ArithVarToNodeMap;
+typedef DenseMap<Node> ArithVarToNodeMap;
/**
* ArithVarCallBack provides a mechanism for agreeing on callbacks while
@@ -50,6 +49,16 @@ public:
virtual void operator()(ArithVar x) = 0;
};
+/**
+ * Requests arithmetic variables for internal use,
+ * and releases arithmetic variables that are no longer being used.
+ */
+class ArithVarMalloc {
+public:
+ virtual ArithVar request() = 0;
+ virtual void release(ArithVar v) = 0;
+};
+
class TNodeCallBack {
public:
virtual void operator()(TNode n) = 0;
diff --git a/src/theory/arith/arithvar_node_map.h b/src/theory/arith/arithvar_node_map.h
index 3a2cff236..e0e589e57 100644
--- a/src/theory/arith/arithvar_node_map.h
+++ b/src/theory/arith/arithvar_node_map.h
@@ -40,31 +40,50 @@ private:
ArithVarToNodeMap d_arithVarToNodeMap;
public:
+
+ typedef ArithVarToNodeMap::const_iterator var_iterator;
+
ArithVarNodeMap() {}
inline bool hasArithVar(TNode x) const {
return d_nodeToArithVarMap.find(x) != d_nodeToArithVarMap.end();
}
+ inline bool hasNode(ArithVar a) const {
+ return d_arithVarToNodeMap.isKey(a);
+ }
+
inline ArithVar asArithVar(TNode x) const{
Assert(hasArithVar(x));
Assert((d_nodeToArithVarMap.find(x))->second <= ARITHVAR_SENTINEL);
return (d_nodeToArithVarMap.find(x))->second;
}
+
inline Node asNode(ArithVar a) const{
- Assert(d_arithVarToNodeMap.find(a) != d_arithVarToNodeMap.end());
- return (d_arithVarToNodeMap.find(a))->second;
+ Assert(hasNode(a));
+ return d_arithVarToNodeMap[a];
}
inline void setArithVar(TNode x, ArithVar a){
Assert(!hasArithVar(x));
- Assert(d_arithVarToNodeMap.find(a) == d_arithVarToNodeMap.end());
- d_arithVarToNodeMap[a] = x;
+ Assert(!d_arithVarToNodeMap.isKey(a));
+ d_arithVarToNodeMap.set(a, x);
d_nodeToArithVarMap[x] = a;
}
- const ArithVarToNodeMap& getArithVarToNodeMap() const {
- return d_arithVarToNodeMap;
+ inline void remove(ArithVar x){
+ Assert(hasNode(x));
+ Node node = asNode(x);
+
+ d_nodeToArithVarMap.erase(d_nodeToArithVarMap.find(node));
+ d_arithVarToNodeMap.remove(x);
+ }
+
+ var_iterator var_begin() const {
+ return d_arithVarToNodeMap.begin();
+ }
+ var_iterator var_end() const {
+ return d_arithVarToNodeMap.end();
}
};/* class ArithVarNodeMap */
diff --git a/src/theory/arith/congruence_manager.cpp b/src/theory/arith/congruence_manager.cpp
index 5ee250c09..de4c7eac3 100644
--- a/src/theory/arith/congruence_manager.cpp
+++ b/src/theory/arith/congruence_manager.cpp
@@ -272,7 +272,7 @@ void ArithCongruenceManager::addWatchedPair(ArithVar s, TNode x, TNode y){
d_watchedVariables.add(s);
Node eq = x.eqNode(y);
- d_watchedEqualities[s] = eq;
+ d_watchedEqualities.set(s, eq);
}
void ArithCongruenceManager::assertionToEqualityEngine(bool isEquality, ArithVar s, TNode reason){
diff --git a/src/theory/arith/constraint.cpp b/src/theory/arith/constraint.cpp
index 392d04f6c..cf3aeafee 100644
--- a/src/theory/arith/constraint.cpp
+++ b/src/theory/arith/constraint.cpp
@@ -371,6 +371,10 @@ void ConstraintValue::setAssertedToTheTheory(TNode witness) {
d_database->pushAssertionOrderWatch(this, witness);
}
+// bool ConstraintValue::isPsuedoConstraint() const {
+// return d_proof == d_database->d_psuedoConstraintProof;
+// }
+
bool ConstraintValue::isSelfExplaining() const {
return d_proof == d_database->d_selfExplainingProof;
}
@@ -481,6 +485,9 @@ ConstraintDatabase::ConstraintDatabase(context::Context* satContext, context::Co
d_equalityEngineProof = d_proofs.size();
d_proofs.push_back(NullConstraint);
+
+ // d_psuedoConstraintProof = d_proofs.size();
+ // d_proofs.push_back(NullConstraint);
}
Constraint ConstraintDatabase::getConstraint(ArithVar v, ConstraintType t, const DeltaRational& r){
@@ -566,8 +573,32 @@ ConstraintDatabase::Statistics::~Statistics(){
}
void ConstraintDatabase::addVariable(ArithVar v){
- Assert(v == d_varDatabases.size());
- d_varDatabases.push_back(new PerVariableDatabase(v));
+ if(d_reclaimable.isMember(v)){
+ SortedConstraintMap& scm = getVariableSCM(v);
+
+ std::vector<Constraint> constraintList;
+
+ for(SortedConstraintMapIterator i = scm.begin(), end = scm.end(); i != end; ++i){
+ (i->second).push_into(constraintList);
+ }
+ while(!constraintList.empty()){
+ Constraint c = constraintList.back();
+ constraintList.pop_back();
+ Assert(c->safeToGarbageCollect());
+ delete c;
+ }
+ Assert(scm.empty());
+
+ d_reclaimable.remove(v);
+ }else{
+ Assert(v == d_varDatabases.size());
+ d_varDatabases.push_back(new PerVariableDatabase(v));
+ }
+}
+
+void ConstraintDatabase::removeVariable(ArithVar v){
+ Assert(!d_reclaimable.isMember(v));
+ d_reclaimable.add(v);
}
bool ConstraintValue::safeToGarbageCollect() const{
@@ -802,6 +833,13 @@ void ConstraintValue::impliedBy(const std::vector<Constraint>& b){
}
}
+// void ConstraintValue::setPsuedoConstraint(){
+// Assert(truthIsUnknown());
+// Assert(!hasLiteral());
+
+// d_database->pushProofWatch(this, d_database->d_psuedoConstraintProof);
+// }
+
void ConstraintValue::setEqualityEngineProof(){
Assert(truthIsUnknown());
Assert(hasLiteral());
@@ -818,6 +856,7 @@ void ConstraintValue::markAsTrue(){
void ConstraintValue::markAsTrue(Constraint imp){
Assert(truthIsUnknown());
Assert(imp->hasProof());
+ //Assert(!imp->isPsuedoConstraint());
d_database->d_proofs.push_back(NullConstraint);
d_database->d_proofs.push_back(imp);
@@ -829,6 +868,8 @@ void ConstraintValue::markAsTrue(Constraint impA, Constraint impB){
Assert(truthIsUnknown());
Assert(impA->hasProof());
Assert(impB->hasProof());
+ //Assert(!impA->isPsuedoConstraint());
+ //Assert(!impB->isPsuedoConstraint());
d_database->d_proofs.push_back(NullConstraint);
d_database->d_proofs.push_back(impA);
@@ -845,6 +886,7 @@ void ConstraintValue::markAsTrue(const vector<Constraint>& a){
for(vector<Constraint>::const_iterator i = a.begin(), end = a.end(); i != end; ++i){
Constraint c_i = *i;
Assert(c_i->hasProof());
+ //Assert(!c_i->isPsuedoConstraint());
d_database->d_proofs.push_back(c_i);
}
@@ -861,6 +903,7 @@ SortedConstraintMap& ConstraintValue::constraintSet() const{
bool ConstraintValue::proofIsEmpty() const{
Assert(hasProof());
bool result = d_database->d_proofs[d_proof] == NullConstraint;
+ //Assert((!result) || isSelfExplaining() || hasEqualityEngineProof() || isPsuedoConstraint());
Assert((!result) || isSelfExplaining() || hasEqualityEngineProof());
return result;
}
@@ -869,6 +912,7 @@ void ConstraintValue::explainBefore(NodeBuilder<>& nb, AssertionOrder order) con
Assert(hasProof());
Assert(!isSelfExplaining() || assertedToTheTheory());
+
if(assertedBefore(order)){
nb << getWitness();
}else if(hasEqualityEngineProof()){
diff --git a/src/theory/arith/constraint.h b/src/theory/arith/constraint.h
index 331fd2bcb..52aa5a5ce 100644
--- a/src/theory/arith/constraint.h
+++ b/src/theory/arith/constraint.h
@@ -485,6 +485,15 @@ public:
void setEqualityEngineProof();
bool hasEqualityEngineProof() const;
+
+ /**
+ * There cannot be a literal associated with this constraint.
+ * The explanation is the constant true.
+ * explainInto() does nothing.
+ */
+ //void setPsuedoConstraint();
+ //bool isPsuedoConstraint() const;
+
/**
* Returns a explanation of the constraint that is appropriate for conflicts.
*
@@ -694,6 +703,14 @@ private:
*/
ProofId d_equalityEngineProof;
+ /**
+ * Marks a node as being true always.
+ * This is only okay for purely internal things.
+ *
+ * This is a special proof that is always a member of the list.
+ */
+ //ProofId d_psuedoConstraintProof;
+
typedef context::CDList<Constraint, ConstraintValue::ProofCleanup> ProofCleanupList;
typedef context::CDList<Constraint, ConstraintValue::CanBePropagatedCleanup> CBPList;
typedef context::CDList<Constraint, ConstraintValue::AssertionOrderCleanup> AOList;
@@ -817,6 +834,7 @@ public:
void addVariable(ArithVar v);
bool variableDatabaseIsSetup(ArithVar v) const;
+ void removeVariable(ArithVar v);
Node eeExplain(ConstConstraint c) const;
void eeExplain(ConstConstraint c, NodeBuilder<>& nb) const;
@@ -881,6 +899,8 @@ public:
private:
void raiseUnateConflict(Constraint ant, Constraint cons);
+ DenseSet d_reclaimable;
+
class Statistics {
public:
IntStat d_unatePropagateCalls;
diff --git a/src/theory/arith/linear_equality.cpp b/src/theory/arith/linear_equality.cpp
index 360e45289..5063a05c7 100644
--- a/src/theory/arith/linear_equality.cpp
+++ b/src/theory/arith/linear_equality.cpp
@@ -80,7 +80,7 @@ void LinearEqualityModule::update(ArithVar x_i, const DeltaRational& v){
if(Debug.isOn("paranoid:check_tableau")){ debugCheckTableau(); }
}
-void LinearEqualityModule::pivotAndUpdate(ArithVar x_i, ArithVar x_j, DeltaRational& v){
+void LinearEqualityModule::pivotAndUpdate(ArithVar x_i, ArithVar x_j, const DeltaRational& v){
Assert(x_i != x_j);
TimerStat::CodeTimer codeTimer(d_statistics.d_pivotTime);
@@ -188,6 +188,23 @@ void LinearEqualityModule::debugCheckTableau(){
Assert(sum == shouldBe);
}
}
+bool LinearEqualityModule::debugEntireLinEqIsConsistent(const string& s){
+ bool result = true;
+ for(ArithVar var = 0, end = d_tableau.getNumColumns(); var != end; ++var){
+ // for(VarIter i = d_variables.begin(), end = d_variables.end(); i != end; ++i){
+ //ArithVar var = d_arithvarNodeMap.asArithVar(*i);
+ if(!d_partialModel.assignmentIsConsistent(var)){
+ d_partialModel.printModel(var);
+ Warning() << s << ":" << "Assignment is not consistent for " << var ;
+ if(d_tableau.isBasic(var)){
+ Warning() << " (basic)";
+ }
+ Warning() << endl;
+ result = false;
+ }
+ }
+ return result;
+}
DeltaRational LinearEqualityModule::computeBound(ArithVar basic, bool upperBound){
DeltaRational sum(0,0);
diff --git a/src/theory/arith/linear_equality.h b/src/theory/arith/linear_equality.h
index f337ef0db..7df5ee9c3 100644
--- a/src/theory/arith/linear_equality.h
+++ b/src/theory/arith/linear_equality.h
@@ -79,7 +79,7 @@ public:
* and then pivots x_i with the nonbasic variable in its row x_j.
* Updates the assignment of the other basic variables accordingly.
*/
- void pivotAndUpdate(ArithVar x_i, ArithVar x_j, DeltaRational& v);
+ void pivotAndUpdate(ArithVar x_i, ArithVar x_j, const DeltaRational& v);
ArithPartialModel& getPartialModel() const{ return d_partialModel; }
@@ -141,6 +141,11 @@ public:
/** Debugging information for a pivot. */
void debugPivot(ArithVar x_i, ArithVar x_j);
+ /**
+ *
+ */
+ bool debugEntireLinEqIsConsistent(const std::string& s);
+
private:
/** These fields are designed to be accessible to TheoryArith methods. */
diff --git a/src/theory/arith/matrix.cpp b/src/theory/arith/matrix.cpp
index 8e7fe7894..cd7a8a9aa 100644
--- a/src/theory/arith/matrix.cpp
+++ b/src/theory/arith/matrix.cpp
@@ -247,7 +247,7 @@ void Tableau::rowPivot(ArithVar basicOld, ArithVar basicNew){
d_basic2RowIndex.remove(basicOld);
d_basic2RowIndex.set(basicNew, rid);
- d_rowIndex2basic[rid] = basicNew;
+ d_rowIndex2basic.set(rid, basicNew);
}
// void Tableau::addEntry(ArithVar row, ArithVar col, const Rational& coeff){
@@ -397,10 +397,11 @@ void Tableau::addRow(ArithVar basic,
RowIndex newRow = Matrix<Rational>::addRow(coefficients, variables);
addEntry(newRow, basic, Rational(-1));
- Assert(d_rowIndex2basic.size() == newRow);
+ Assert(!d_basic2RowIndex.isKey(basic));
+ Assert(!d_rowIndex2basic.isKey(newRow));
d_basic2RowIndex.set(basic, newRow);
- d_rowIndex2basic.push_back(basic);
+ d_rowIndex2basic.set(newRow, basic);
if(Debug.isOn("matrix")){ printMatrix(); }
@@ -558,6 +559,15 @@ void ReducedRowVector::enqueueNonBasicVariablesAndCoefficients(std::vector< Arit
// return newId;
// }
+void Tableau::removeBasicRow(ArithVar basic){
+ RowIndex rid = basicToRowIndex(basic);
+
+ removeRow(rid);
+ d_basic2RowIndex.remove(basic);
+ d_rowIndex2basic.remove(rid);
+
+}
+
}/* CVC4::theory::arith namespace */
}/* CVC4::theory namespace */
diff --git a/src/theory/arith/matrix.h b/src/theory/arith/matrix.h
index ea6c389b9..027397b6a 100644
--- a/src/theory/arith/matrix.h
+++ b/src/theory/arith/matrix.h
@@ -25,6 +25,7 @@
#include "util/dense_map.h"
#include "theory/arith/arithvar.h"
+#include "theory/arith/arithvar_node_map.h"
#include "theory/arith/normal_form.h"
#include <queue>
@@ -377,6 +378,8 @@ protected:
uint32_t d_entriesInUse;
MatrixEntryVector<T> d_entries;
+ std::vector<RowIndex> d_pool;
+
T d_zero;
public:
@@ -446,6 +449,23 @@ protected:
d_entries.freeEntry(id);
}
+ private:
+ RowIndex requestRowIndex(){
+ if(d_pool.empty()){
+ RowIndex ridx = d_rows.size();
+ d_rows.push_back(RowVectorT(&d_entries));
+ return ridx;
+ }else{
+ RowIndex rid = d_pool.back();
+ d_pool.pop_back();
+ return rid;
+ }
+ }
+
+ void releaseRowIndex(RowIndex rid){
+ d_pool.push_back(rid);
+ }
+
public:
size_t getNumRows() const {
@@ -485,8 +505,11 @@ public:
*/
RowIndex addRow(const std::vector<T>& coeffs,
const std::vector<ArithVar>& variables){
- RowIndex ridx = d_rows.size();
- d_rows.push_back(RowVectorT(&d_entries));
+
+ RowIndex ridx = requestRowIndex();
+
+ //RowIndex ridx = d_rows.size();
+ //d_rows.push_back(RowVectorT(&d_entries));
std::vector<Rational>::const_iterator coeffIter = coeffs.begin();
std::vector<ArithVar>::const_iterator varsIter = variables.begin();
@@ -701,36 +724,7 @@ public:
EntryID id = i.getID();
removeEntry(id);
}
- }
-
-
- Node rowAsEquality(RowIndex rid, const ArithVarToNodeMap& map){
- using namespace CVC4::kind;
-
- Assert(getRowLength(rid) >= 2);
-
- std::vector<Node> pairs;
- for(RowIterator i = getRow(rid); !i.atEnd(); ++i){
- const Entry& entry = *i;
- ArithVar colVar = entry.getColVar();
-
- Node var = (map.find(colVar))->second;
- Node coeff = mkRationalNode(entry.getCoefficient());
-
- Node mult = NodeBuilder<2>(MULT) << coeff << var;
- pairs.push_back(mult);
- }
-
- Node sum = Node::null();
- if(pairs.size() == 1 ){
- sum = pairs.front();
- }else{
- Assert(pairs.size() >= 2);
- NodeBuilder<> sumBuilder(PLUS);
- sumBuilder.append(pairs);
- sum = sumBuilder;
- }
- return NodeBuilder<2>(EQUAL) << sum << mkRationalNode(d_zero);
+ releaseRowIndex(rid);
}
double densityMeasure() const{
@@ -754,6 +748,15 @@ public:
}
}
+ void loadSignQueries(RowIndex rid, DenseMap<int>& target) const{
+
+ RowIterator i = getRow(rid).begin(), i_end = getRow(rid).end();
+ for(; i != i_end; ++i){
+ const MatrixEntry<T>& entry = *i;
+ target.set(entry.getColVar(), entry.getCoefficient().sgn());
+ }
+ }
+
protected:
uint32_t numNonZeroEntries() const { return size(); }
@@ -833,8 +836,10 @@ private:
// Set of all of the basic variables in the tableau.
// ArithVarMap<RowIndex> : ArithVar |-> RowIndex
BasicToRowMap d_basic2RowIndex;
+
// RowIndex |-> Basic Variable
- std::vector<ArithVar> d_rowIndex2basic;
+ typedef DenseMap<ArithVar> RowIndexToBasicMap;
+ RowIndexToBasicMap d_rowIndex2basic;
public:
@@ -882,10 +887,6 @@ public:
return getRow(basicToRowIndex(basic)).begin();
}
- // RowIterator rowIterator(RowIndex r) const {
- // return getRow(r).begin();
- // }
-
/**
* Adds a row to the tableau.
* The new row is equivalent to:
@@ -911,7 +912,6 @@ public:
void removeBasicRow(ArithVar basic);
-
private:
/* Changes the basic variable on the row for basicOld to basicNew. */
void rowPivot(ArithVar basicOld, ArithVar basicNew);
diff --git a/src/theory/arith/options b/src/theory/arith/options
index 38cf07251..9e758a0ef 100644
--- a/src/theory/arith/options
+++ b/src/theory/arith/options
@@ -51,4 +51,16 @@ option arithRewriteEq --enable-arith-rewrite-equalities/--disable-arith-rewrite-
turns on the preprocessing rewrite turning equalities into a conjunction of inequalities
/turns off the preprocessing rewrite turning equalities into a conjunction of inequalities
+option arithMLTrick miplib-trick --enable-miplib-trick/--disable-miplib-trick bool :default false
+ turns on the preprocessing step of attempting to infer bounds on miplib problems
+/turns off the preprocessing step of attempting to infer bounds on miplib problems
+
+option arithMLTrickSubstitutions miplib-trick-subs --miplib-trick-subs unsigned :default 1
+ do substitution for miplib 'tmp' vars if defined in <= N eliminated vars
+
+option doCutAllBounded --enable-cut-all-bounded/--disable-cut-all-bounded bool :default false :read-write
+ turns on the integer solving step of periodically cutting all integer variables that have both upper and lower bounds
+/ turns off the integer solving step of periodically cutting all integer variables that have both upper and lower bounds
+
+
endmodule
diff --git a/src/theory/arith/partial_model.cpp b/src/theory/arith/partial_model.cpp
index 0ffe67763..5dccd8747 100644
--- a/src/theory/arith/partial_model.cpp
+++ b/src/theory/arith/partial_model.cpp
@@ -72,7 +72,9 @@ void ArithPartialModel::setAssignment(ArithVar x, const DeltaRational& safe, con
Debug("partial_model") << "pm: updating the assignment to" << x
<< " now " << r <<endl;
if(safe == r){
- d_hasSafeAssignment[x] = false;
+ if(d_hasSafeAssignment[x]){
+ d_safeAssignment[x] = safe;
+ }
}else{
d_safeAssignment[x] = safe;
@@ -177,6 +179,25 @@ void ArithPartialModel::setUpperBoundConstraint(Constraint c){
d_ubc.set(x, c);
}
+void ArithPartialModel::forceRelaxLowerBound(ArithVar v){
+ AssertArgument(inMaps(v), "Calling forceRelaxLowerBound on a variable that is not properly setup.");
+ AssertArgument(hasLowerBound(v), "Calling forceRelaxLowerBound on a variable without a lowerbound.");
+
+ Debug("partial_model") << "forceRelaxLowerBound(" << v << ") dropping :" << getLowerBoundConstraint(v) << endl;
+
+ d_lbc.set(v, NullConstraint);
+}
+
+
+void ArithPartialModel::forceRelaxUpperBound(ArithVar v){
+ AssertArgument(inMaps(v), "Calling forceRelaxUpperBound on a variable that is not properly setup.");
+ AssertArgument(hasUpperBound(v), "Calling forceRelaxUpperBound on a variable without an upper bound.");
+
+ Debug("partial_model") << "forceRelaxUpperBound(" << v << ") dropping :" << getUpperBoundConstraint(v) << endl;
+
+ d_ubc.set(v, NullConstraint);
+}
+
int ArithPartialModel::cmpToLowerBound(ArithVar x, const DeltaRational& c) const{
if(!hasLowerBound(x)){
// l = -\intfy
diff --git a/src/theory/arith/partial_model.h b/src/theory/arith/partial_model.h
index 49cfd44a1..fdb4a8ffa 100644
--- a/src/theory/arith/partial_model.h
+++ b/src/theory/arith/partial_model.h
@@ -68,16 +68,40 @@ public:
ArithPartialModel(context::Context* c, RationalCallBack& deltaComputation);
+ /**
+ * This sets the lower bound for a variable in the current context.
+ * This must be stronger the previous constraint.
+ */
void setLowerBoundConstraint(Constraint lb);
+
+ /**
+ * This sets the upper bound for a variable in the current context.
+ * This must be stronger the previous constraint.
+ */
void setUpperBoundConstraint(Constraint ub);
+ /** Returns the constraint for the upper bound of a variable. */
inline Constraint getUpperBoundConstraint(ArithVar x) const{
return d_ubc[x];
}
+ /** Returns the constraint for the lower bound of a variable. */
inline Constraint getLowerBoundConstraint(ArithVar x) const{
return d_lbc[x];
}
+ /**
+ * This forces the lower bound for a variable to be relaxed in the current context.
+ * This is done by forcing the lower bound to be NullConstraint.
+ * This is an expert only operation! (See primal simplex for an example.)
+ */
+ void forceRelaxLowerBound(ArithVar x);
+
+ /**
+ * This forces the upper bound for a variable to be relaxed in the current context.
+ * This is done by forcing the upper bound to be NullConstraint.
+ * This is an expert only operation! (See primal simplex for an example.)
+ */
+ void forceRelaxUpperBound(ArithVar x);
/* Initializes a variable to a safe value.*/
void initialize(ArithVar x, const DeltaRational& r);
@@ -190,7 +214,6 @@ public:
d_deltaIsSafe = true;
}
-
private:
/**
@@ -202,7 +225,7 @@ private:
bool equalSizes();
bool inMaps(ArithVar x) const{
- return 0 <= x && x < d_mapSize;
+ return x < d_mapSize;
}
};/* class ArithPartialModel */
diff --git a/src/theory/arith/theory_arith.cpp b/src/theory/arith/theory_arith.cpp
index c2c005767..52f234129 100644
--- a/src/theory/arith/theory_arith.cpp
+++ b/src/theory/arith/theory_arith.cpp
@@ -62,6 +62,8 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputCha
d_unknownsInARow(0),
d_hasDoneWorkSinceCut(false),
d_learner(u),
+ d_numberOfVariables(0),
+ d_pool(),
d_setupLiteralCallback(this),
d_assertionsThatDoNotMatchTheirLiterals(c),
d_nextIntegerCheckVar(0),
@@ -79,12 +81,14 @@ TheoryArith::TheoryArith(context::Context* c, context::UserContext* u, OutputCha
d_tableauResetPeriod(10),
d_conflicts(c),
d_raiseConflict(d_conflicts),
+ d_tempVarMalloc(*this),
d_congruenceManager(c, d_constraintDatabase, d_setupLiteralCallback, d_arithvarNodeMap, d_raiseConflict),
d_simplex(d_linEq, d_raiseConflict),
d_constraintDatabase(c, u, d_arithvarNodeMap, d_congruenceManager, d_raiseConflict),
d_deltaComputeCallback(this),
d_basicVarModelUpdateCallBack(d_simplex),
d_DELTA_ZERO(0),
+ d_fullCheckCounter(0),
d_statistics()
{
}
@@ -749,8 +753,8 @@ Theory::PPAssertStatus TheoryArith::ppAssert(TNode in, SubstitutionMap& outSubst
Assert(elim == Rewriter::rewrite(elim));
- static const unsigned MAX_SUB_SIZE = 20;
- if(false && right.size() > MAX_SUB_SIZE){
+ static const unsigned MAX_SUB_SIZE = 2;
+ if(right.size() > MAX_SUB_SIZE){
Debug("simplify") << "TheoryArith::solve(): did not substitute due to the right hand side containing too many terms: " << minVar << ":" << elim << endl;
Debug("simplify") << right.size() << endl;
}else if(elim.hasSubterm(minVar)){
@@ -822,8 +826,9 @@ void TheoryArith::setupVariable(const Variable& x){
Assert(!isSetup(n));
++(d_statistics.d_statUserVariables);
- ArithVar varN = requestArithVar(n,false);
- setupInitialValue(varN);
+ requestArithVar(n,false);
+ //ArithVar varN = requestArithVar(n,false);
+ //setupInitialValue(varN);
markSetup(n);
@@ -860,8 +865,9 @@ void TheoryArith::setupVariableList(const VarList& vl){
d_nlIncomplete = true;
++(d_statistics.d_statUserVariables);
- ArithVar av = requestArithVar(vlNode, false);
- setupInitialValue(av);
+ requestArithVar(vlNode, false);
+ //ArithVar av = requestArithVar(vlNode, false);
+ //setupInitialValue(av);
markSetup(vlNode);
}
@@ -1054,7 +1060,7 @@ void TheoryArith::setupPolynomial(const Polynomial& poly) {
ArithVar varSlack = requestArithVar(polyNode, true);
d_tableau.addRow(varSlack, coefficients, variables);
- setupInitialValue(varSlack);
+ setupBasicValue(varSlack);
//Add differences to the difference manager
Polynomial::iterator i = poly.begin(), end = poly.end();
@@ -1125,6 +1131,14 @@ void TheoryArith::preRegisterTerm(TNode n) {
Debug("arith::preregister") << "end arith::preRegisterTerm("<< n <<")" << endl;
}
+void TheoryArith::releaseArithVar(ArithVar v){
+ Assert(d_arithvarNodeMap.hasNode(v));
+
+ d_constraintDatabase.removeVariable(v);
+ d_arithvarNodeMap.remove(v);
+
+ d_pool.push_back(v);
+}
ArithVar TheoryArith::requestArithVar(TNode x, bool slack){
//TODO : The VarList trick is good enough?
@@ -1135,32 +1149,73 @@ ArithVar TheoryArith::requestArithVar(TNode x, bool slack){
Assert(!d_arithvarNodeMap.hasArithVar(x));
Assert(x.getType().isReal());// real or integer
- ArithVar varX = d_variables.size();
- d_variables.push_back(Node(x));
- Debug("integers") << "isInteger[[" << x << "]]: " << x.getType().isInteger() << endl;
+ // ArithVar varX = d_variables.size();
+ // d_variables.push_back(Node(x));
+
+ bool reclaim = !d_pool.empty();
+ ArithVar varX;
+
+ if(reclaim){
+ varX = d_pool.back();
+ d_pool.pop_back();
+
+ d_partialModel.setAssignment(varX, d_DELTA_ZERO, d_DELTA_ZERO);
+ }else{
+ varX = d_numberOfVariables;
+ ++d_numberOfVariables;
+
+ d_slackVars.push_back(true);
+ d_variableTypes.push_back(ATReal);
+
+ d_simplex.increaseMax();
+ d_tableau.increaseSize();
+ d_tableauSizeHasBeenModified = true;
+
+ d_partialModel.initialize(varX, d_DELTA_ZERO);
+ }
+
+ ArithType type;
if(slack){
//The type computation is not quite accurate for Rationals that are integral.
//We'll use the isIntegral check from the polynomial package instead.
Polynomial p = Polynomial::parsePolynomial(x);
- d_variableTypes.push_back(p.isIntegral() ? ATInteger : ATReal);
+ type = p.isIntegral() ? ATInteger : ATReal;
}else{
- d_variableTypes.push_back(nodeToArithType(x));
+ type = nodeToArithType(x);
}
+ d_variableTypes[varX] = type;
+ d_slackVars[varX] = slack;
- d_slackVars.push_back(slack);
-
- d_simplex.increaseMax();
+ d_constraintDatabase.addVariable(varX);
d_arithvarNodeMap.setArithVar(x,varX);
- d_tableau.increaseSize();
- d_tableauSizeHasBeenModified = true;
+ // Debug("integers") << "isInteger[[" << x << "]]: " << x.getType().isInteger() << endl;
- d_constraintDatabase.addVariable(varX);
+ // if(slack){
+ // //The type computation is not quite accurate for Rationals that are integral.
+ // //We'll use the isIntegral check from the polynomial package instead.
+ // Polynomial p = Polynomial::parsePolynomial(x);
+ // d_variableTypes.push_back(p.isIntegral() ? ATInteger : ATReal);
+ // }else{
+ // d_variableTypes.push_back(nodeToArithType(x));
+ // }
+
+ // d_slackVars.push_back(slack);
+
+ // d_simplex.increaseMax();
+
+ // d_tableau.increaseSize();
+ // d_tableauSizeHasBeenModified = true;
+
+ // d_constraintDatabase.addVariable(varX);
Debug("arith::arithvar") << x << " |-> " << varX << endl;
+ Assert(!d_partialModel.hasUpperBound(varX));
+ Assert(!d_partialModel.hasLowerBound(varX));
+
return varX;
}
@@ -1179,18 +1234,7 @@ void TheoryArith::asVectors(const Polynomial& p, std::vector<Rational>& coeffs,
Assert(theoryOf(n) != THEORY_ARITH || d_arithvarNodeMap.hasArithVar(n));
Assert(d_arithvarNodeMap.hasArithVar(n));
- ArithVar av;
- // The first if is likely dead is likely dead code:
- // if (theoryOf(n) != THEORY_ARITH && !d_arithvarNodeMap.hasArithVar(n)) {
- // // The only way not to get it through pre-register is if it's a foreign term
- // ++(d_statistics.d_statUserVariables);
- // av = requestArithVar(n,false);
- // setupInitialValue(av);
- // } else {
- // // Otherwise, we already have it's variable
- // av = d_arithvarNodeMap.asArithVar(n);
- // }
- av = d_arithvarNodeMap.asArithVar(n);
+ ArithVar av = d_arithvarNodeMap.asArithVar(n);
coeffs.push_back(constant.getValue());
variables.push_back(av);
@@ -1200,11 +1244,12 @@ void TheoryArith::asVectors(const Polynomial& p, std::vector<Rational>& coeffs,
/* Requirements:
* For basic variables the row must have been added to the tableau.
*/
-void TheoryArith::setupInitialValue(ArithVar x){
+void TheoryArith::setupBasicValue(ArithVar x){
+ Assert(d_tableau.isBasic(x));
- if(!d_tableau.isBasic(x)){
- d_partialModel.initialize(x, d_DELTA_ZERO);
- }else{
+ // if(!d_tableau.isBasic(x)){
+ // d_partialModel.setAssignment(x, d_DELTA_ZERO, d_DELTA_ZERO);
+ // }else{
//If the variable is basic, assertions may have already happened and updates
//may have occured before setting this variable up.
@@ -1212,9 +1257,11 @@ void TheoryArith::setupInitialValue(ArithVar x){
//time instead of register
DeltaRational safeAssignment = d_linEq.computeRowValue(x, true);
DeltaRational assignment = d_linEq.computeRowValue(x, false);
- d_partialModel.initialize(x,safeAssignment);
- d_partialModel.setAssignment(x,assignment);
- }
+ //d_partialModel.initialize(x,safeAssignment);
+ //d_partialModel.setAssignment(x,assignment);
+ d_partialModel.setAssignment(x,safeAssignment,assignment);
+
+ // }
Debug("arith") << "setupVariable("<<x<<")"<<std::endl;
}
@@ -1254,8 +1301,8 @@ Node TheoryArith::dioCutting(){
context::Context::ScopedPush speculativePush(getSatContext());
//DO NOT TOUCH THE OUTPUTSTREAM
- //TODO: Improve this
- for(ArithVar v = 0, end = d_variables.size(); v != end; ++v){
+ for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+ ArithVar v = *vi;
if(isInteger(v)){
const DeltaRational& dr = d_partialModel.getAssignment(v);
if(d_partialModel.equalsUpperBound(v, dr) || d_partialModel.equalsLowerBound(v, dr)){
@@ -1369,7 +1416,7 @@ Constraint TheoryArith::constraintFromFactQueue(){
if(assertion != reAssertion){
Debug("arith::nf") << "getting non-nf assertion " << assertion << " |-> " << reAssertion << endl;
Assert(constraint != NullConstraint);
- d_assertionsThatDoNotMatchTheirLiterals[assertion] = constraint;
+ d_assertionsThatDoNotMatchTheirLiterals.insert(assertion, constraint);
}
}
@@ -1485,7 +1532,8 @@ bool TheoryArith::assertionCases(Constraint constraint){
* If this returns true, all integer variables have an integer assignment.
*/
bool TheoryArith::hasIntegerModel(){
- if(d_variables.size() > 0){
+ //if(d_variables.size() > 0){
+ if(getNumberOfVariables()){
const ArithVar rrEnd = d_nextIntegerCheckVar;
do {
//Do not include slack variables
@@ -1495,7 +1543,7 @@ bool TheoryArith::hasIntegerModel(){
return false;
}
}
- } while((d_nextIntegerCheckVar = (1 + d_nextIntegerCheckVar == d_variables.size() ? 0 : 1 + d_nextIntegerCheckVar)) != rrEnd);
+ } while((d_nextIntegerCheckVar = (1 + d_nextIntegerCheckVar == getNumberOfVariables() ? 0 : 1 + d_nextIntegerCheckVar)) != rrEnd);
}
return true;
}
@@ -1576,6 +1624,7 @@ void TheoryArith::check(Effort effortLevel){
Assert(d_conflicts.empty());
d_qflraStatus = d_simplex.findModel(fullEffort(effortLevel));
+
switch(d_qflraStatus){
case Result::SAT:
if(newFacts){
@@ -1682,6 +1731,20 @@ void TheoryArith::check(Effort effortLevel){
}
Assert( d_currentPropagationList.empty());
+ if(!emmittedConflictOrSplit && fullEffort(effortLevel)){
+ ++d_fullCheckCounter;
+ }
+ static const int CUT_ALL_BOUNDED_PERIOD = 10;
+ if(!emmittedConflictOrSplit && fullEffort(effortLevel) &&
+ d_fullCheckCounter % CUT_ALL_BOUNDED_PERIOD == 1){
+ vector<Node> lemmas = cutAllBounded();
+ //output the lemmas
+ for(vector<Node>::const_iterator i = lemmas.begin(); i != lemmas.end(); ++i){
+ d_out->lemma(*i);
+ ++(d_statistics.d_externalBranchAndBounds);
+ }
+ emmittedConflictOrSplit = lemmas.size() > 0;
+ }
if(!emmittedConflictOrSplit && fullEffort(effortLevel)){
emmittedConflictOrSplit = splitDisequalities();
@@ -1728,6 +1791,55 @@ void TheoryArith::check(Effort effortLevel){
Debug("arith") << "TheoryArith::check end" << std::endl;
}
+Node TheoryArith::branchIntegerVariable(ArithVar x) const {
+ const DeltaRational& d = d_partialModel.getAssignment(x);
+ Assert(!d.isIntegral());
+ const Rational& r = d.getNoninfinitesimalPart();
+ const Rational& i = d.getInfinitesimalPart();
+ Trace("integers") << "integers: assignment to [[" << d_arithvarNodeMap.asNode(x) << "]] is " << r << "[" << i << "]" << endl;
+
+ Assert(! (r.getDenominator() == 1 && i.getNumerator() == 0));
+ Assert(!d.isIntegral());
+ TNode var = d_arithvarNodeMap.asNode(x);
+ Integer floor_d = d.floor();
+
+ Node ub = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::LEQ, var, mkRationalNode(floor_d)));
+ Node lb = ub.notNode();
+
+
+ Node lem = NodeManager::currentNM()->mkNode(kind::OR, ub, lb);
+ Trace("integers") << "integers: branch & bound: " << lem << endl;
+ if(d_valuation.isSatLiteral(lem[0])) {
+ Debug("integers") << " " << lem[0] << " == " << d_valuation.getSatValue(lem[0]) << endl;
+ } else {
+ Debug("integers") << " " << lem[0] << " is not assigned a SAT literal" << endl;
+ }
+ if(d_valuation.isSatLiteral(lem[1])) {
+ Debug("integers") << " " << lem[1] << " == " << d_valuation.getSatValue(lem[1]) << endl;
+ } else {
+ Debug("integers") << " " << lem[1] << " is not assigned a SAT literal" << endl;
+ }
+ return lem;
+}
+
+std::vector<Node> TheoryArith::cutAllBounded() const{
+ vector<Node> lemmas;
+ if(options::doCutAllBounded() && getNumberOfVariables() > 0){
+ for(ArithVar iter = 0; iter != getNumberOfVariables(); ++iter){
+ //Do not include slack variables
+ const DeltaRational& d = d_partialModel.getAssignment(iter);
+ if(isInteger(iter) && !isSlackVariable(iter) &&
+ d_partialModel.hasUpperBound(iter) &&
+ d_partialModel.hasLowerBound(iter) &&
+ !d.isIntegral()){
+ Node lem = branchIntegerVariable(iter);
+ lemmas.push_back(lem);
+ }
+ }
+ }
+ return lemmas;
+}
+
/** Returns true if the roundRobinBranching() issues a lemma. */
Node TheoryArith::roundRobinBranch(){
if(hasIntegerModel()){
@@ -1737,36 +1849,40 @@ Node TheoryArith::roundRobinBranch(){
Assert(isInteger(v));
Assert(!isSlackVariable(v));
+ return branchIntegerVariable(v);
- const DeltaRational& d = d_partialModel.getAssignment(v);
- const Rational& r = d.getNoninfinitesimalPart();
- const Rational& i = d.getInfinitesimalPart();
- Trace("integers") << "integers: assignment to [[" << d_arithvarNodeMap.asNode(v) << "]] is " << r << "[" << i << "]" << endl;
+ // Assert(isInteger(v));
+ // Assert(!isSlackVariable(v));
- Assert(! (r.getDenominator() == 1 && i.getNumerator() == 0));
- Assert(!d.isIntegral());
+ // const DeltaRational& d = d_partialModel.getAssignment(v);
+ // const Rational& r = d.getNoninfinitesimalPart();
+ // const Rational& i = d.getInfinitesimalPart();
+ // Trace("integers") << "integers: assignment to [[" << d_arithvarNodeMap.asNode(v) << "]] is " << r << "[" << i << "]" << endl;
- TNode var = d_arithvarNodeMap.asNode(v);
- Integer floor_d = d.floor();
- Integer ceil_d = d.ceiling();
+ // Assert(! (r.getDenominator() == 1 && i.getNumerator() == 0));
+ // Assert(!d.isIntegral());
- Node leq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::LEQ, var, mkRationalNode(floor_d)));
- Node geq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::GEQ, var, mkRationalNode(ceil_d)));
+ // TNode var = d_arithvarNodeMap.asNode(v);
+ // Integer floor_d = d.floor();
+ // Integer ceil_d = d.ceiling();
+ // Node leq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::LEQ, var, mkRationalNode(floor_d)));
+ // Node geq = Rewriter::rewrite(NodeManager::currentNM()->mkNode(kind::GEQ, var, mkRationalNode(ceil_d)));
- Node lem = NodeManager::currentNM()->mkNode(kind::OR, leq, geq);
- Trace("integers") << "integers: branch & bound: " << lem << endl;
- if(d_valuation.isSatLiteral(lem[0])) {
- Debug("integers") << " " << lem[0] << " == " << d_valuation.getSatValue(lem[0]) << endl;
- } else {
- Debug("integers") << " " << lem[0] << " is not assigned a SAT literal" << endl;
- }
- if(d_valuation.isSatLiteral(lem[1])) {
- Debug("integers") << " " << lem[1] << " == " << d_valuation.getSatValue(lem[1]) << endl;
- } else {
- Debug("integers") << " " << lem[1] << " is not assigned a SAT literal" << endl;
- }
- return lem;
+
+ // Node lem = NodeManager::currentNM()->mkNode(kind::OR, leq, geq);
+ // Trace("integers") << "integers: branch & bound: " << lem << endl;
+ // if(d_valuation.isSatLiteral(lem[0])) {
+ // Debug("integers") << " " << lem[0] << " == " << d_valuation.getSatValue(lem[0]) << endl;
+ // } else {
+ // Debug("integers") << " " << lem[0] << " is not assigned a SAT literal" << endl;
+ // }
+ // if(d_valuation.isSatLiteral(lem[1])) {
+ // Debug("integers") << " " << lem[1] << " == " << d_valuation.getSatValue(lem[1]) << endl;
+ // } else {
+ // Debug("integers") << " " << lem[1] << " is not assigned a SAT literal" << endl;
+ // }
+ // return lem;
}
}
@@ -1822,7 +1938,8 @@ bool TheoryArith::splitDisequalities(){
*/
void TheoryArith::debugPrintAssertions() {
Debug("arith::print_assertions") << "Assertions:" << endl;
- for (ArithVar i = 0; i < d_variables.size(); ++ i) {
+ for (var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+ ArithVar i = *vi;
if (d_partialModel.hasLowerBound(i)) {
Constraint lConstr = d_partialModel.getLowerBoundConstraint(i);
Debug("arith::print_assertions") << lConstr << endl;
@@ -1842,13 +1959,15 @@ void TheoryArith::debugPrintAssertions() {
void TheoryArith::debugPrintModel(){
Debug("arith::print_model") << "Model:" << endl;
-
- for (ArithVar i = 0; i < d_variables.size(); ++ i) {
- Debug("arith::print_model") << d_variables[i] << " : " <<
- d_partialModel.getAssignment(i);
- if(d_tableau.isBasic(i))
- Debug("arith::print_model") << " (basic)";
- Debug("arith::print_model") << endl;
+ for (var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+ ArithVar i = *vi;
+ if(d_arithvarNodeMap.hasNode(i)){
+ Debug("arith::print_model") << d_arithvarNodeMap.asNode(i) << " : " <<
+ d_partialModel.getAssignment(i);
+ if(d_tableau.isBasic(i))
+ Debug("arith::print_model") << " (basic)";
+ Debug("arith::print_model") << endl;
+ }
}
}
@@ -2057,7 +2176,8 @@ Rational TheoryArith::deltaValueForTotalOrder() const{
relevantDeltaValues.insert(val);
}
- for(ArithVar v = 0; v < d_variables.size(); ++v){
+ for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+ ArithVar v = *vi;
const DeltaRational& value = d_partialModel.getAssignment(v);
relevantDeltaValues.insert(value);
if( d_partialModel.hasLowerBound(v)){
@@ -2108,7 +2228,8 @@ void TheoryArith::collectModelInfo( TheoryModel* m, bool fullModel ){
// TODO:
// This is not very good for user push/pop....
// Revisit when implementing push/pop
- for(ArithVar v = 0; v < d_variables.size(); ++v){
+ for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+ ArithVar v = *vi;
if(!isSlackVariable(v)){
Node term = d_arithvarNodeMap.asNode(v);
@@ -2187,13 +2308,13 @@ void TheoryArith::notifyRestart(){
}
bool TheoryArith::entireStateIsConsistent(const string& s){
- typedef std::vector<Node>::const_iterator VarIter;
bool result = true;
- for(VarIter i = d_variables.begin(), end = d_variables.end(); i != end; ++i){
- ArithVar var = d_arithvarNodeMap.asArithVar(*i);
+ for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+ ArithVar var = *vi;
+ //ArithVar var = d_arithvarNodeMap.asArithVar(*i);
if(!d_partialModel.assignmentIsConsistent(var)){
d_partialModel.printModel(var);
- Warning() << s << ":" << "Assignment is not consistent for " << var << *i;
+ Warning() << s << ":" << "Assignment is not consistent for " << var << d_arithvarNodeMap.asNode(var);
if(d_tableau.isBasic(var)){
Warning() << " (basic)";
}
@@ -2205,15 +2326,14 @@ bool TheoryArith::entireStateIsConsistent(const string& s){
}
bool TheoryArith::unenqueuedVariablesAreConsistent(){
- typedef std::vector<Node>::const_iterator VarIter;
bool result = true;
- for(VarIter i = d_variables.begin(), end = d_variables.end(); i != end; ++i){
- ArithVar var = d_arithvarNodeMap.asArithVar(*i);
+ for(var_iterator vi = var_begin(), vend = var_end(); vi != vend; ++vi){
+ ArithVar var = *vi;
if(!d_partialModel.assignmentIsConsistent(var)){
if(!d_simplex.debugIsInCollectionQueue(var)){
d_partialModel.printModel(var);
- Warning() << "Unenqueued var is not consistent for " << var << *i;
+ Warning() << "Unenqueued var is not consistent for " << var << d_arithvarNodeMap.asNode(var);
if(d_tableau.isBasic(var)){
Warning() << " (basic)";
}
@@ -2221,7 +2341,7 @@ bool TheoryArith::unenqueuedVariablesAreConsistent(){
result = false;
} else if(Debug.isOn("arith::consistency::initial")){
d_partialModel.printModel(var);
- Warning() << "Initial var is not consistent for " << var << *i;
+ Warning() << "Initial var is not consistent for " << var << d_arithvarNodeMap.asNode(var);
if(d_tableau.isBasic(var)){
Warning() << " (basic)";
}
diff --git a/src/theory/arith/theory_arith.h b/src/theory/arith/theory_arith.h
index 6a83c501b..31f9bfcaf 100644
--- a/src/theory/arith/theory_arith.h
+++ b/src/theory/arith/theory_arith.h
@@ -22,6 +22,7 @@
#include "context/context.h"
#include "context/cdlist.h"
#include "context/cdhashset.h"
+#include "context/cdinsert_hashmap.h"
#include "context/cdqueue.h"
#include "expr/node.h"
@@ -88,17 +89,20 @@ private:
/** Static learner. */
ArithStaticLearner d_learner;
- /**
- * List of the variables in the system.
- * This is needed to keep a positive ref count on slack variables.
- */
- std::vector<Node> d_variables;
+
+ ArithVar d_numberOfVariables;
+ inline ArithVar getNumberOfVariables() const { return d_numberOfVariables; }
+ std::vector<ArithVar> d_pool;
+ void releaseArithVar(ArithVar v);
/**
* The map between arith variables to nodes.
*/
ArithVarNodeMap d_arithvarNodeMap;
+ typedef ArithVarNodeMap::var_iterator var_iterator;
+ var_iterator var_begin() const { return d_arithvarNodeMap.var_begin(); }
+ var_iterator var_end() const { return d_arithvarNodeMap.var_end(); }
NodeSet d_setupNodes;
bool isSetup(Node n) const {
@@ -135,7 +139,7 @@ private:
* A superset of all of the assertions that currently are not the literal for
* their constraint do not match constraint literals. Not just the witnesses.
*/
- context::CDHashMap<TNode, Constraint, TNodeHashFunction> d_assertionsThatDoNotMatchTheirLiterals;
+ context::CDInsertHashMap<Node, Constraint, NodeHashFunction> d_assertionsThatDoNotMatchTheirLiterals;
/**
* (For the moment) the type hierarchy goes as:
@@ -272,6 +276,18 @@ private:
void outputConflicts();
+ class TempVarMalloc : public ArithVarMalloc {
+ private:
+ TheoryArith& d_ta;
+ public:
+ TempVarMalloc(TheoryArith& ta) : d_ta(ta) {}
+ ArithVar request(){
+ Node skolem = mkRealSkolem("tmpVar");
+ return d_ta.requestArithVar(skolem, false);
+ }
+ void release(ArithVar v){ d_ta.releaseArithVar(v); }
+ } d_tempVarMalloc;
+
/**
* A copy of the tableau.
* This is equivalent to the original tableau if d_tableauSizeHasBeenModified
@@ -432,7 +448,7 @@ private:
ArithVar requestArithVar(TNode x, bool slack);
/** Initial (not context dependent) sets up for a variable.*/
- void setupInitialValue(ArithVar x);
+ void setupBasicValue(ArithVar x);
/** Initial (not context dependent) sets up for a new slack variable.*/
void setupSlack(TNode left);
@@ -521,6 +537,11 @@ private:
/** Debugging only routine. Prints the model. */
void debugPrintModel();
+ /** Counts the number of fullCheck calls to arithmetic. */
+ uint32_t d_fullCheckCounter;
+ std::vector<Node> cutAllBounded() const;
+ Node branchIntegerVariable(ArithVar x) const;
+
/** These fields are designed to be accessible to TheoryArith methods. */
class Statistics {
public:
diff --git a/src/theory/arrays/theory_arrays.cpp b/src/theory/arrays/theory_arrays.cpp
index a05d30517..aabd3a62d 100644
--- a/src/theory/arrays/theory_arrays.cpp
+++ b/src/theory/arrays/theory_arrays.cpp
@@ -537,7 +537,7 @@ EqualityStatus TheoryArrays::getEqualityStatus(TNode a, TNode b) {
void TheoryArrays::computeCareGraph()
{
if (d_sharedArrays.size() > 0) {
- context::CDHashSet<TNode, TNodeHashFunction>::iterator it1 = d_sharedArrays.begin(), it2, iend = d_sharedArrays.end();
+ CDNodeSet::key_iterator it1 = d_sharedArrays.key_begin(), it2, iend = d_sharedArrays.key_end();
for (; it1 != iend; ++it1) {
for (it2 = it1, ++it2; it2 != iend; ++it2) {
if ((*it1).getType() != (*it2).getType()) {
@@ -1261,7 +1261,7 @@ void TheoryArrays::checkRowLemmas(TNode a, TNode b)
void TheoryArrays::queueRowLemma(RowLemmaType lem)
{
- if (d_conflict || d_RowAlreadyAdded.count(lem) != 0) {
+ if (d_conflict || d_RowAlreadyAdded.contains(lem)) {
return;
}
TNode a = lem.first;
@@ -1407,7 +1407,7 @@ void TheoryArrays::dischargeLemmas()
for (unsigned count = 0; count < sz; ++count) {
RowLemmaType l = d_RowQueue.front();
d_RowQueue.pop();
- if (d_RowAlreadyAdded.count(l) != 0) {
+ if (d_RowAlreadyAdded.contains(l)) {
continue;
}
diff --git a/src/theory/arrays/theory_arrays.h b/src/theory/arrays/theory_arrays.h
index 240cfad9a..172482e71 100644
--- a/src/theory/arrays/theory_arrays.h
+++ b/src/theory/arrays/theory_arrays.h
@@ -333,8 +333,10 @@ class TheoryArrays : public Theory {
context::CDQueue<RowLemmaType> d_RowQueue;
context::CDHashSet<RowLemmaType, RowLemmaTypeHashFunction > d_RowAlreadyAdded;
- context::CDHashSet<TNode, TNodeHashFunction> d_sharedArrays;
- context::CDHashSet<TNode, TNodeHashFunction> d_sharedOther;
+ typedef context::CDHashSet<Node, NodeHashFunction> CDNodeSet;
+
+ CDNodeSet d_sharedArrays;
+ CDNodeSet d_sharedOther;
context::CDO<bool> d_sharedTerms;
context::CDList<TNode> d_reads;
std::hash_map<TNode, Node, TNodeHashFunction> d_diseqCache;
diff --git a/src/theory/arrays/theory_arrays_model.h b/src/theory/arrays/theory_arrays_model.h
index 4825c710d..c82c7635d 100644
--- a/src/theory/arrays/theory_arrays_model.h
+++ b/src/theory/arrays/theory_arrays_model.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file theory_arrays_model.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/booleans/circuit_propagator.h b/src/theory/booleans/circuit_propagator.h
index e62f9b7a1..de4bb30d2 100644
--- a/src/theory/booleans/circuit_propagator.h
+++ b/src/theory/booleans/circuit_propagator.h
@@ -64,6 +64,8 @@ public:
else return ASSIGNED_TO_TRUE;
}
+ typedef std::hash_map<Node, std::vector<Node>, NodeHashFunction> BackEdgesMap;
+
private:
context::Context d_context;
@@ -96,7 +98,7 @@ private:
*/
DataClearer< std::vector<TNode> > d_propagationQueueClearer;
- /** Are we in conflict */
+ /** Are we in conflict? */
context::CDO<bool> d_conflict;
/** Map of substitutions */
@@ -107,8 +109,9 @@ private:
*/
DataClearer< std::vector<Node> > d_learnedLiteralClearer;
- /** Back edges from nodes to where they are used */
- typedef std::hash_map<Node, std::vector<Node>, NodeHashFunction> BackEdgesMap;
+ /**
+ * Back edges from nodes to where they are used.
+ */
BackEdgesMap d_backEdges;
/**
@@ -118,7 +121,7 @@ private:
/** Nodes that have been attached already (computed forward edges for) */
// All the nodes we've visited so far
- context::CDHashSet<TNode, TNodeHashFunction> d_seen;
+ context::CDHashSet<Node, NodeHashFunction> d_seen;
/**
* Assignment status of each node.
@@ -157,6 +160,7 @@ private:
}
}
+public:
/** True iff Node is assigned in circuit (either true or false). */
bool isAssigned(TNode n) const {
AssignmentMap::const_iterator i = d_state.find(n);
@@ -179,6 +183,7 @@ private:
return (*i).second == ASSIGNED_TO_TRUE;
}
+private:
/** Predicate for use in STL functions. */
class IsAssigned : public std::unary_function<TNode, bool> {
CircuitPropagator& d_circuit;
@@ -268,6 +273,13 @@ public:
*/
bool propagate() CVC4_WARN_UNUSED_RESULT;
+ /**
+ * Get the back edges of this circuit.
+ */
+ const BackEdgesMap& getBackEdges() const {
+ return d_backEdges;
+ }
+
};/* class CircuitPropagator */
}/* CVC4::theory::booleans namespace */
diff --git a/src/theory/bv/theory_bv.h b/src/theory/bv/theory_bv.h
index 0c8df3fca..e38f3568c 100644
--- a/src/theory/bv/theory_bv.h
+++ b/src/theory/bv/theory_bv.h
@@ -40,8 +40,8 @@ class TheoryBV : public Theory {
context::Context* d_context;
/** Context dependent set of atoms we already propagated */
- context::CDHashSet<TNode, TNodeHashFunction> d_alreadyPropagatedSet;
- context::CDHashSet<TNode, TNodeHashFunction> d_sharedTermsSet;
+ context::CDHashSet<Node, NodeHashFunction> d_alreadyPropagatedSet;
+ context::CDHashSet<Node, NodeHashFunction> d_sharedTermsSet;
BitblastSolver d_bitblastSolver;
EqualitySolver d_equalitySolver;
diff --git a/src/theory/bv/theory_bv_rewrite_rules_simplification.h b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
index a8aef748b..9d1cafab9 100644
--- a/src/theory/bv/theory_bv_rewrite_rules_simplification.h
+++ b/src/theory/bv/theory_bv_rewrite_rules_simplification.h
@@ -430,10 +430,6 @@ Node RewriteRule<BitwiseNotOr>::apply(TNode node) {
template<> inline
bool RewriteRule<XorNot>::applies(TNode node) {
Unreachable();
- if (node.getKind() == kind::BITVECTOR_XOR &&
- node.getNumChildren() == 2 &&
- node[0].getKind() == kind::BITVECTOR_NOT &&
- node[1].getKind() == kind::BITVECTOR_NOT);
}
template<> inline
diff --git a/src/theory/datatypes/options b/src/theory/datatypes/options
index d250bee74..1daa30981 100644
--- a/src/theory/datatypes/options
+++ b/src/theory/datatypes/options
@@ -11,7 +11,7 @@ module DATATYPES "theory/datatypes/options.h" Datatypes theory
# cdr( nil ) has no set value.
expert-option dtRewriteErrorSel /--disable-dt-rewrite-error-sel bool :default true
disable rewriting incorrectly applied selectors to arbitrary ground term
-expert-option dtForceAssignment /--dt-force-assignment bool :default false :read-write
+option dtForceAssignment /--dt-force-assignment bool :default false :read-write
force the datatypes solver to give specific values to all datatypes terms before answering sat
endmodule
diff --git a/src/theory/quantifiers/first_order_model.cpp b/src/theory/quantifiers/first_order_model.cpp
index 3d98674a8..8272ce168 100644
--- a/src/theory/quantifiers/first_order_model.cpp
+++ b/src/theory/quantifiers/first_order_model.cpp
@@ -42,10 +42,6 @@ void FirstOrderModel::reset(){
TheoryModel::reset();
}
-void FirstOrderModel::addTerm( Node n ){
- TheoryModel::addTerm( n );
-}
-
void FirstOrderModel::initialize( bool considerAxioms ){
//rebuild models
d_uf_model_tree.clear();
diff --git a/src/theory/quantifiers/first_order_model.h b/src/theory/quantifiers/first_order_model.h
index 3779579fd..50a941968 100644
--- a/src/theory/quantifiers/first_order_model.h
+++ b/src/theory/quantifiers/first_order_model.h
@@ -33,8 +33,6 @@ class TermDb;
class FirstOrderModel : public TheoryModel
{
private:
- //add term function
- void addTerm( Node n );
//for initialize model
void initializeModelForTerm( Node n );
/** whether an axiom is asserted */
diff --git a/src/theory/quantifiers/inst_gen.cpp b/src/theory/quantifiers/inst_gen.cpp
index b5f92c5f8..dea371e9c 100755..100644
--- a/src/theory/quantifiers/inst_gen.cpp
+++ b/src/theory/quantifiers/inst_gen.cpp
@@ -1,13 +1,11 @@
/********************* */
/*! \file inst_gen.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/inst_gen.h b/src/theory/quantifiers/inst_gen.h
index c8de2c642..94922df18 100755..100644
--- a/src/theory/quantifiers/inst_gen.h
+++ b/src/theory/quantifiers/inst_gen.h
@@ -1,13 +1,11 @@
/********************* */
/*! \file inst_gen.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 The Analysis of Computer Systems Group (ACSys)
- ** Courant Institute of Mathematical Sciences
- ** New York University
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/inst_match_generator.cpp b/src/theory/quantifiers/inst_match_generator.cpp
index 2822597e1..386834385 100755..100644
--- a/src/theory/quantifiers/inst_match_generator.cpp
+++ b/src/theory/quantifiers/inst_match_generator.cpp
@@ -1,15 +1,16 @@
/********************* */
/*! \file inst_match_generator.cpp
-** \verbatim
-** Original author: ajreynol
-** Major contributors: bobot
-** Minor contributors (to current version): barrett, mdeters
-** This file is part of the CVC4 prototype.
-** Copyright (c) 2009-2012 New York University and The University of Iowa
-** See the file COPYING in the top-level source directory for licensing
-** information.\endverbatim
-**
-** \brief Implementation of inst match generator class
+ ** \verbatim
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
+ ** See the file COPYING in the top-level source directory for licensing
+ ** information.\endverbatim
+ **
+ ** [[ Add lengthier description here ]]
+ ** \todo document this file
**/
#include "theory/quantifiers/inst_match_generator.h"
@@ -29,116 +30,111 @@ namespace theory {
namespace inst {
-InstMatchGenerator::InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
- initializePattern( pat, qe );
-}
-
-InstMatchGenerator::InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchPolicy ) : d_matchPolicy( matchPolicy ){
- if( pats.size()==1 ){
- initializePattern( pats[0], qe );
- }else{
- initializePatterns( pats, qe );
- }
+InstMatchGenerator::InstMatchGenerator( Node pat, int matchPolicy ) : d_matchPolicy( matchPolicy ){
+ d_active_add = false;
+ Assert( pat.hasAttribute(InstConstantAttribute()) );
+ d_pattern = pat;
+ d_match_pattern = pat;
+ d_next = NULL;
}
-void InstMatchGenerator::initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe ){
- int childMatchPolicy = d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ? 0 : d_matchPolicy;
- for( int i=0; i<(int)pats.size(); i++ ){
- d_children.push_back( new InstMatchGenerator( pats[i], qe, childMatchPolicy ) );
+void InstMatchGenerator::setActiveAdd(){
+ d_active_add = true;
+ if( d_next!=NULL ){
+ d_next->setActiveAdd();
}
- d_pattern = Node::null();
- d_match_pattern = Node::null();
- d_cg = NULL;
}
-void InstMatchGenerator::initializePattern( Node pat, QuantifiersEngine* qe ){
- Debug("inst-match-gen") << "Pattern term is " << pat << std::endl;
- Assert( pat.hasAttribute(InstConstantAttribute()) );
- d_pattern = pat;
- d_match_pattern = pat;
- if( d_match_pattern.getKind()==NOT ){
- //we want to add the children of the NOT
- d_match_pattern = d_pattern[0];
- }
- if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
- if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
- Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
- //swap sides
- d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
- d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
- d_match_pattern = d_match_pattern[1];
- }else{
- d_match_pattern = d_pattern[0][0];
- }
- }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
- Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
- if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
- d_match_pattern = d_match_pattern[0];
+void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMatchGenerator * > & gens ){
+ if( !d_pattern.isNull() ){
+ Debug("inst-match-gen") << "Pattern term is " << d_pattern << std::endl;
+ if( d_match_pattern.getKind()==NOT ){
+ //we want to add the children of the NOT
+ d_match_pattern = d_pattern[0];
+ }
+ if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
+ if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
+ //swap sides
+ Node pat = d_pattern;
+ d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
+ d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
+ if( pat.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[1];
+ }else{
+ d_match_pattern = d_pattern[0][0];
+ }
+ }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
+ Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
+ if( d_pattern.getKind()!=NOT ){ //TEMPORARY until we do better implementation of disequality matching
+ d_match_pattern = d_match_pattern[0];
+ }
}
}
- }
- int childMatchPolicy = MATCH_GEN_DEFAULT;
- for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
- if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
- if( d_match_pattern[i].getKind()!=INST_CONSTANT ){
- d_children.push_back( new InstMatchGenerator( d_match_pattern[i], qe, childMatchPolicy ) );
- d_children_index.push_back( i );
+ int childMatchPolicy = MATCH_GEN_DEFAULT;
+ for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
+ if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
+ if( d_match_pattern[i].getKind()!=INST_CONSTANT ){
+ InstMatchGenerator * cimg = new InstMatchGenerator( d_match_pattern[i], childMatchPolicy );
+ d_children.push_back( cimg );
+ d_children_index.push_back( i );
+ gens.push_back( cimg );
+ }
}
}
- }
- Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
+ Debug("inst-match-gen") << "Pattern is " << d_pattern << ", match pattern is " << d_match_pattern << std::endl;
- //create candidate generator
- if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
- //we will be producing candidates via literal matching heuristics
- if( d_pattern.getKind()!=NOT ){
- //candidates will be all equalities
- d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
- }else{
- //candidates will be all disequalities
- d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
- }
- }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
- Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
- if( d_pattern.getKind()==NOT ){
- Unimplemented("Disequal generator unimplemented");
- }else{
- Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
- //we are matching only in a particular equivalence class
+ //create candidate generator
+ if( d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==IFF ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ //we will be producing candidates via literal matching heuristics
+ if( d_pattern.getKind()!=NOT ){
+ //candidates will be all equalities
+ d_cg = new inst::CandidateGeneratorQELitEq( qe, d_match_pattern );
+ }else{
+ //candidates will be all disequalities
+ d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
+ }
+ }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
+ Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
+ if( d_pattern.getKind()==NOT ){
+ Unimplemented("Disequal generator unimplemented");
+ }else{
+ Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
+ //we are matching only in a particular equivalence class
+ d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+ //store the equivalence class that we will call d_cg->reset( ... ) on
+ d_eq_class = d_pattern[1];
+ }
+ }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
+ //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
+ //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
+ //}
+ //we will be scanning lists trying to find d_match_pattern.getOperator()
d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
- //store the equivalence class that we will call d_cg->reset( ... ) on
- d_eq_class = d_pattern[1];
- }
- }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
- //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
- //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
- //}
- //we will be scanning lists trying to find d_match_pattern.getOperator()
- d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
- }else{
- d_cg = new CandidateGeneratorQueue;
- if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
- Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
- //Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
- d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
}else{
- Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;
- for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
- Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ d_cg = new CandidateGeneratorQueue;
+ if( !Trigger::getPatternArithmetic( d_match_pattern.getAttribute(InstConstantAttribute()), d_match_pattern, d_arith_coeffs ) ){
+ Debug("inst-match-gen") << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ //Warning() << "(?) Unknown matching pattern is " << d_match_pattern << std::endl;
+ d_matchPolicy = MATCH_GEN_INTERNAL_ERROR;
+ }else{
+ Debug("matching-arith") << "Generated arithmetic pattern for " << d_match_pattern << ": " << std::endl;
+ for( std::map< Node, Node >::iterator it = d_arith_coeffs.begin(); it != d_arith_coeffs.end(); ++it ){
+ Debug("matching-arith") << " " << it->first << " -> " << it->second << std::endl;
+ }
+ //we will treat this as match gen internal arithmetic
+ d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;
}
- //we will treat this as match gen internal arithmetic
- d_matchPolicy = MATCH_GEN_INTERNAL_ARITHMETIC;
}
}
}
/** get match (not modulo equality) */
-bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe ){
+bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe ){
Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
- << m.size() << ")" << ", " << d_children.size() << std::endl;
+ << m << ")" << ", " << d_children.size() << std::endl;
Assert( !d_match_pattern.isNull() );
if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
return true;
@@ -148,9 +144,8 @@ bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe )
return false;
}else{
EqualityQuery* q = qe->getEqualityQuery();
- //add m to partial match vector
- std::vector< InstMatch > partial;
- partial.push_back( InstMatch( &m ) );
+ //save previous match
+ InstMatch prev( &m );
//if t is null
Assert( !t.isNull() );
Assert( !t.hasAttribute(InstConstantAttribute()) );
@@ -160,13 +155,13 @@ bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe )
for( int i=0; i<(int)d_match_pattern.getNumChildren(); i++ ){
if( d_match_pattern[i].hasAttribute(InstConstantAttribute()) ){
if( d_match_pattern[i].getKind()==INST_CONSTANT ){
- if( !partial[0].setMatch( q, d_match_pattern[i], t[i] ) ){
+ if( !m.setMatch( q, d_match_pattern[i], t[i] ) ){
//match is in conflict
Debug("matching-debug") << "Match in conflict " << t[i] << " and "
<< d_match_pattern[i] << " because "
- << partial[0].get(d_match_pattern[i])
+ << m.get(d_match_pattern[i])
<< std::endl;
- Debug("matching-fail") << "Match fail: " << partial[0].get(d_match_pattern[i]) << " and " << t[i] << std::endl;
+ Debug("matching-fail") << "Match fail: " << m.get(d_match_pattern[i]) << " and " << t[i] << std::endl;
return false;
}
}
@@ -184,48 +179,25 @@ bool InstMatchGenerator::getMatch( Node t, InstMatch& m, QuantifiersEngine* qe )
for( int i=0; i<(int)d_children.size(); i++ ){
Node rep = q->getRepresentative( t[ d_children_index[i] ] );
reps.push_back( rep );
- d_children[i]->d_cg->reset( rep );
+ d_children[i]->reset( rep, qe );
}
-
- //combine child matches
- int index = 0;
- while( index>=0 && index<(int)d_children.size() ){
- partial.push_back( InstMatch( &partial[index] ) );
- if( d_children[index]->getNextMatch2( partial[index+1], qe ) ){
- index++;
- }else{
- d_children[index]->d_cg->reset( reps[index] );
- partial.pop_back();
- if( !partial.empty() ){
- partial.pop_back();
- }
- index--;
+ bool success = true;
+ if( d_next!=NULL ){
+ success = d_next->getNextMatch( f, m, qe );
+ }else{
+ if( d_active_add ){
+ Trace("active-add") << "Active Adding instantiation " << m << std::endl;
+ success = qe->addInstantiation( f, m );
+ Trace("active-add") << "Success = " << success << std::endl;
}
}
- if( index>=0 ){
- m = partial.back();
- return true;
- }else{
- return false;
+ if( !success ){
+ m = InstMatch( &prev );
}
+ return success;
}
}
-bool InstMatchGenerator::getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched ){
- bool success = false;
- Node t;
- do{
- //get the next candidate term t
- t = d_cg->getNextCandidate();
- //if t not null, try to fit it into match m
- if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
- success = getMatch( t, m, qe );
- }
- }while( !success && !t.isNull() );
- if (saveMatched) m.d_matched = t;
- return success;
-}
-
bool InstMatchGenerator::getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe ){
Debug("matching-arith") << "Matching " << t << " " << d_match_pattern << std::endl;
if( !d_arith_coeffs.empty() ){
@@ -298,74 +270,57 @@ void InstMatchGenerator::resetInstantiationRound( QuantifiersEngine* qe ){
}
void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
- if( d_match_pattern.isNull() ){
- for( int i=0; i<(int)d_children.size(); i++ ){
- d_children[i]->reset( eqc, qe );
- }
- d_partial.clear();
- }else{
- if( !d_eq_class.isNull() ){
- //we have a specific equivalence class in mind
- //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
- //just look in equivalence class of the RHS
- d_cg->reset( d_eq_class );
- }else{
- d_cg->reset( eqc );
- }
+ if( !eqc.isNull() ){
+ d_eq_class = eqc;
}
+ //we have a specific equivalence class in mind
+ //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
+ //just look in equivalence class of the RHS
+ d_cg->reset( d_eq_class );
}
-bool InstMatchGenerator::getNextMatch( InstMatch& m, QuantifiersEngine* qe ){
+bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){
m.d_matched = Node::null();
- if( d_match_pattern.isNull() ){
- int index = (int)d_partial.size();
- while( index>=0 && index<(int)d_children.size() ){
- if( index>0 ){
- d_partial.push_back( InstMatch( &d_partial[index-1] ) );
- }else{
- d_partial.push_back( InstMatch() );
- }
- if( d_children[index]->getNextMatch( d_partial[index], qe ) ){
- index++;
- }else{
- d_children[index]->reset( Node::null(), qe );
- d_partial.pop_back();
- if( !d_partial.empty() ){
- d_partial.pop_back();
- }
- index--;
- }
- }
- if( index>=0 ){
- m = d_partial.back();
- d_partial.pop_back();
- return true;
- }else{
- return false;
+ //Debug("matching") << this << " " << d_pattern << " get next match 2 " << m << " in eq class " << d_eq_class << std::endl;
+ bool success = false;
+ Node t;
+ do{
+ //get the next candidate term t
+ t = d_cg->getNextCandidate();
+ //if t not null, try to fit it into match m
+ if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
+ success = getMatch( f, t, m, qe );
}
- }else{
- bool res = getNextMatch2( m, qe, true );
- Assert(!res || !m.d_matched.isNull());
- return res;
+ }while( !success && !t.isNull() );
+ m.d_matched = t;
+ if( !success ){
+ //Debug("matching") << this << " failed, reset " << d_eq_class << std::endl;
+ //we failed, must reset
+ reset( d_eq_class, qe );
}
+ return success;
}
int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
- //now, try to add instantiation for each match produced
+ //try to add instantiation for each match produced
int addedLemmas = 0;
InstMatch m;
- while( getNextMatch( m, qe ) ){
- //m.makeInternal( d_quantEngine->getEqualityQuery() );
- m.add( baseMatch );
- if( qe->addInstantiation( f, m ) ){
- addedLemmas++;
- if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
- return addedLemmas;
+ while( getNextMatch( f, m, qe ) ){
+ if( !d_active_add ){
+ //m.makeInternal( d_quantEngine->getEqualityQuery() );
+ m.add( baseMatch );
+ if( qe->addInstantiation( f, m ) ){
+ addedLemmas++;
+ if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
+ return addedLemmas;
+ }
}
+ m.clear();
+ }else{
+ addedLemmas++;
}
- m.clear();
}
//return number of lemmas added
return addedLemmas;
@@ -375,7 +330,7 @@ int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
Assert( options::eagerInstQuant() );
if( !d_match_pattern.isNull() ){
InstMatch m;
- if( getMatch( t, m, qe ) ){
+ if( getMatch( f, t, m, qe ) ){
if( qe->addInstantiation( f, m ) ){
return 1;
}
@@ -388,6 +343,40 @@ int InstMatchGenerator::addTerm( Node f, Node t, QuantifiersEngine* qe ){
return 0;
}
+
+InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( Node pat, QuantifiersEngine* qe ) {
+ std::vector< Node > pats;
+ pats.push_back( pat );
+ return mkInstMatchGenerator( pats, qe );
+}
+
+InstMatchGenerator* InstMatchGenerator::mkInstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe ) {
+ size_t pCounter = 0;
+ InstMatchGenerator* prev = NULL;
+ InstMatchGenerator* oinit = NULL;
+ while( pCounter<pats.size() ){
+ size_t counter = 0;
+ std::vector< InstMatchGenerator* > gens;
+ InstMatchGenerator* init = new InstMatchGenerator(pats[pCounter]);
+ if(pCounter==0){
+ oinit = init;
+ }
+ gens.push_back(init);
+ //chain the resulting match generators together
+ while (counter<gens.size()) {
+ InstMatchGenerator* curr = gens[counter];
+ if( prev ){
+ prev->d_next = curr;
+ }
+ curr->initialize(qe, gens);
+ prev = curr;
+ counter++;
+ }
+ pCounter++;
+ }
+ return oinit;
+}
+
/** constructors */
InstMatchGeneratorMulti::InstMatchGeneratorMulti( Node f, std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption ) :
d_f( f ){
@@ -408,7 +397,7 @@ d_f( f ){
for( int i=0; i<(int)pats.size(); i++ ){
Node n = pats[i];
//make the match generator
- d_children.push_back( new InstMatchGenerator( n, qe, matchOption ) );
+ d_children.push_back( InstMatchGenerator::mkInstMatchGenerator( n, qe ) );
//compute unique/shared variables
std::vector< int > unique_vars;
std::map< int, bool > shared_vars;
@@ -473,7 +462,7 @@ int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, Qu
Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
std::vector< InstMatch > newMatches;
InstMatch m;
- while( d_children[i]->getNextMatch( m, qe ) ){
+ while( d_children[i]->getNextMatch( f, m, qe ) ){
m.makeRepresentative( qe );
newMatches.push_back( InstMatch( &m ) );
m.clear();
@@ -595,7 +584,7 @@ int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
if( ((InstMatchGenerator*)d_children[i])->d_match_pattern.getOperator()==t.getOperator() ){
InstMatch m;
//if it produces a match, then process it with the rest
- if( ((InstMatchGenerator*)d_children[i])->getMatch( t, m, qe ) ){
+ if( ((InstMatchGenerator*)d_children[i])->getMatch( f, t, m, qe ) ){
processNewMatch( qe, m, i, addedLemmas );
}
}
diff --git a/src/theory/quantifiers/inst_match_generator.h b/src/theory/quantifiers/inst_match_generator.h
index dd3663e0a..b201fa60f 100755..100644
--- a/src/theory/quantifiers/inst_match_generator.h
+++ b/src/theory/quantifiers/inst_match_generator.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file inst_match_generator.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
@@ -38,11 +38,13 @@ public:
/** reset, eqc is the equivalence class to search in (any if eqc=null) */
virtual void reset( Node eqc, QuantifiersEngine* qe ) = 0;
/** get the next match. must call reset( eqc ) before this function. */
- virtual bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) = 0;
+ virtual bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) = 0;
/** add instantiations directly */
virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
/** add ground term t, called when t is added to term db */
virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;
+ /** set active add */
+ virtual void setActiveAdd() {}
};/* class IMGenerator */
class CandidateGenerator;
@@ -56,15 +58,14 @@ private:
/** children generators */
std::vector< InstMatchGenerator* > d_children;
std::vector< int > d_children_index;
- /** partial vector */
- std::vector< InstMatch > d_partial;
+ /** the next generator in order */
+ InstMatchGenerator* d_next;
/** eq class */
Node d_eq_class;
/** for arithmetic matching */
std::map< Node, Node > d_arith_coeffs;
/** initialize pattern */
- void initializePatterns( std::vector< Node >& pats, QuantifiersEngine* qe );
- void initializePattern( Node pat, QuantifiersEngine* qe );
+ void initialize( QuantifiersEngine* qe, std::vector< InstMatchGenerator * > & gens );
public:
enum {
//options for producing matches
@@ -75,10 +76,6 @@ public:
MATCH_GEN_INTERNAL_ERROR,
};
private:
- /** get the next match. must call d_cg->reset( ... ) before using.
- only valid for use where !d_match_pattern.isNull().
- */
- bool getNextMatch2( InstMatch& m, QuantifiersEngine* qe, bool saveMatched = false );
/** for arithmetic */
bool getMatchArithmetic( Node t, InstMatch& m, QuantifiersEngine* qe );
public:
@@ -86,11 +83,10 @@ public:
d_match_pattern and t should have the same shape.
only valid for use where !d_match_pattern.isNull().
*/
- bool getMatch( Node t, InstMatch& m, QuantifiersEngine* qe );
+ bool getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe );
/** constructors */
- InstMatchGenerator( Node pat, QuantifiersEngine* qe, int matchOption = 0 );
- InstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe, int matchOption = 0 );
+ InstMatchGenerator( Node pat, int matchOption = 0 );
/** destructor */
~InstMatchGenerator(){}
/** The pattern we are producing matches for.
@@ -105,11 +101,17 @@ public:
/** reset, eqc is the equivalence class to search in (any if eqc=null) */
void reset( Node eqc, QuantifiersEngine* qe );
/** get the next match. must call reset( eqc ) before this function. */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe );
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe );
/** add instantiations */
int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t */
int addTerm( Node f, Node t, QuantifiersEngine* qe );
+
+ bool d_active_add;
+ void setActiveAdd();
+
+ static InstMatchGenerator* mkInstMatchGenerator( Node pat, QuantifiersEngine* qe );
+ static InstMatchGenerator* mkInstMatchGenerator( std::vector< Node >& pats, QuantifiersEngine* qe );
};/* class InstMatchGenerator */
/** smart multi-trigger implementation */
@@ -152,7 +154,7 @@ public:
/** reset, eqc is the equivalence class to search in (any if eqc=null) */
void reset( Node eqc, QuantifiersEngine* qe );
/** get the next match. must call reset( eqc ) before this function. (not implemented) */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }
/** add instantiations */
int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t */
@@ -178,7 +180,7 @@ public:
/** reset, eqc is the equivalence class to search in (any if eqc=null) */
void reset( Node eqc, QuantifiersEngine* qe ) {}
/** get the next match. must call reset( eqc ) before this function. (not implemented) */
- bool getNextMatch( InstMatch& m, QuantifiersEngine* qe ) { return false; }
+ bool getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ) { return false; }
/** add instantiations */
int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t, possibly add instantiations */
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.cpp b/src/theory/quantifiers/inst_strategy_cbqi.cpp
index aba311500..b12fed619 100755..100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.cpp
+++ b/src/theory/quantifiers/inst_strategy_cbqi.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file inst_strategy_cbqi.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): bobot, mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
@@ -46,11 +46,12 @@ void InstStrategySimplex::processResetInstantiationRound( Theory::Effort effort
d_tableaux.clear();
d_ceTableaux.clear();
//search for instantiation rows in simplex tableaux
- ArithVarToNodeMap avtnm = d_th->d_arithvarNodeMap.getArithVarToNodeMap();
- for( ArithVarToNodeMap::iterator it = avtnm.begin(); it != avtnm.end(); ++it ){
- ArithVar x = (*it).first;
+ ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
+ ArithVarNodeMap::var_iterator vi, vend;
+ for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
+ ArithVar x = *vi;
if( d_th->d_partialModel.hasEitherBound( x ) ){
- Node n = (*it).second;
+ Node n = avnm.asNode(x);
Node f;
NodeBuilder<> t(kind::PLUS);
if( n.getKind()==PLUS ){
@@ -167,10 +168,11 @@ void InstStrategySimplex::addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder
}
void InstStrategySimplex::debugPrint( const char* c ){
- ArithVarToNodeMap avtnm = d_th->d_arithvarNodeMap.getArithVarToNodeMap();
- for( ArithVarToNodeMap::iterator it = avtnm.begin(); it != avtnm.end(); ++it ){
- ArithVar x = (*it).first;
- Node n = (*it).second;
+ const ArithVarNodeMap& avnm = d_th->d_arithvarNodeMap;
+ ArithVarNodeMap::var_iterator vi, vend;
+ for(vi = avnm.var_begin(), vend = avnm.var_end(); vi != vend; ++vi ){
+ ArithVar x = *vi;
+ Node n = avnm.asNode(x);
//if( ((TheoryArith*)getTheory())->d_partialModel.hasEitherBound( x ) ){
Debug(c) << x << " : " << n << ", bounds = ";
if( d_th->d_partialModel.hasLowerBound( x ) ){
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.h b/src/theory/quantifiers/inst_strategy_cbqi.h
index 1c9565de6..de548ab14 100755..100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.h
+++ b/src/theory/quantifiers/inst_strategy_cbqi.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file inst_strategy_cbqi.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.cpp b/src/theory/quantifiers/inst_strategy_e_matching.cpp
index edf9d976c..3f5cc7666 100755..100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.cpp
+++ b/src/theory/quantifiers/inst_strategy_e_matching.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file inst_strategy_e_matching.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: mdeters
- ** Minor contributors (to current version): bobot
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
@@ -27,7 +27,6 @@ using namespace CVC4::theory;
using namespace CVC4::theory::inst;
using namespace CVC4::theory::quantifiers;
-#define USE_SINGLE_TRIGGER_BEFORE_MULTI_TRIGGER
//#define MULTI_TRIGGER_FULL_EFFORT_HALF
#define MULTI_MULTI_TRIGGERS
@@ -65,18 +64,13 @@ int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
//Notice() << "Try user-provided patterns..." << std::endl;
for( int i=0; i<(int)d_user_gen[f].size(); i++ ){
bool processTrigger = true;
- if( effort!=Theory::EFFORT_LAST_CALL && d_user_gen[f][i]->isMultiTrigger() ){
-//#ifdef MULTI_TRIGGER_FULL_EFFORT_HALF
-// processTrigger = d_counter[f]%2==0;
-//#endif
- }
if( processTrigger ){
//if( d_user_gen[f][i]->isMultiTrigger() )
- //Notice() << " Process (user) " << (*d_user_gen[f][i]) << " for " << f << "..." << std::endl;
+ Trace("process-trigger") << " Process (user) " << (*d_user_gen[f][i]) << "..." << std::endl;
InstMatch baseMatch;
int numInst = d_user_gen[f][i]->addInstantiations( baseMatch );
//if( d_user_gen[f][i]->isMultiTrigger() )
- //Notice() << " Done, numInst = " << numInst << "." << std::endl;
+ Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;
d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_user_patterns += numInst;
if( d_user_gen[f][i]->isMultiTrigger() ){
d_quantEngine->d_statistics.d_multi_trigger_instantiations += numInst;
@@ -125,6 +119,7 @@ void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort
itt->first->reset( Node::null() );
}
}
+ d_processed_trigger.clear();
}
int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
@@ -134,6 +129,7 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
if( e<peffort ){
return STATUS_UNFINISHED;
}else{
+ int status = STATUS_UNKNOWN;
bool gen = false;
if( e==peffort ){
if( d_counter.find( f )==d_counter.end() ){
@@ -147,7 +143,7 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
gen = true;
}
if( gen ){
- generateTriggers( f );
+ generateTriggers( f, effort, e, status );
}
Debug("quant-uf-strategy") << "Try auto-generated triggers... " << d_tr_strategy << " " << e << std::endl;
//Notice() << "Try auto-generated triggers..." << std::endl;
@@ -155,18 +151,14 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
Trigger* tr = itt->first;
if( tr ){
bool processTrigger = itt->second;
- if( effort!=Theory::EFFORT_LAST_CALL && tr->isMultiTrigger() ){
-#ifdef MULTI_TRIGGER_FULL_EFFORT_HALF
- processTrigger = d_counter[f]%2==0;
-#endif
- }
- if( processTrigger ){
+ if( processTrigger && d_processed_trigger[f].find( tr )==d_processed_trigger[f].end() ){
+ d_processed_trigger[f][tr] = true;
//if( tr->isMultiTrigger() )
- Debug("quant-uf-strategy-auto-gen-triggers") << " Process " << (*tr) << "..." << std::endl;
+ Trace("process-trigger") << " Process " << (*tr) << "..." << std::endl;
InstMatch baseMatch;
int numInst = tr->addInstantiations( baseMatch );
//if( tr->isMultiTrigger() )
- Debug("quant-uf-strategy-auto-gen-triggers") << " Done, numInst = " << numInst << "." << std::endl;
+ Trace("process-trigger") << " Done, numInst = " << numInst << "." << std::endl;
if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){
d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_auto_gen_min += numInst;
}else{
@@ -181,24 +173,24 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
}
Debug("quant-uf-strategy") << "done." << std::endl;
//Notice() << "done" << std::endl;
+ return status;
}
- return STATUS_UNKNOWN;
}
-void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
- Debug("auto-gen-trigger") << "Generate trigger for " << f << std::endl;
+void InstStrategyAutoGenTriggers::generateTriggers( Node f, Theory::Effort effort, int e, int & status ){
+ Trace("auto-gen-trigger-debug") << "Generate trigger for " << f << std::endl;
if( d_patTerms[0].find( f )==d_patTerms[0].end() ){
//determine all possible pattern terms based on trigger term selection strategy d_tr_strategy
d_patTerms[0][f].clear();
d_patTerms[1][f].clear();
std::vector< Node > patTermsF;
Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getInstConstantBody( f ), patTermsF, d_tr_strategy, true );
- Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << std::endl;
- Debug("auto-gen-trigger") << " ";
+ Trace("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getInstConstantBody( f ) << std::endl;
+ Trace("auto-gen-trigger") << " ";
for( int i=0; i<(int)patTermsF.size(); i++ ){
- Debug("auto-gen-trigger") << patTermsF[i] << " ";
+ Trace("auto-gen-trigger") << patTermsF[i] << " ";
}
- Debug("auto-gen-trigger") << std::endl;
+ Trace("auto-gen-trigger") << std::endl;
//extend to literal matching (if applicable)
d_quantEngine->getPhaseReqTerms( f, patTermsF );
//sort into single/multi triggers
@@ -214,23 +206,22 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
}
}
d_made_multi_trigger[f] = false;
- Debug("auto-gen-trigger") << "Single triggers for " << f << " : " << std::endl;
- Debug("auto-gen-trigger") << " ";
+ Trace("auto-gen-trigger") << "Single triggers for " << f << " : " << std::endl;
+ Trace("auto-gen-trigger") << " ";
for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
- Debug("auto-gen-trigger") << d_patTerms[0][f][i] << " ";
+ Trace("auto-gen-trigger") << d_patTerms[0][f][i] << " ";
}
- Debug("auto-gen-trigger") << std::endl;
- Debug("auto-gen-trigger") << "Multi-trigger term pool for " << f << " : " << std::endl;
- Debug("auto-gen-trigger") << " ";
+ Trace("auto-gen-trigger") << std::endl;
+ Trace("auto-gen-trigger") << "Multi-trigger term pool for " << f << " : " << std::endl;
+ Trace("auto-gen-trigger") << " ";
for( int i=0; i<(int)d_patTerms[1][f].size(); i++ ){
- Debug("auto-gen-trigger") << d_patTerms[1][f][i] << " ";
+ Trace("auto-gen-trigger") << d_patTerms[1][f][i] << " ";
}
- Debug("auto-gen-trigger") << std::endl;
+ Trace("auto-gen-trigger") << std::endl;
}
//populate candidate pattern term vector for the current trigger
std::vector< Node > patTerms;
-#ifdef USE_SINGLE_TRIGGER_BEFORE_MULTI_TRIGGER
//try to add single triggers first
for( int i=0; i<(int)d_patTerms[0][f].size(); i++ ){
if( !d_single_trigger_gen[d_patTerms[0][f][i]] ){
@@ -241,13 +232,9 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
if( patTerms.empty() ){
patTerms.insert( patTerms.begin(), d_patTerms[1][f].begin(), d_patTerms[1][f].end() );
}
-#else
- patTerms.insert( patTerms.begin(), d_patTerms[0][f].begin(), d_patTerms[0][f].end() );
- patTerms.insert( patTerms.begin(), d_patTerms[1][f].begin(), d_patTerms[1][f].end() );
-#endif
if( !patTerms.empty() ){
- Debug("auto-gen-trigger") << "Generate trigger for " << f << std::endl;
+ Trace("auto-gen-trigger") << "Generate trigger for " << f << std::endl;
//sort terms based on relevance
if( d_rlv_strategy==RELEVANCE_DEFAULT ){
sortQuantifiersForSymbol sqfs;
@@ -273,6 +260,15 @@ void InstStrategyAutoGenTriggers::generateTriggers( Node f ){
options::smartTriggers() );
d_single_trigger_gen[ patTerms[0] ] = true;
}else{
+ //only generate multi trigger if effort level > 5, or if no single triggers exist
+ if( !d_patTerms[0][f].empty() ){
+ if( e<=5 ){
+ status = STATUS_UNFINISHED;
+ return;
+ }else{
+ Trace("multi-trigger-debug") << "Resort to choosing multi-triggers..." << std::endl;
+ }
+ }
//if we are re-generating triggers, shuffle based on some method
if( d_made_multi_trigger[f] ){
#ifndef MULTI_MULTI_TRIGGERS
diff --git a/src/theory/quantifiers/inst_strategy_e_matching.h b/src/theory/quantifiers/inst_strategy_e_matching.h
index b5ff90a62..13d443c6a 100755..100644
--- a/src/theory/quantifiers/inst_strategy_e_matching.h
+++ b/src/theory/quantifiers/inst_strategy_e_matching.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file inst_strategy_e_matching.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): bobot, mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
@@ -80,12 +80,14 @@ private:
std::map< Node, bool > d_is_single_trigger;
std::map< Node, bool > d_single_trigger_gen;
std::map< Node, bool > d_made_multi_trigger;
+ //processed trigger this round
+ std::map< Node, std::map< inst::Trigger*, bool > > d_processed_trigger;
private:
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
int process( Node f, Theory::Effort effort, int e );
/** generate triggers */
- void generateTriggers( Node f );
+ void generateTriggers( Node f, Theory::Effort effort, int e, int & status );
public:
/** tstrt is the type of triggers to use (maximum depth, minimum depth, or all)
rstrt is the relevance setting for trigger (use only relevant triggers vs. use all)
diff --git a/src/theory/quantifiers/macros.cpp b/src/theory/quantifiers/macros.cpp
index 5c7c9415e..9f08764a9 100755..100644
--- a/src/theory/quantifiers/macros.cpp
+++ b/src/theory/quantifiers/macros.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file macros.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/macros.h b/src/theory/quantifiers/macros.h
index f4e58665d..140f02966 100755..100644
--- a/src/theory/quantifiers/macros.h
+++ b/src/theory/quantifiers/macros.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file macros.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/model_builder.cpp b/src/theory/quantifiers/model_builder.cpp
index 2f44140c2..d1c04ceab 100644
--- a/src/theory/quantifiers/model_builder.cpp
+++ b/src/theory/quantifiers/model_builder.cpp
@@ -526,7 +526,7 @@ int ModelEngineBuilderDefault::doInstGen( FirstOrderModel* fm, Node f ){
//if applicable, try to add exceptions here
if( !tr_terms.empty() ){
//make a trigger for these terms, add instantiations
- inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms );
+ inst::Trigger* tr = inst::Trigger::mkTrigger( d_qe, f, tr_terms, 0, true, inst::Trigger::TR_MAKE_NEW, options::smartTriggers() );
//Notice() << "Trigger = " << (*tr) << std::endl;
tr->resetInstantiationRound();
tr->reset( Node::null() );
diff --git a/src/theory/quantifiers/options b/src/theory/quantifiers/options
index bc45e6051..eace177b7 100644
--- a/src/theory/quantifiers/options
+++ b/src/theory/quantifiers/options
@@ -45,8 +45,8 @@ option macrosQuant --macros-quant bool :default false
option smartTriggers /--disable-smart-triggers bool :default true
disable smart triggers
# Whether to use relevent triggers
-option relevantTriggers /--relevant-triggers bool :default true
- prefer triggers that are more relevant based on SInE style method
+option relevantTriggers --relevant-triggers bool :default true
+ prefer triggers that are more relevant based on SInE style analysis
# Whether to consider terms in the bodies of quantifiers for matching
option registerQuantBodyTerms --register-quant-body-terms bool :default false
diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp
index a78cd5612..9e4a2a14a 100755..100644
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file quant_util.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot, mdeters
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/quant_util.h b/src/theory/quantifiers/quant_util.h
index 1daaf3ea1..85602dbab 100755..100644
--- a/src/theory/quantifiers/quant_util.h
+++ b/src/theory/quantifiers/quant_util.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file quant_util.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters, bobot
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/quantifiers_attributes.cpp b/src/theory/quantifiers/quantifiers_attributes.cpp
index 108c09c87..b00fe45f4 100644
--- a/src/theory/quantifiers/quantifiers_attributes.cpp
+++ b/src/theory/quantifiers/quantifiers_attributes.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file quantifiers_attributes.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/quantifiers_attributes.h b/src/theory/quantifiers/quantifiers_attributes.h
index f5a8a749a..8e8ebe97a 100644
--- a/src/theory/quantifiers/quantifiers_attributes.h
+++ b/src/theory/quantifiers/quantifiers_attributes.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file quantifiers_attributes.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index d60aa2ef4..78109ea37 100644
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -206,6 +206,7 @@ Node TermDb::getModelBasisTerm( TypeNode tn, int i ){
ModelBasisAttribute mba;
mbt.setAttribute(mba,true);
d_model_basis_term[tn] = mbt;
+ Trace("model-basis-term") << "Choose " << mbt << " as model basis term for " << tn << std::endl;
}
return d_model_basis_term[tn];
}
@@ -367,6 +368,10 @@ Node TermDb::getSkolemizedBody( Node f ){
Node skv = NodeManager::currentNM()->mkSkolem( "skv_$$", f[0][i].getType(), "is a termdb-created skolemized body" );
d_skolem_constants[ f ].push_back( skv );
vars.push_back( f[0][i] );
+ //carry information for sort inference
+ if( options::sortInference() ){
+ d_quantEngine->getTheoryEngine()->getSortInference()->setSkolemVar( f, f[0][i], skv );
+ }
}
d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),
d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );
@@ -515,6 +520,34 @@ int TermDb::isInstanceOf( Node n1, Node n2 ){
return 0;
}
+bool TermDb::isUnifiableInstanceOf( Node n1, Node n2, std::map< Node, Node >& subs ){
+ if( n1==n2 ){
+ return true;
+ }else if( n2.getKind()==INST_CONSTANT ){
+ //if( !node_contains( n1, n2 ) ){
+ // return false;
+ //}
+ if( subs.find( n2 )==subs.end() ){
+ subs[n2] = n1;
+ }else if( subs[n2]!=n1 ){
+ return false;
+ }
+ return true;
+ }else if( n1.getKind()==n2.getKind() && n1.getMetaKind()==kind::metakind::PARAMETERIZED ){
+ if( n1.getOperator()!=n2.getOperator() ){
+ return false;
+ }
+ for( int i=0; i<(int)n1.getNumChildren(); i++ ){
+ if( !isUnifiableInstanceOf( n1[i], n2[i], subs ) ){
+ return false;
+ }
+ }
+ return true;
+ }else{
+ return false;
+ }
+}
+
void TermDb::filterInstances( std::vector< Node >& nodes ){
std::vector< bool > active;
active.resize( nodes.size(), true );
@@ -523,8 +556,10 @@ void TermDb::filterInstances( std::vector< Node >& nodes ){
if( active[i] && active[j] ){
int result = isInstanceOf( nodes[i], nodes[j] );
if( result==1 ){
+ Trace("filter-instances") << nodes[j] << " is an instance of " << nodes[i] << std::endl;
active[j] = false;
}else if( result==-1 ){
+ Trace("filter-instances") << nodes[i] << " is an instance of " << nodes[j] << std::endl;
active[i] = false;
}
}
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index a1f1de1dc..9ac431107 100644
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -212,6 +212,8 @@ private:
std::map< TNode, std::vector< TNode > > d_var_contains;
/** triggers for each operator */
std::map< Node, std::vector< inst::Trigger* > > d_op_triggers;
+ /** helper for is intance of */
+ bool isUnifiableInstanceOf( Node n1, Node n2, std::map< Node, Node >& subs );
public:
/** compute var contains */
void computeVarContains( Node n );
diff --git a/src/theory/quantifiers/trigger.cpp b/src/theory/quantifiers/trigger.cpp
index bc577fda6..c4bc248d3 100644
--- a/src/theory/quantifiers/trigger.cpp
+++ b/src/theory/quantifiers/trigger.cpp
@@ -34,24 +34,26 @@ using namespace CVC4::theory::inst;
Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
d_quantEngine( qe ), d_f( f ){
d_nodes.insert( d_nodes.begin(), nodes.begin(), nodes.end() );
+ Trace("trigger") << "Trigger for " << f << ": " << std::endl;
+ for( int i=0; i<(int)d_nodes.size(); i++ ){
+ Trace("trigger") << " " << d_nodes[i] << std::endl;
+ }
+ Trace("trigger") << ", smart triggers = " << smartTriggers << std::endl;
if( smartTriggers ){
if( d_nodes.size()==1 ){
if( isSimpleTrigger( d_nodes[0] ) ){
d_mg = new InstMatchGeneratorSimple( f, d_nodes[0] );
}else{
- d_mg = new InstMatchGenerator( d_nodes[0], qe, matchOption );
+ d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes[0], qe );
+ d_mg->setActiveAdd();
}
}else{
d_mg = new InstMatchGeneratorMulti( f, d_nodes, qe, matchOption );
}
}else{
- d_mg = new InstMatchGenerator( d_nodes, qe, matchOption );
- }
- Trace("trigger") << "Trigger for " << f << ": " << std::endl;
- for( int i=0; i<(int)d_nodes.size(); i++ ){
- Trace("trigger") << " " << d_nodes[i] << std::endl;
+ d_mg = InstMatchGenerator::mkInstMatchGenerator( d_nodes, qe );
+ d_mg->setActiveAdd();
}
- Trace("trigger") << std::endl;
if( d_nodes.size()==1 ){
if( isSimpleTrigger( d_nodes[0] ) ){
++(qe->d_statistics.d_triggers);
@@ -59,7 +61,7 @@ d_quantEngine( qe ), d_f( f ){
++(qe->d_statistics.d_simple_triggers);
}
}else{
- Debug("multi-trigger") << "Multi-trigger " << (*this) << std::endl;
+ Trace("multi-trigger") << "Multi-trigger " << (*this) << " for " << f << std::endl;
//Notice() << "Multi-trigger for " << f << " : " << std::endl;
//Notice() << " " << (*this) << std::endl;
++(qe->d_statistics.d_multi_triggers);
@@ -80,14 +82,14 @@ void Trigger::reset( Node eqc ){
d_mg->reset( eqc, d_quantEngine );
}
-bool Trigger::getNextMatch( InstMatch& m ){
- bool retVal = d_mg->getNextMatch( m, d_quantEngine );
+bool Trigger::getNextMatch( Node f, InstMatch& m ){
+ bool retVal = d_mg->getNextMatch( f, m, d_quantEngine );
return retVal;
}
-bool Trigger::getMatch( Node t, InstMatch& m ){
+bool Trigger::getMatch( Node f, Node t, InstMatch& m ){
//FIXME: this assumes d_mg is an inst match generator
- return ((InstMatchGenerator*)d_mg)->getMatch( t, m, d_quantEngine );
+ return ((InstMatchGenerator*)d_mg)->getMatch( f, t, m, d_quantEngine );
}
int Trigger::addTerm( Node t ){
@@ -115,6 +117,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
temp.insert( temp.begin(), nodes.begin(), nodes.end() );
std::map< Node, bool > vars;
std::map< Node, std::vector< Node > > patterns;
+ size_t varCount = 0;
for( int i=0; i<(int)temp.size(); i++ ){
bool foundVar = false;
qe->getTermDatabase()->computeVarContains( temp[i] );
@@ -122,6 +125,7 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
Node v = qe->getTermDatabase()->d_var_contains[ temp[i] ][j];
if( v.getAttribute(InstConstantAttribute())==f ){
if( vars.find( v )==vars.end() ){
+ varCount++;
vars[ v ] = true;
foundVar = true;
}
@@ -134,32 +138,40 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
patterns[ v ].push_back( temp[i] );
}
}
- }
- //now, minimalize the trigger
- for( int i=0; i<(int)trNodes.size(); i++ ){
- bool keepPattern = false;
- Node n = trNodes[i];
- for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ n ].size(); j++ ){
- Node v = qe->getTermDatabase()->d_var_contains[ n ][j];
- if( patterns[v].size()==1 ){
- keepPattern = true;
- break;
- }
+ if( varCount==f[0].getNumChildren() ){
+ break;
}
- if( !keepPattern ){
- //remove from pattern vector
+ }
+ if( varCount<f[0].getNumChildren() ){
+ //do not generate multi-trigger if it does not contain all variables
+ return NULL;
+ }else{
+ //now, minimize the trigger
+ for( int i=0; i<(int)trNodes.size(); i++ ){
+ bool keepPattern = false;
+ Node n = trNodes[i];
for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ n ].size(); j++ ){
Node v = qe->getTermDatabase()->d_var_contains[ n ][j];
- for( int k=0; k<(int)patterns[v].size(); k++ ){
- if( patterns[v][k]==n ){
- patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
- break;
+ if( patterns[v].size()==1 ){
+ keepPattern = true;
+ break;
+ }
+ }
+ if( !keepPattern ){
+ //remove from pattern vector
+ for( int j=0; j<(int)qe->getTermDatabase()->d_var_contains[ n ].size(); j++ ){
+ Node v = qe->getTermDatabase()->d_var_contains[ n ][j];
+ for( int k=0; k<(int)patterns[v].size(); k++ ){
+ if( patterns[v][k]==n ){
+ patterns[v].erase( patterns[v].begin() + k, patterns[v].begin() + k + 1 );
+ break;
+ }
}
}
+ //remove from trigger nodes
+ trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
+ i--;
}
- //remove from trigger nodes
- trNodes.erase( trNodes.begin() + i, trNodes.begin() + i + 1 );
- i--;
}
}
}else{
@@ -322,16 +334,16 @@ void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vecto
temp.insert( temp.begin(), patTerms2.begin(), patTerms2.end() );
qe->getTermDatabase()->filterInstances( temp );
if( temp.size()!=patTerms2.size() ){
- Debug("trigger-filter-instance") << "Filtered an instance: " << std::endl;
- Debug("trigger-filter-instance") << "Old: ";
+ Trace("trigger-filter-instance") << "Filtered an instance: " << std::endl;
+ Trace("trigger-filter-instance") << "Old: ";
for( int i=0; i<(int)patTerms2.size(); i++ ){
- Debug("trigger-filter-instance") << patTerms2[i] << " ";
+ Trace("trigger-filter-instance") << patTerms2[i] << " ";
}
- Debug("trigger-filter-instance") << std::endl << "New: ";
+ Trace("trigger-filter-instance") << std::endl << "New: ";
for( int i=0; i<(int)temp.size(); i++ ){
- Debug("trigger-filter-instance") << temp[i] << " ";
+ Trace("trigger-filter-instance") << temp[i] << " ";
}
- Debug("trigger-filter-instance") << std::endl;
+ Trace("trigger-filter-instance") << std::endl;
}
if( tstrt==TS_ALL ){
patTerms.insert( patTerms.begin(), temp.begin(), temp.end() );
diff --git a/src/theory/quantifiers/trigger.h b/src/theory/quantifiers/trigger.h
index 6fcd316f4..93731283b 100644
--- a/src/theory/quantifiers/trigger.h
+++ b/src/theory/quantifiers/trigger.h
@@ -56,12 +56,12 @@ public:
/** reset, eqc is the equivalence class to search in (search in any if eqc=null) */
void reset( Node eqc );
/** get next match. must call reset( eqc ) once before this function. */
- bool getNextMatch( InstMatch& m );
+ bool getNextMatch( Node f, InstMatch& m );
/** get the match against ground term or formula t.
the trigger and t should have the same shape.
Currently the trigger should not be a multi-trigger.
*/
- bool getMatch( Node t, InstMatch& m);
+ bool getMatch( Node f, Node t, InstMatch& m);
/** add ground term t, called when t is added to the TermDb */
int addTerm( Node t );
/** return whether this is a multi-trigger */
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 08bdd496b..f938199f8 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -71,6 +71,7 @@ d_lemmas_produced_c(u){
d_optMatchIgnoreModelBasis = false;
d_optInstLimitActive = false;
d_optInstLimit = 0;
+ d_total_inst_count_debug = 0;
}
QuantifiersEngine::~QuantifiersEngine(){
@@ -142,10 +143,23 @@ void QuantifiersEngine::check( Theory::Effort e ){
}
//build the model if not done so already
// this happens if no quantifiers are currently asserted and no model-building module is enabled
- if( options::produceModels() && e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma && !d_model->isModelSet() ){
- d_te->getModelBuilder()->buildModel( d_model, true );
+ if( e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma ){
+ if( options::produceModels() && !d_model->isModelSet() ){
+ d_te->getModelBuilder()->buildModel( d_model, true );
+ }
+ if( Trace.isOn("inst-per-quant") ){
+ for( std::map< Node, int >::iterator it = d_total_inst_debug.begin(); it != d_total_inst_debug.end(); ++it ){
+ Trace("inst-per-quant") << " * " << it->second << " for " << it->first << std::endl;
+ }
+ }
+ }else{
+ if( Trace.isOn("inst-per-quant-round") ){
+ for( std::map< Node, int >::iterator it = d_temp_inst_debug.begin(); it != d_temp_inst_debug.end(); ++it ){
+ Trace("inst-per-quant-round") << " * " << it->second << " for " << it->first << std::endl;
+ d_temp_inst_debug[it->first] = 0;
+ }
+ }
}
-
Trace("quant-engine") << "Finished quantifiers engine check." << std::endl;
}
}
@@ -242,6 +256,9 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
Node lem = nb;
//check for duplication
if( addLemma( lem ) ){
+ d_total_inst_debug[f]++;
+ d_temp_inst_debug[f]++;
+ d_total_inst_count_debug++;
Trace("inst") << "*** Instantiate " << f << " with " << std::endl;
uint64_t maxInstLevel = 0;
for( int i=0; i<(int)terms.size(); i++ ){
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index 29381a309..fa8a51d1f 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -119,6 +119,10 @@ private:
rrinst::TriggerTrie* d_rr_tr_trie;
/** extended model object */
quantifiers::FirstOrderModel* d_model;
+ /** statistics for debugging */
+ std::map< Node, int > d_total_inst_debug;
+ std::map< Node, int > d_temp_inst_debug;
+ int d_total_inst_count_debug;
private:
KEEP_STATISTIC(TimerStat, d_time, "theory::QuantifiersEngine::time");
public:
diff --git a/src/theory/rep_set.cpp b/src/theory/rep_set.cpp
index 3b5ba0cef..4ae7f2d0c 100644
--- a/src/theory/rep_set.cpp
+++ b/src/theory/rep_set.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file rep_set.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/rep_set.h b/src/theory/rep_set.h
index fec5d3ed8..dc31f2d5f 100644
--- a/src/theory/rep_set.h
+++ b/src/theory/rep_set.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file rep_set.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/rewriterules/efficient_e_matching.cpp b/src/theory/rewriterules/efficient_e_matching.cpp
index 24693d496..5ed34d46c 100755..100644
--- a/src/theory/rewriterules/efficient_e_matching.cpp
+++ b/src/theory/rewriterules/efficient_e_matching.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file efficient_e_matching.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/rewriterules/efficient_e_matching.h b/src/theory/rewriterules/efficient_e_matching.h
index fe65362ef..11c6b783e 100755..100644
--- a/src/theory/rewriterules/efficient_e_matching.h
+++ b/src/theory/rewriterules/efficient_e_matching.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file efficient_e_matching.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: bobot
- ** Minor contributors (to current version): mdeters
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
+ ** Minor contributors (to current version): none
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
diff --git a/src/theory/rewriterules/theory_rewriterules.cpp b/src/theory/rewriterules/theory_rewriterules.cpp
index c6fd9611c..a82b94f73 100644
--- a/src/theory/rewriterules/theory_rewriterules.cpp
+++ b/src/theory/rewriterules/theory_rewriterules.cpp
@@ -276,7 +276,7 @@ void TheoryRewriteRules::check(Effort level) {
if(glast.inst == RULEINST_TRUE||glast.inst == RULEINST_FALSE)
continue;
// If it has a value it should already has been notified
- bool value; value = value; // avoiding the warning in non debug mode
+ bool value CVC4_UNUSED;
Assert(!getValuation().hasSatValue(g,value));
Debug("rewriterules::check") << "RewriteRules::Check Narrowing on:" << g << std::endl;
/** Can split on already rewritten instrule... but... */
diff --git a/src/theory/shared_terms_database.h b/src/theory/shared_terms_database.h
index 655918986..c7036a9ad 100644
--- a/src/theory/shared_terms_database.h
+++ b/src/theory/shared_terms_database.h
@@ -66,7 +66,7 @@ private:
AlreadyNotifiedMap d_alreadyNotifiedMap;
/** The registered equalities for propagation */
- typedef context::CDHashSet<TNode, TNodeHashFunction> RegisteredEqualitiesSet;
+ typedef context::CDHashSet<Node, NodeHashFunction> RegisteredEqualitiesSet;
RegisteredEqualitiesSet d_registeredEqualities;
private:
diff --git a/src/theory/theory.h b/src/theory/theory.h
index f317d4b92..5b2032430 100644
--- a/src/theory/theory.h
+++ b/src/theory/theory.h
@@ -33,6 +33,7 @@
#include "options/options.h"
#include "util/statistics_registry.h"
#include "util/dump.h"
+#include "lib/ffs.h"
#include <string>
#include <iostream>
@@ -49,13 +50,13 @@ namespace theory {
class QuantifiersEngine;
class TheoryModel;
-namespace rrinst{
-class CandidateGenerator;
-}
+namespace rrinst {
+ class CandidateGenerator;
+}/* CVC4::theory::rrinst namespace */
namespace eq {
-class EqualityEngine;
-}
+ class EqualityEngine;
+}/* CVC4::theory::eq namespace */
/**
* Information about an assertion for the theories.
@@ -786,14 +787,10 @@ public:
std::hash_set<TNode, TNodeHashFunction> currentlySharedTerms() const;
};/* class Theory */
-std::ostream& operator<<(std::ostream& os, Theory::Effort level);
-
-namespace eq{
- class EqualityEngine;
-}
-
+std::ostream& operator<<(std::ostream& os, theory::Theory::Effort level);
+inline std::ostream& operator<<(std::ostream& out, const theory::Assertion& a);
-inline Assertion Theory::get() {
+inline theory::Assertion Theory::get() {
Assert( !done(), "Theory::get() called with assertion queue empty!" );
// Get the assertion
@@ -809,7 +806,9 @@ inline Assertion Theory::get() {
return fact;
}
-}/* CVC4::theory namespace */
+inline std::ostream& operator<<(std::ostream& out, const theory::Assertion& a) {
+ return out << a.assertion;
+}
inline std::ostream& operator<<(std::ostream& out,
const CVC4::theory::Theory& theory) {
@@ -830,6 +829,7 @@ inline std::ostream& operator << (std::ostream& out, theory::Theory::PPAssertSta
return out;
}
+}/* CVC4::theory namespace */
}/* CVC4 namespace */
#endif /* __CVC4__THEORY__THEORY_H */
diff --git a/src/theory/theory_engine.cpp b/src/theory/theory_engine.cpp
index 35ed63bed..f85a5f3cd 100644
--- a/src/theory/theory_engine.cpp
+++ b/src/theory/theory_engine.cpp
@@ -286,7 +286,9 @@ void TheoryEngine::check(Theory::Effort effort) {
#endif
#define CVC4_FOR_EACH_THEORY_STATEMENT(THEORY) \
if (theory::TheoryTraits<THEORY>::hasCheck && d_logicInfo.isTheoryEnabled(THEORY)) { \
+Debug("theory") << "check<" << THEORY << ">" << std::endl; \
theoryOf(THEORY)->check(effort); \
+Debug("theory") << "done<" << THEORY << ">" << std::endl; \
if (d_inConflict) { \
break; \
} \
@@ -726,16 +728,6 @@ theory::Theory::PPAssertStatus TheoryEngine::solve(TNode literal, SubstitutionMa
Theory::PPAssertStatus solveStatus = theoryOf(atom)->ppAssert(literal, substitutionOut);
Trace("theory::solve") << "TheoryEngine::solve(" << literal << ") => " << solveStatus << endl;
- //must add substitutions to model
- theory::TheoryModel* m = getModel();
- if( m ){
- for( SubstitutionMap::iterator pos = substitutionOut.begin(); pos != substitutionOut.end(); ++pos) {
- Node n = (*pos).first;
- Node v = (*pos).second;
- Trace("model") << "Add substitution : " << n << " " << v << std::endl;
- m->addSubstitution( n, v );
- }
- }
return solveStatus;
}
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 063943056..388c0edf0 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -41,6 +41,7 @@
#include "util/hash.h"
#include "util/cache.h"
#include "util/cvc4_assert.h"
+#include "util/sort_inference.h"
#include "theory/ite_simplifier.h"
#include "theory/unconstrained_simplifier.h"
#include "theory/uf/equality_engine.h"
@@ -190,7 +191,7 @@ class TheoryEngine {
* context-dependent set of those theory-propagable literals that
* have been propagated.
*/
- context::CDHashSet<TNode, TNodeHashFunction> d_hasPropagated;
+ context::CDHashSet<Node, NodeHashFunction> d_hasPropagated;
/**
* Statistics for a particular theory.
@@ -422,6 +423,9 @@ class TheoryEngine {
RemoveITE& d_iteRemover;
+ /** sort inference module */
+ SortInference d_sortInfer;
+
/** Time spent in theory combination */
TimerStat d_combineTheoriesTime;
@@ -732,6 +736,7 @@ public:
SharedTermsDatabase* getSharedTermsDatabase() { return &d_sharedTerms; }
+ SortInference* getSortInference() { return &d_sortInfer; }
private:
std::map< std::string, std::vector< theory::Theory* > > d_attr_handle;
public:
diff --git a/src/theory/uf/options b/src/theory/uf/options
index 2569ccbff..d6a2bb025 100644
--- a/src/theory/uf/options
+++ b/src/theory/uf/options
@@ -25,6 +25,8 @@ option ufssAbortCardinality --uf-ss-abort-card=N int :default -1
option ufssSmartSplits --uf-ss-smart-split bool :default false
use smart splitting heuristic for uf strong solver
option ufssExplainedCliques --uf-ss-explained-cliques bool :default false
- add explained clique lemmas for uf strong solver
+ use explained clique lemmas for uf strong solver
+option ufssSimpleCliques --uf-ss-simple-cliques bool :default true
+ always use simple clique lemmas for uf strong solver
endmodule
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index 46ac5aa60..0a96cf548 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -533,6 +533,7 @@ void StrongSolverTheoryUf::SortRepModel::assertDisequal( Node a, Node b, Node re
//internal disequality
d_regions[ai]->setDisequal( a, b, 1, true );
d_regions[ai]->setDisequal( b, a, 1, true );
+ checkRegion( ai, false ); //do not need to check if it needs to combine (no new ext. disequalities)
}else{
//external disequality
d_regions[ai]->setDisequal( a, b, 0, true );
@@ -610,14 +611,33 @@ void StrongSolverTheoryUf::SortRepModel::check( Theory::Effort level, OutputChan
if( level==Theory::EFFORT_FULL ){
if( !addedLemma ){
Trace("uf-ss-debug") << "No splits added. " << d_cardinality << std::endl;
- if( !options::ufssColoringSat() ){
+ Trace("uf-ss-si") << "Must combine region" << std::endl;
+ if( true || !options::ufssColoringSat() ){
bool recheck = false;
//naive strategy, force region combination involving the first valid region
- for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
- forceCombineRegion( i, false );
- recheck = true;
- break;
+ if( options::sortInference()){
+ std::map< int, int > sortsFound;
+ for( int i=0; i<(int)d_regions_index; i++ ){
+ if( d_regions[i]->d_valid ){
+ Node op = d_regions[i]->d_nodes.begin()->first;
+ int sort_id = d_th->getQuantifiersEngine()->getTheoryEngine()->getSortInference()->getSortId(op) ;
+ if( sortsFound.find( sort_id )!=sortsFound.end() ){
+ combineRegions( sortsFound[sort_id], i );
+ recheck = true;
+ break;
+ }else{
+ sortsFound[sort_id] = i;
+ }
+ }
+ }
+ }
+ if( !recheck ) {
+ for( int i=0; i<(int)d_regions_index; i++ ){
+ if( d_regions[i]->d_valid ){
+ forceCombineRegion( i, false );
+ recheck = true;
+ break;
+ }
}
}
if( recheck ){
@@ -803,15 +823,10 @@ void StrongSolverTheoryUf::SortRepModel::assertCardinality( OutputChannel* out,
}
}
-void StrongSolverTheoryUf::SortRepModel::checkRegion( int ri, bool rec ){
+void StrongSolverTheoryUf::SortRepModel::checkRegion( int ri, bool checkCombine ){
if( isValid(ri) && d_hasCard ){
Assert( d_cardinality>0 );
- //first check if region is in conflict
- std::vector< Node > clique;
- if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
- //explain clique
- addCliqueLemma( clique, &d_th->getOutputChannel() );
- }else if( d_regions[ri]->getMustCombine( d_cardinality ) ){
+ if( checkCombine && d_regions[ri]->getMustCombine( d_cardinality ) ){
////alternatively, check if we can reduce the number of external disequalities by moving single nodes
//for( std::map< Node, bool >::iterator it = d_regions[i]->d_reps.begin(); it != d_regions[i]->d_reps.end(); ++it ){
// if( it->second ){
@@ -822,10 +837,16 @@ void StrongSolverTheoryUf::SortRepModel::checkRegion( int ri, bool rec ){
// }
//}
int riNew = forceCombineRegion( ri, true );
- if( riNew>=0 && rec ){
- checkRegion( riNew, rec );
+ if( riNew>=0 ){
+ checkRegion( riNew, checkCombine );
}
}
+ //now check if region is in conflict
+ std::vector< Node > clique;
+ if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
+ //explain clique
+ addCliqueLemma( clique, &d_th->getOutputChannel() );
+ }
}
}
@@ -996,6 +1017,13 @@ bool StrongSolverTheoryUf::SortRepModel::addSplit( Region* r, OutputChannel* out
Assert( s!=Node::null() && s.getKind()==EQUAL );
s = Rewriter::rewrite( s );
Trace("uf-ss-lemma") << "*** Split on " << s << std::endl;
+ if( options::sortInference()) {
+ for( int i=0; i<2; i++ ){
+ int si = d_th->getQuantifiersEngine()->getTheoryEngine()->getSortInference()->getSortId( s[i] );
+ Trace("uf-ss-split-si") << si << " ";
+ }
+ Trace("uf-ss-split-si") << std::endl;
+ }
//Trace("uf-ss-lemma") << d_th->getEqualityEngine()->areEqual( s[0], s[1] ) << " ";
//Trace("uf-ss-lemma") << d_th->getEqualityEngine()->areDisequal( s[0], s[1] ) << std::endl;
//Trace("uf-ss-lemma") << s[0].getType() << " " << s[1].getType() << std::endl;
@@ -1018,117 +1046,149 @@ void StrongSolverTheoryUf::SortRepModel::addCliqueLemma( std::vector< Node >& cl
while( clique.size()>size_t(d_cardinality+1) ){
clique.pop_back();
}
- if( !options::ufssExplainedCliques() ){
+ if( options::ufssSimpleCliques() && !options::ufssExplainedCliques() ){
//add as lemma
std::vector< Node > eqs;
for( int i=0; i<(int)clique.size(); i++ ){
for( int j=0; j<i; j++ ){
+ Node r1 = d_th->d_equalityEngine.getRepresentative(clique[i]);
+ Node r2 = d_th->d_equalityEngine.getRepresentative(clique[j]);
eqs.push_back( clique[i].eqNode( clique[j] ) );
}
}
eqs.push_back( d_cardinality_literal[ d_cardinality ].notNode() );
Node lem = NodeManager::currentNM()->mkNode( OR, eqs );
+ Trace("uf-ss-lemma") << "*** Add clique conflict " << lem << std::endl;
+ ++( d_th->getStrongSolver()->d_statistics.d_clique_lemmas );
out->lemma( lem );
- return;
- }
- //if( options::ufssModelInference() ||
- if( Trace.isOn("uf-ss-cliques") ){
- std::vector< Node > clique_vec;
- clique_vec.insert( clique_vec.begin(), clique.begin(), clique.end() );
- d_cliques[ d_cardinality ].push_back( clique_vec );
- }
-
- //found a clique
- Debug("uf-ss-cliques") << "Found a clique (cardinality=" << d_cardinality << ") :" << std::endl;
- Debug("uf-ss-cliques") << " ";
- for( int i=0; i<(int)clique.size(); i++ ){
- Debug("uf-ss-cliques") << clique[i] << " ";
- }
- Debug("uf-ss-cliques") << std::endl;
- Debug("uf-ss-cliques") << "Finding clique disequalities..." << std::endl;
- std::vector< Node > conflict;
- //collect disequalities, and nodes that must be equal within representatives
- std::map< Node, std::map< Node, bool > > explained;
- std::map< Node, std::map< Node, bool > > nodesWithinRep;
- for( int i=0; i<(int)d_disequalities_index; i++ ){
- //if both sides of disequality exist in clique
- Node r1 = d_th->d_equalityEngine.getRepresentative( d_disequalities[i][0][0] );
- Node r2 = d_th->d_equalityEngine.getRepresentative( d_disequalities[i][0][1] );
- if( r1!=r2 && ( explained.find( r1 )==explained.end() || explained[r1].find( r2 )==explained[r1].end() ) &&
- std::find( clique.begin(), clique.end(), r1 )!=clique.end() &&
- std::find( clique.begin(), clique.end(), r2 )!=clique.end() ){
- explained[r1][r2] = true;
- explained[r2][r1] = true;
- conflict.push_back( d_disequalities[i] );
- Debug("uf-ss-cliques") << " -> disequality : " << d_disequalities[i] << std::endl;
- nodesWithinRep[r1][ d_disequalities[i][0][0] ] = true;
- nodesWithinRep[r2][ d_disequalities[i][0][1] ] = true;
- if( conflict.size()==(clique.size()*( clique.size()-1 )/2) ){
- break;
+ }else{
+ //debugging information
+ if( Trace.isOn("uf-ss-cliques") ){
+ std::vector< Node > clique_vec;
+ clique_vec.insert( clique_vec.begin(), clique.begin(), clique.end() );
+ d_cliques[ d_cardinality ].push_back( clique_vec );
+ }
+ //found a clique
+ Debug("uf-ss-cliques") << "Found a clique (cardinality=" << d_cardinality << ") :" << std::endl;
+ Debug("uf-ss-cliques") << " ";
+ for( int i=0; i<(int)clique.size(); i++ ){
+ Debug("uf-ss-cliques") << clique[i] << " ";
+ }
+ Debug("uf-ss-cliques") << std::endl;
+ Debug("uf-ss-cliques") << "Finding clique disequalities..." << std::endl;
+
+ //we will scan through each of the disequaltities
+ bool isSatConflict = true;
+ std::vector< Node > conflict;
+ //collect disequalities, and nodes that must be equal within representatives
+ std::map< Node, std::map< Node, bool > > explained;
+ std::map< Node, std::map< Node, bool > > nodesWithinRep;
+ //map from the reprorted clique members to those reported in the lemma
+ std::map< Node, Node > cliqueRepMap;
+ for( int i=0; i<(int)d_disequalities_index; i++ ){
+ //if both sides of disequality exist in clique
+ Node r1 = d_th->d_equalityEngine.getRepresentative( d_disequalities[i][0][0] );
+ Node r2 = d_th->d_equalityEngine.getRepresentative( d_disequalities[i][0][1] );
+ if( r1!=r2 && ( explained.find( r1 )==explained.end() || explained[r1].find( r2 )==explained[r1].end() ) &&
+ std::find( clique.begin(), clique.end(), r1 )!=clique.end() &&
+ std::find( clique.begin(), clique.end(), r2 )!=clique.end() ){
+ explained[r1][r2] = true;
+ explained[r2][r1] = true;
+ if( options::ufssExplainedCliques() ){
+ conflict.push_back( d_disequalities[i] );
+ Debug("uf-ss-cliques") << " -> disequality : " << d_disequalities[i] << std::endl;
+ nodesWithinRep[r1][ d_disequalities[i][0][0] ] = true;
+ nodesWithinRep[r2][ d_disequalities[i][0][1] ] = true;
+ }else{
+ //get the terms we report in the lemma
+ Node ru1 = r1;
+ if( cliqueRepMap.find( r1 )==cliqueRepMap.end() ){
+ ru1 = d_disequalities[i][0][0];
+ cliqueRepMap[r1] = ru1;
+ }else{
+ ru1 = cliqueRepMap[r1];
+ }
+ Node ru2 = r2;
+ if( cliqueRepMap.find( r2 )==cliqueRepMap.end() ){
+ ru2 = d_disequalities[i][0][1];
+ cliqueRepMap[r2] = ru2;
+ }else{
+ ru2 = cliqueRepMap[r2];
+ }
+ if( ru1!=d_disequalities[i][0][0] || ru2!=d_disequalities[i][0][1] ){
+ //disequalities have endpoints that are not connected within an equivalence class
+ // we will be producing a lemma, introducing a new literal ru1 != ru2
+ conflict.push_back( ru1.eqNode( ru2 ).notNode() );
+ isSatConflict = false;
+ }else{
+ conflict.push_back( d_disequalities[i] );
+ }
+ }
+ if( conflict.size()==(clique.size()*( clique.size()-1 )/2) ){
+ break;
+ }
}
}
- }
- //Debug("uf-ss-cliques") << conflict.size() << " " << clique.size() << std::endl;
- Assert( (int)conflict.size()==((int)clique.size()*( (int)clique.size()-1 )/2) );
- //Assert( (int)conflict.size()==(int)clique.size()*( (int)clique.size()-1 )/2 );
- Debug("uf-ss-cliques") << "Finding clique equalities internal to eq classes..." << std::endl;
- //now, we must explain equalities within each equivalence class
- for( std::map< Node, std::map< Node, bool > >::iterator it = nodesWithinRep.begin(); it != nodesWithinRep.end(); ++it ){
- if( it->second.size()>1 ){
- Node prev;
- //add explanation of t1 = t2 = ... = tn
- Debug("uf-ss-cliques") << "Explain ";
- for( std::map< Node, bool >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- if( prev!=Node::null() ){
- Debug("uf-ss-cliques") << " = ";
- //explain it2->first and prev
- std::vector< TNode > expl;
- d_th->d_equalityEngine.explainEquality( it2->first, prev, true, expl );
- for( int i=0; i<(int)expl.size(); i++ ){
- if( std::find( conflict.begin(), conflict.end(), expl[i] )==conflict.end() ){
- conflict.push_back( expl[i] );
+ if( options::ufssExplainedCliques() ){
+ //Debug("uf-ss-cliques") << conflict.size() << " " << clique.size() << std::endl;
+ Assert( (int)conflict.size()==((int)clique.size()*( (int)clique.size()-1 )/2) );
+ //Assert( (int)conflict.size()==(int)clique.size()*( (int)clique.size()-1 )/2 );
+ Debug("uf-ss-cliques") << "Finding clique equalities internal to eq classes..." << std::endl;
+ //now, we must explain equalities within each equivalence class
+ for( std::map< Node, std::map< Node, bool > >::iterator it = nodesWithinRep.begin(); it != nodesWithinRep.end(); ++it ){
+ if( it->second.size()>1 ){
+ Node prev;
+ //add explanation of t1 = t2 = ... = tn
+ Debug("uf-ss-cliques") << "Explain ";
+ for( std::map< Node, bool >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ if( prev!=Node::null() ){
+ Debug("uf-ss-cliques") << " = ";
+ //explain it2->first and prev
+ std::vector< TNode > expl;
+ d_th->d_equalityEngine.explainEquality( it2->first, prev, true, expl );
+ for( int i=0; i<(int)expl.size(); i++ ){
+ if( std::find( conflict.begin(), conflict.end(), expl[i] )==conflict.end() ){
+ conflict.push_back( expl[i] );
+ }
+ }
}
+ prev = it2->first;
+ Debug("uf-ss-cliques") << prev;
}
+ Debug("uf-ss-cliques") << std::endl;
}
- prev = it2->first;
- Debug("uf-ss-cliques") << prev;
+ }
+ Debug("uf-ss-cliques") << "Explanation of clique (size=" << conflict.size() << ") = " << std::endl;
+ for( int i=0; i<(int)conflict.size(); i++ ){
+ Debug("uf-ss-cliques") << conflict[i] << " ";
}
Debug("uf-ss-cliques") << std::endl;
}
- }
- Debug("uf-ss-cliques") << "Explanation of clique (size=" << conflict.size() << ") = " << std::endl;
- for( int i=0; i<(int)conflict.size(); i++ ){
- Debug("uf-ss-cliques") << conflict[i] << " ";
- //bool value;
- //bool hasValue = d_th->getValuation().hasSatValue( conflict[i], value );
- //Assert( hasValue );
- //Assert( value );
- }
- Debug("uf-ss-cliques") << std::endl;
- //now, make the conflict
-#if 1
- conflict.push_back( d_cardinality_literal[ d_cardinality ] );
- Node conflictNode = NodeManager::currentNM()->mkNode( AND, conflict );
- Trace("uf-ss-lemma") << "*** Add clique conflict " << conflictNode << std::endl;
- //Notice() << "*** Add clique conflict " << conflictNode << std::endl;
- out->conflict( conflictNode );
- d_conflict = true;
-#else
- Node conflictNode = conflict.size()==1 ? conflict[0] : NodeManager::currentNM()->mkNode( AND, conflict );
- //add cardinality constraint
- Node cardNode = d_cardinality_literal[ d_cardinality ];
- //bool value;
- //bool hasValue = d_th->getValuation().hasSatValue( cardNode, value );
- //Assert( hasValue );
- //Assert( value );
- conflictNode = NodeManager::currentNM()->mkNode( IMPLIES, conflictNode, cardNode.notNode() );
- Trace("uf-ss-lemma") << "*** Add clique conflict " << conflictNode << std::endl;
- //Notice() << "*** Add clique conflict " << conflictNode << std::endl;
- out->lemma( conflictNode );
-#endif
- ++( d_th->getStrongSolver()->d_statistics.d_clique_lemmas );
+ //now, make the conflict
+ if( isSatConflict ){
+ conflict.push_back( d_cardinality_literal[ d_cardinality ] );
+ Node conflictNode = NodeManager::currentNM()->mkNode( AND, conflict );
+ Trace("uf-ss-lemma") << "*** Add clique conflict " << conflictNode << std::endl;
+ //Notice() << "*** Add clique conflict " << conflictNode << std::endl;
+ out->conflict( conflictNode );
+ d_conflict = true;
+ ++( d_th->getStrongSolver()->d_statistics.d_clique_conflicts );
+ }else{
+ Node conflictNode = conflict.size()==1 ? conflict[0] : NodeManager::currentNM()->mkNode( AND, conflict );
+ //add cardinality constraint
+ Node cardNode = d_cardinality_literal[ d_cardinality ];
+ //bool value;
+ //bool hasValue = d_th->getValuation().hasSatValue( cardNode, value );
+ //Assert( hasValue );
+ //Assert( value );
+ conflictNode = NodeManager::currentNM()->mkNode( IMPLIES, conflictNode, cardNode.notNode() );
+ Trace("uf-ss-lemma") << "*** Add clique lemma " << conflictNode << std::endl;
+ out->lemma( conflictNode );
+ ++( d_th->getStrongSolver()->d_statistics.d_clique_lemmas );
+ }
- //DO_THIS: ensure that the same clique is not reported??? Check standard effort after assertDisequal can produce same clique.
+ //DO_THIS: ensure that the same clique is not reported??? Check standard effort after assertDisequal can produce same clique.
+ }
}
void StrongSolverTheoryUf::SortRepModel::addTotalityAxiom( Node n, int cardinality, OutputChannel* out ){
@@ -1222,7 +1282,7 @@ int StrongSolverTheoryUf::SortRepModel::getNumRegions(){
}
void StrongSolverTheoryUf::SortRepModel::getRepresentatives( std::vector< Node >& reps ){
- if( !options::ufssColoringSat() ){
+ //if( !options::ufssColoringSat() ){
bool foundRegion = false;
for( int i=0; i<(int)d_regions_index; i++ ){
//should not have multiple regions at this point
@@ -1235,123 +1295,9 @@ void StrongSolverTheoryUf::SortRepModel::getRepresentatives( std::vector< Node >
foundRegion = true;
}
}
- }else{
- Unimplemented("Build representatives for fmf region sat is not implemented");
- }
-}
-
-
-/** initialize */
-void StrongSolverTheoryUf::InfRepModel::initialize( OutputChannel* out ){
-
-}
-
-/** new node */
-void StrongSolverTheoryUf::InfRepModel::newEqClass( Node n ){
- d_rep[n] = n;
- //d_const_rep[n] = n.getMetaKind()==metakind::CONSTANT;
-}
-
-/** merge */
-void StrongSolverTheoryUf::InfRepModel::merge( Node a, Node b ){
- //d_rep[b] = false;
- //d_const_rep[a] = d_const_rep[a] || d_const_rep[b];
- Node repb = d_rep[b];
- Assert( !repb.isNull() );
- if( repb.getMetaKind()==metakind::CONSTANT || isBadRepresentative( d_rep[a] ) ){
- d_rep[a] = repb;
- }
- d_rep[b] = Node::null();
-}
-
-/** check */
-void StrongSolverTheoryUf::InfRepModel::check( Theory::Effort level, OutputChannel* out ){
-
-}
-
-/** minimize */
-bool StrongSolverTheoryUf::InfRepModel::minimize( OutputChannel* out ){
-#if 0
- bool retVal = true;
-#else
- bool retVal = !addSplit( out );
-#endif
- if( retVal ){
- std::vector< Node > reps;
- getRepresentatives( reps );
- Trace("uf-ss-fmf") << "Num representatives of type " << d_type << " : " << reps.size() << std::endl;
- /*
- for( int i=0; i<(int)reps.size(); i++ ){
- std::cout << reps[i] << " ";
- }
- std::cout << std::endl;
- for( int i=0; i<(int)reps.size(); i++ ){
- std::cout << reps[i].getMetaKind() << " ";
- }
- std::cout << std::endl;
- for( NodeNodeMap::iterator it = d_rep.begin(); it != d_rep.end(); ++it ){
- Node rep = (*it).second;
- if( !rep.isNull() && !isBadRepresentative( rep ) ){
- for( NodeNodeMap::iterator it2 = d_rep.begin(); it2 != d_rep.end(); ++it2 ){
- Node rep2 = (*it2).second;
- if( !rep2.isNull() && !isBadRepresentative( rep2 ) ){
- if( d_th->getQuantifiersEngine()->getEqualityQuery()->areDisequal( rep, rep2 ) ){
- std::cout << "1 ";
- }else{
- std::cout << "0 ";
- }
- }
- }
- //std::cout << " : " << rep;
- std::cout << std::endl;
- }
- }
- */
- }
- return retVal;
-}
-
-/** get representatives */
-void StrongSolverTheoryUf::InfRepModel::getRepresentatives( std::vector< Node >& reps ){
- for( NodeNodeMap::iterator it = d_rep.begin(); it != d_rep.end(); ++it ){
- if( !(*it).second.isNull() ){
- reps.push_back( (*it).first );
- }
- }
-}
-
-
-/** add split function */
-bool StrongSolverTheoryUf::InfRepModel::addSplit( OutputChannel* out ){
- std::vector< Node > visited;
- for( NodeNodeMap::iterator it = d_rep.begin(); it != d_rep.end(); ++it ){
- Node rep = (*it).second;
- if( !rep.isNull() && !isBadRepresentative( rep ) ){
- bool constRep = rep.getMetaKind()==metakind::CONSTANT;
- for( size_t i=0; i<visited.size(); i++ ){
- if( !constRep || !visited[i].getMetaKind()==metakind::CONSTANT ){
- if( !d_th->getQuantifiersEngine()->getEqualityQuery()->areDisequal( rep, visited[i] ) ){
- //split on these nodes
- Node eq = rep.eqNode( visited[i] );
- Trace("uf-ss-lemma") << "*** Split on " << eq << std::endl;
- eq = Rewriter::rewrite( eq );
- Debug("uf-ss-lemma-debug") << "Rewritten " << eq << std::endl;
- out->split( eq );
- //explore the equals branch first
- out->requirePhase( eq, true );
- ++( d_th->getStrongSolver()->d_statistics.d_split_lemmas );
- return true;
- }
- }
- }
- visited.push_back( rep );
- }
- }
- return false;
-}
-
-bool StrongSolverTheoryUf::InfRepModel::isBadRepresentative( Node n ){
- return n.getKind()==kind::PLUS;
+ //}else{
+ // Unimplemented("Build representatives for fmf region sat is not implemented");
+ //}
}
StrongSolverTheoryUf::StrongSolverTheoryUf(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th) :
@@ -1438,6 +1384,13 @@ void StrongSolverTheoryUf::check( Theory::Effort level ){
if( level==Theory::EFFORT_FULL ){
debugPrint( "uf-ss-debug" );
}
+ if( !d_conflict && level==Theory::EFFORT_FULL && options::ufssColoringSat() ){
+ int lemmas = d_term_amb->disambiguateTerms( d_out );
+ d_statistics.d_disamb_term_lemmas += lemmas;
+ if( lemmas>=0 ){
+ return;
+ }
+ }
for( std::map< TypeNode, RepModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
it->second->check( level, d_out );
if( it->second->isConflict() ){
@@ -1446,10 +1399,10 @@ void StrongSolverTheoryUf::check( Theory::Effort level ){
}
}
//disambiguate terms if necessary
- if( !d_conflict && level==Theory::EFFORT_FULL && options::ufssColoringSat() ){
- Assert( d_term_amb!=NULL );
- d_statistics.d_disamb_term_lemmas += d_term_amb->disambiguateTerms( d_out );
- }
+ //if( !d_conflict && level==Theory::EFFORT_FULL && options::ufssColoringSat() ){
+ // Assert( d_term_amb!=NULL );
+ // d_statistics.d_disamb_term_lemmas += d_term_amb->disambiguateTerms( d_out );
+ //}
Trace("uf-ss-solver") << "Done StrongSolverTheoryUf: check " << level << std::endl;
}
}
@@ -1481,9 +1434,6 @@ void StrongSolverTheoryUf::preRegisterTerm( TNode n ){
if( tn.isSort() ){
Trace("uf-ss-register") << "Preregister sort " << tn << "." << std::endl;
rm = new SortRepModel( n, d_th->getSatContext(), d_th );
- }else if( tn.isInteger() ){
- //rm = new InfRepModel( tn, d_th->getSatContext(), d_th );
- //rm = new SortRepModel( tn, d_th->getSatContext(), d_th );
}else{
/*
if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
@@ -1603,12 +1553,14 @@ void StrongSolverTheoryUf::debugModel( TheoryModel* m ){
}
StrongSolverTheoryUf::Statistics::Statistics():
+ d_clique_conflicts("StrongSolverTheoryUf::Clique_Conflicts", 0),
d_clique_lemmas("StrongSolverTheoryUf::Clique_Lemmas", 0),
d_split_lemmas("StrongSolverTheoryUf::Split_Lemmas", 0),
d_disamb_term_lemmas("StrongSolverTheoryUf::Disambiguate_Term_Lemmas", 0),
d_totality_lemmas("StrongSolverTheoryUf::Totality_Lemmas", 0),
d_max_model_size("StrongSolverTheoryUf::Max_Model_Size", 1)
{
+ StatisticsRegistry::registerStat(&d_clique_conflicts);
StatisticsRegistry::registerStat(&d_clique_lemmas);
StatisticsRegistry::registerStat(&d_split_lemmas);
StatisticsRegistry::registerStat(&d_disamb_term_lemmas);
@@ -1617,6 +1569,7 @@ StrongSolverTheoryUf::Statistics::Statistics():
}
StrongSolverTheoryUf::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_clique_conflicts);
StatisticsRegistry::unregisterStat(&d_clique_lemmas);
StatisticsRegistry::unregisterStat(&d_split_lemmas);
StatisticsRegistry::unregisterStat(&d_disamb_term_lemmas);
@@ -1667,11 +1620,12 @@ int TermDisambiguator::disambiguateTerms( OutputChannel* out ){
}
Assert( children.size()>1 );
Node lem = NodeManager::currentNM()->mkNode( OR, children );
- Debug( "uf-ss-lemma" ) << "*** Disambiguate lemma : " << lem << std::endl;
+ Trace( "uf-ss-lemma" ) << "*** Disambiguate lemma : " << lem << std::endl;
//Notice() << "*** Disambiguate lemma : " << lem << std::endl;
out->lemma( lem );
d_term_amb[ eq ] = false;
lemmaAdded++;
+ return lemmaAdded;
}
}
}
diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h
index febae2eae..ceb59d5c3 100644
--- a/src/theory/uf/theory_uf_strong_solver.h
+++ b/src/theory/uf/theory_uf_strong_solver.h
@@ -213,7 +213,7 @@ public:
void setSplitScore( Node n, int s );
private:
/** check if we need to combine region ri */
- void checkRegion( int ri, bool rec = true );
+ void checkRegion( int ri, bool checkCombine = true );
/** force combine region */
int forceCombineRegion( int ri, bool useDensity = true );
/** merge regions */
@@ -293,42 +293,6 @@ public:
int getNumRegions();
}; /** class SortRepModel */
private:
- /** infinite rep model */
- class InfRepModel : public RepModel
- {
- protected:
- /** theory uf pointer */
- TheoryUF* d_th;
- /** list of representatives */
- NodeNodeMap d_rep;
- /** whether representatives are constant */
- NodeBoolMap d_const_rep;
- /** add split */
- bool addSplit( OutputChannel* out );
- /** is bad representative */
- bool isBadRepresentative( Node n );
- public:
- InfRepModel( TypeNode tn, context::Context* c, TheoryUF* th ) : RepModel( tn ),
- d_th( th ), d_rep( c ), d_const_rep( c ){}
- virtual ~InfRepModel(){}
- /** initialize */
- void initialize( OutputChannel* out );
- /** new node */
- void newEqClass( Node n );
- /** merge */
- void merge( Node a, Node b );
- /** assert terms are disequal */
- void assertDisequal( Node a, Node b, Node reason ){}
- /** check */
- void check( Theory::Effort level, OutputChannel* out );
- /** minimize */
- bool minimize( OutputChannel* out );
- /** get representatives */
- void getRepresentatives( std::vector< Node >& reps );
- /** print debug */
- void debugPrint( const char* c ){}
- };
-private:
/** The output channel for the strong solver. */
OutputChannel* d_out;
/** theory uf pointer */
@@ -393,6 +357,7 @@ public:
class Statistics {
public:
+ IntStat d_clique_conflicts;
IntStat d_clique_lemmas;
IntStat d_split_lemmas;
IntStat d_disamb_term_lemmas;
diff --git a/src/util/dense_map.h b/src/util/dense_map.h
index fa78e6787..222a761c3 100644
--- a/src/util/dense_map.h
+++ b/src/util/dense_map.h
@@ -151,6 +151,7 @@ public:
pop_back();
}
+ /** Returns the key at the back of a non-empty list.*/
Key back() const {
return d_list.back();
}
@@ -164,6 +165,27 @@ public:
d_list.pop_back();
}
+
+ /** Adds at least a constant fraction of the elements in the current map to another map. */
+ void splitInto(DenseMap<T>& target){
+ uint32_t targetSize = size()/2;
+ while(size() > targetSize){
+ Key key = back();
+ target.set(key, get(key));
+ pop_back();
+ }
+ }
+
+ /** Adds the current target map to the current map.*/
+ void addAll(const DenseMap<T>& target){
+ for(const_iterator i = target.begin(), e = target.end(); i != e; ++i){
+ Key k = *i;
+ set(k, target[k]);
+ }
+ }
+
+
+
private:
size_t allocated() const {
diff --git a/src/util/node_visitor.h b/src/util/node_visitor.h
index e444ba6e2..4c8e646bd 100644
--- a/src/util/node_visitor.h
+++ b/src/util/node_visitor.h
@@ -36,10 +36,11 @@ class NodeVisitor {
/**
* Guard against NodeVisitor<> being re-entrant.
*/
+ template <class T>
class GuardReentry {
- bool& d_guard;
+ T& d_guard;
public:
- GuardReentry(bool& guard)
+ GuardReentry(T& guard)
: d_guard(guard) {
Assert(!d_guard);
d_guard = true;
@@ -71,7 +72,7 @@ public:
*/
static typename Visitor::return_type run(Visitor& visitor, TNode node) {
- GuardReentry guard(bool(s_inRun));
+ GuardReentry<CVC4_THREADLOCAL_TYPE(bool)> guard(s_inRun);
// Notify of a start
visitor.start(node);
diff --git a/src/util/record.h b/src/util/record.h
index 2c15d30e0..27b090e1d 100644
--- a/src/util/record.h
+++ b/src/util/record.h
@@ -29,7 +29,7 @@
namespace CVC4 {
-class Record;
+class CVC4_PUBLIC Record;
// operators for record select and update
diff --git a/src/util/sort_inference.cpp b/src/util/sort_inference.cpp
index 2a037a020..0304a8e35 100755..100644
--- a/src/util/sort_inference.cpp
+++ b/src/util/sort_inference.cpp
@@ -1,11 +1,11 @@
/********************* */
/*! \file sort_inference.cpp
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
@@ -58,6 +58,14 @@ void SortInference::simplify( std::vector< Node >& assertions, bool doRewrite ){
printSort( "sort-inference", it->second );
Trace("sort-inference") << std::endl;
}
+ for( std::map< Node, std::map< Node, int > >::iterator it = d_var_types.begin(); it != d_var_types.end(); ++it ){
+ Trace("sort-inference") << "Quantified formula " << it->first << " : " << std::endl;
+ for( std::map< Node, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
+ printSort( "sort-inference", it2->second );
+ Trace("sort-inference") << std::endl;
+ }
+ Trace("sort-inference") << std::endl;
+ }
}
if( doRewrite ){
//simplify all assertions by introducing new symbols wherever necessary (NOTE: this is unsound for quantifiers)
@@ -149,11 +157,11 @@ int SortInference::process( Node n, std::map< Node, Node >& var_bound ){
if( n.getKind()==kind::FORALL || n.getKind()==kind::EXISTS ){
for( size_t i=0; i<n[0].getNumChildren(); i++ ){
//TODO: try applying sort inference to quantified variables
- //d_var_types[n][ n[0][i] ] = sortCount;
- //sortCount++;
+ d_var_types[n][ n[0][i] ] = sortCount;
+ sortCount++;
//type of the quantified variable must be the same
- d_var_types[n][ n[0][i] ] = getIdForType( n[0][i].getType() );
+ //d_var_types[n][ n[0][i] ] = getIdForType( n[0][i].getType() );
var_bound[ n[0][i] ] = n;
}
}
@@ -404,5 +412,17 @@ Node SortInference::simplify( Node n, std::map< Node, Node >& var_bound ){
}
}
+int SortInference::getSortId( Node n ) {
+ Node op = n.getKind()==kind::APPLY_UF ? n.getOperator() : n;
+ return getRepresentative( d_op_return_types[op] );
+}
+
+int SortInference::getSortId( Node f, Node v ) {
+ return getRepresentative( d_var_types[f][v] );
+}
+void SortInference::setSkolemVar( Node f, Node v, Node sk ){
+ d_op_return_types[sk] = getSortId( f, v );
}
+
+} \ No newline at end of file
diff --git a/src/util/sort_inference.h b/src/util/sort_inference.h
index 1873688fa..0b1f96f85 100755..100644
--- a/src/util/sort_inference.h
+++ b/src/util/sort_inference.h
@@ -1,11 +1,11 @@
/********************* */
/*! \file sort_inference.h
** \verbatim
- ** Original author: ajreynol
- ** Major contributors: none
+ ** Original author: Andrew Reynolds <andrew.j.reynolds@gmail.com>
+ ** Major contributors: Morgan Deters <mdeters@cs.nyu.edu>
** Minor contributors (to current version): none
- ** This file is part of the CVC4 prototype.
- ** Copyright (c) 2009-2012 New York University and The University of Iowa
+ ** This file is part of the CVC4 project.
+ ** Copyright (c) 2009-2013 New York University and The University of Iowa
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
@@ -65,6 +65,10 @@ public:
~SortInference(){}
void simplify( std::vector< Node >& assertions, bool doRewrite = false );
+ int getSortId( Node n );
+ int getSortId( Node f, Node v );
+ //set that sk is the skolem variable of v for quantifier f
+ void setSkolemVar( Node f, Node v, Node sk );
};
}
diff --git a/src/util/statistics_registry.h b/src/util/statistics_registry.h
index 3bf990dbb..af9088663 100644
--- a/src/util/statistics_registry.h
+++ b/src/util/statistics_registry.h
@@ -23,6 +23,7 @@
#include "util/statistics.h"
#include "util/exception.h"
+#include "lib/clock_gettime.h"
#include <sstream>
#include <iomanip>
@@ -612,12 +613,17 @@ public:
};/* class StatisticsRegistry */
+}/* CVC4 namespace */
+
/****************************************************************************/
/* Some utility functions for timespec */
/****************************************************************************/
+inline std::ostream& operator<<(std::ostream& os, const timespec& t);
+
/** Compute the sum of two timespecs. */
inline timespec& operator+=(timespec& a, const timespec& b) {
+ using namespace CVC4;
// assumes a.tv_nsec and b.tv_nsec are in range
const long nsec_per_sec = 1000000000L; // one thousand million
CheckArgument(a.tv_nsec >= 0 && a.tv_nsec < nsec_per_sec, a);
@@ -640,6 +646,7 @@ inline timespec& operator+=(timespec& a, const timespec& b) {
/** Compute the difference of two timespecs. */
inline timespec& operator-=(timespec& a, const timespec& b) {
+ using namespace CVC4;
// assumes a.tv_nsec and b.tv_nsec are in range
const long nsec_per_sec = 1000000000L; // one thousand million
CheckArgument(a.tv_nsec >= 0 && a.tv_nsec < nsec_per_sec, a);
@@ -716,6 +723,8 @@ inline std::ostream& operator<<(std::ostream& os, const timespec& t) {
<< std::setfill('0') << std::setw(8) << std::right << t.tv_nsec;
}
+namespace CVC4 {
+
class CodeTimer;
/**
@@ -765,7 +774,6 @@ public:
};/* class TimerStat */
-
/**
* Utility class to make it easier to call stop() at the end of a
* code block. When constructed, it starts the timer. When
@@ -788,7 +796,6 @@ public:
}
};/* class CodeTimer */
-
/**
* To use a statistic, you need to declare it, initialize it in your
* constructor, register it in your constructor, and deregister it in
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback