summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKshitij Bansal <kshitij@cs.nyu.edu>2015-09-02 09:07:38 -0400
committerKshitij Bansal <kshitij@cs.nyu.edu>2015-09-02 09:07:38 -0400
commit1ea1262c394c623d64ea2cab33681a16a1aec8a6 (patch)
tree12b97d6ee900ae8ba580b09222150f89dbe90da5 /src
parentebaa44a4b93b00614b41ef38f36112883ee27626 (diff)
parent6f9186c6eac5ce04c6ff3318e807909031528f59 (diff)
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src')
-rw-r--r--src/smt/smt_engine.cpp17
-rw-r--r--src/theory/bv/bitblast_strategies_template.h8
-rw-r--r--src/theory/bv/bv_subtheory_algebraic.cpp7
-rw-r--r--src/theory/bv/bv_subtheory_core.cpp13
-rw-r--r--src/theory/bv/bv_subtheory_core.h3
-rw-r--r--src/theory/bv/eager_bitblaster.cpp3
-rw-r--r--src/theory/bv/theory_bv_utils.cpp15
-rw-r--r--src/theory/bv/theory_bv_utils.h2
-rw-r--r--src/theory/datatypes/theory_datatypes.cpp4
-rw-r--r--src/theory/quantifiers/ce_guided_instantiation.cpp59
-rw-r--r--src/theory/quantifiers/ce_guided_instantiation.h10
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv.cpp112
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv.h12
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv_sol.cpp90
-rw-r--r--src/theory/quantifiers/ce_guided_single_inv_sol.h7
-rw-r--r--src/theory/quantifiers/inst_strategy_cbqi.cpp1045
-rw-r--r--src/theory/quantifiers/inst_strategy_cbqi.h51
-rw-r--r--src/theory/quantifiers/instantiation_engine.cpp29
-rw-r--r--src/theory/quantifiers/instantiation_engine.h6
-rw-r--r--src/theory/quantifiers/options20
-rw-r--r--src/theory/quantifiers/quant_util.cpp31
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp159
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.h2
-rw-r--r--src/theory/quantifiers/term_database.cpp240
-rw-r--r--src/theory/quantifiers/term_database.h26
-rw-r--r--src/theory/quantifiers/theory_quantifiers.cpp5
-rw-r--r--src/theory/quantifiers_engine.cpp22
-rw-r--r--src/theory/quantifiers_engine.h4
-rw-r--r--src/theory/strings/theory_strings_rewriter.cpp5
-rw-r--r--src/theory/theory_engine.h9
-rw-r--r--src/theory/uf/theory_uf_strong_solver.cpp1
31 files changed, 1363 insertions, 654 deletions
diff --git a/src/smt/smt_engine.cpp b/src/smt/smt_engine.cpp
index 66487e4a4..be3df349a 100644
--- a/src/smt/smt_engine.cpp
+++ b/src/smt/smt_engine.cpp
@@ -85,6 +85,7 @@
#include "theory/quantifiers/macros.h"
#include "theory/quantifiers/fun_def_process.h"
#include "theory/quantifiers/quantifiers_rewriter.h"
+#include "theory/quantifiers/ce_guided_instantiation.h"
#include "theory/quantifiers/options.h"
#include "theory/datatypes/options.h"
#include "theory/strings/theory_strings_preprocess.h"
@@ -1375,9 +1376,6 @@ void SmtEngine::setDefaults() {
if( !options::eMatching.wasSetByUser() ){
options::eMatching.set( options::fmfInstEngine() );
}
- if( !options::quantConflictFind.wasSetByUser() ){
- options::quantConflictFind.set( false );
- }
if( ! options::instWhenMode.wasSetByUser()){
//instantiate only on last call
if( options::eMatching() ){
@@ -1431,6 +1429,9 @@ void SmtEngine::setDefaults() {
if( !options::macrosQuant.wasSetByUser()) {
options::macrosQuant.set( false );
}
+ if( !options::cbqiPreRegInst.wasSetByUser()) {
+ options::cbqiPreRegInst.set( true );
+ }
}
//cbqi options
@@ -1440,7 +1441,7 @@ void SmtEngine::setDefaults() {
options::cbqi2.set( true );
}
}
- if( options::recurseCbqi() || options::cbqi2() ){
+ if( options::cbqi2() ){
options::cbqi.set( true );
}
if( options::cbqi2() ){
@@ -3179,6 +3180,13 @@ void SmtEnginePrivate::processAssertions() {
Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
+ if( options::ceGuidedInst() ){
+ //register sygus conjecture pre-rewrite (motivated by solution reconstruction)
+ for (unsigned i = 0; i < d_assertions.size(); ++ i) {
+ d_smt.d_theoryEngine->getQuantifiersEngine()->getCegInstantiation()->preregisterAssertion( d_assertions[i] );
+ }
+ }
+
if (options::bitblastMode() == theory::bv::BITBLAST_MODE_EAGER &&
!d_smt.d_logic.isPure(THEORY_BV)) {
throw ModalException("Eager bit-blasting does not currently support theory combination. "
@@ -4402,6 +4410,7 @@ void SmtEngine::printSynthSolution( std::ostream& out ) {
vector<Expr> SmtEngine::getAssertions() throw(ModalException) {
SmtScope smts(this);
finalOptionsAreSet();
+ doPendingPops();
if(Dump.isOn("benchmark")) {
Dump("benchmark") << GetAssertionsCommand();
}
diff --git a/src/theory/bv/bitblast_strategies_template.h b/src/theory/bv/bitblast_strategies_template.h
index 62c92c0a8..0990c2f29 100644
--- a/src/theory/bv/bitblast_strategies_template.h
+++ b/src/theory/bv/bitblast_strategies_template.h
@@ -536,8 +536,8 @@ void DefaultUdivBB (TNode node, std::vector<T>& q, TBitblaster<T>* bb) {
T b_is_0 = mkAnd(iszero);
for (unsigned i = 0; i < q.size(); ++i) {
- q[i] = mkIte(b_is_0, mkTrue<T>(), q[i]);
- r[i] = mkIte(b_is_0, mkTrue<T>(), r[i]);
+ q[i] = mkIte(b_is_0, mkTrue<T>(), q[i]); // a udiv 0 is 11..11
+ r[i] = mkIte(b_is_0, a[i], r[i]); // a urem 0 is a
}
// cache the remainder in case we need it later
@@ -564,8 +564,8 @@ void DefaultUremBB (TNode node, std::vector<T>& rem, TBitblaster<T>* bb) {
T b_is_0 = mkAnd(iszero);
for (unsigned i = 0; i < q.size(); ++i) {
- q[i] = mkIte(b_is_0, a[i], q[i]);
- rem[i] = mkIte(b_is_0, a[i], rem[i]);
+ q[i] = mkIte(b_is_0, mkTrue<T>(), q[i]); // a udiv 0 is 11..11
+ rem[i] = mkIte(b_is_0, a[i], rem[i]); // a urem 0 is a
}
// cache the quotient in case we need it later
diff --git a/src/theory/bv/bv_subtheory_algebraic.cpp b/src/theory/bv/bv_subtheory_algebraic.cpp
index 96b205bb1..e6e3120f5 100644
--- a/src/theory/bv/bv_subtheory_algebraic.cpp
+++ b/src/theory/bv/bv_subtheory_algebraic.cpp
@@ -684,16 +684,19 @@ void AlgebraicSolver::collectModelInfo(TheoryModel* model, bool fullModel) {
}
}
+ NodeSet leaf_vars;
Debug("bitvector-model") << "Substitutions:\n";
for (unsigned i = 0; i < variables.size(); ++i) {
TNode current = variables[i];
TNode subst = Rewriter::rewrite(d_modelMap->apply(current));
Debug("bitvector-model") << " " << current << " => " << subst << "\n";
values[i] = subst;
+ utils::collectVariables(subst, leaf_vars);
}
Debug("bitvector-model") << "Model:\n";
- for (BVQuickCheck::vars_iterator it = d_quickSolver->beginVars(); it != d_quickSolver->endVars(); ++it) {
+
+ for (NodeSet::const_iterator it = leaf_vars.begin(); it != leaf_vars.end(); ++it) {
TNode var = *it;
Node value = d_quickSolver->getVarValue(var, true);
Assert (!value.isNull() || !fullModel);
@@ -712,7 +715,7 @@ void AlgebraicSolver::collectModelInfo(TheoryModel* model, bool fullModel) {
TNode subst = Rewriter::rewrite(d_modelMap->apply(current));
Debug("bitvector-model") << "AlgebraicSolver: " << variables[i] << " => " << subst << "\n";
// Doesn't have to be constant as it may be irrelevant
- // Assert (subst.getKind() == kind::CONST_BITVECTOR);
+ Assert (subst.getKind() == kind::CONST_BITVECTOR);
model->assertEquality(variables[i], subst, true);
}
diff --git a/src/theory/bv/bv_subtheory_core.cpp b/src/theory/bv/bv_subtheory_core.cpp
index 13c31463b..6ae0ffb71 100644
--- a/src/theory/bv/bv_subtheory_core.cpp
+++ b/src/theory/bv/bv_subtheory_core.cpp
@@ -36,6 +36,7 @@ CoreSolver::CoreSolver(context::Context* c, TheoryBV* bv)
d_equalityEngine(d_notify, c, "theory::bv::TheoryBV", true),
d_slicer(new Slicer()),
d_isComplete(c, true),
+ d_lemmaThreshold(16),
d_useSlicer(false),
d_preregisterCalled(false),
d_checkCalled(false),
@@ -276,16 +277,28 @@ void CoreSolver::buildModel() {
for (unsigned j = i + 1; j < representatives.size(); ++j) {
TNode a = representatives[i];
TNode b = representatives[j];
+ if (a.getKind() == kind::CONST_BITVECTOR &&
+ b.getKind() == kind::CONST_BITVECTOR) {
+ Assert (a != b);
+ continue;
+ }
if (utils::getSize(a) == utils::getSize(b)) {
equalities.push_back(utils::mkNode(kind::EQUAL, a, b));
}
}
}
+ // better off letting the SAT solver split on values
+ if (equalities.size() > d_lemmaThreshold) {
+ d_isComplete = false;
+ return;
+ }
+
Node lemma = utils::mkOr(equalities);
d_bv->lemma(lemma);
Debug("bv-core") << " lemma: " << lemma << "\n";
return;
}
+
Debug("bv-core-model") << " " << repr << " => " << val <<"\n" ;
constants.insert(val);
d_modelValues[repr] = val;
diff --git a/src/theory/bv/bv_subtheory_core.h b/src/theory/bv/bv_subtheory_core.h
index 5b9c54095..0ff193b41 100644
--- a/src/theory/bv/bv_subtheory_core.h
+++ b/src/theory/bv/bv_subtheory_core.h
@@ -74,9 +74,10 @@ class CoreSolver : public SubtheorySolver {
Slicer* d_slicer;
context::CDO<bool> d_isComplete;
+ unsigned d_lemmaThreshold;
/** Used to ensure that the core slicer is used properly*/
- bool d_useSlicer;
+ bool d_useSlicer;
bool d_preregisterCalled;
bool d_checkCalled;
diff --git a/src/theory/bv/eager_bitblaster.cpp b/src/theory/bv/eager_bitblaster.cpp
index eca9f12ab..3f076bd4c 100644
--- a/src/theory/bv/eager_bitblaster.cpp
+++ b/src/theory/bv/eager_bitblaster.cpp
@@ -187,7 +187,8 @@ void EagerBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
TNodeSet::iterator it = d_variables.begin();
for (; it!= d_variables.end(); ++it) {
TNode var = *it;
- if (d_bv->isLeaf(var) || isSharedTerm(var)) {
+ if (d_bv->isLeaf(var) || isSharedTerm(var) ||
+ (var.isVar() && var.getType().isBoolean())) {
// only shared terms could not have been bit-blasted
Assert (hasBBTerm(var) || isSharedTerm(var));
diff --git a/src/theory/bv/theory_bv_utils.cpp b/src/theory/bv/theory_bv_utils.cpp
index 824dc5b92..d2025b1b8 100644
--- a/src/theory/bv/theory_bv_utils.cpp
+++ b/src/theory/bv/theory_bv_utils.cpp
@@ -100,3 +100,18 @@ uint64_t CVC4::theory::bv::utils::numNodes(TNode node, NodeSet& seen) {
seen.insert(node);
return size;
}
+
+
+
+void CVC4::theory::bv::utils::collectVariables(TNode node, NodeSet& vars) {
+ if (vars.find(node) != vars.end())
+ return;
+
+ if (Theory::isLeafOf(node, THEORY_BV) && node.getKind() != kind::CONST_BITVECTOR) {
+ vars.insert(node);
+ return;
+ }
+ for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+ collectVariables(node[i], vars);
+ }
+}
diff --git a/src/theory/bv/theory_bv_utils.h b/src/theory/bv/theory_bv_utils.h
index a8b6887e5..ba8074fbb 100644
--- a/src/theory/bv/theory_bv_utils.h
+++ b/src/theory/bv/theory_bv_utils.h
@@ -513,6 +513,8 @@ typedef __gnu_cxx::hash_set<Node, NodeHashFunction> NodeSet;
uint64_t numNodes(TNode node, NodeSet& seen);
+void collectVariables(TNode node, NodeSet& vars);
+
}
}
}
diff --git a/src/theory/datatypes/theory_datatypes.cpp b/src/theory/datatypes/theory_datatypes.cpp
index 371f27c95..e0a4dc7d8 100644
--- a/src/theory/datatypes/theory_datatypes.cpp
+++ b/src/theory/datatypes/theory_datatypes.cpp
@@ -1414,11 +1414,15 @@ void TheoryDatatypes::collectModelInfo( TheoryModel* m, bool fullModel ){
Node eqc = it->first;
const Datatype& dt = ((DatatypeType)(eqc.getType()).toType()).getDatatype();
if( dt.isCodatatype() ){
+ //until models are implemented for codatatypes
+ throw Exception("Models for codatatypes are not supported in this version.");
+ /*
std::map< Node, Node > vmap;
std::vector< Node > fv;
Node v = getCodatatypesValue( it->first, eqc_cons, eqc_mu, vmap, fv );
Trace("dt-cmi-cdt") << " EQC(" << it->first << "), constructor is " << it->second << ", value is " << v << ", const = " << v.isConst() << std::endl;
//m->assertEquality( eqc, v, true );
+ */
}
}
}
diff --git a/src/theory/quantifiers/ce_guided_instantiation.cpp b/src/theory/quantifiers/ce_guided_instantiation.cpp
index e10ba0fef..0bc5bb008 100644
--- a/src/theory/quantifiers/ce_guided_instantiation.cpp
+++ b/src/theory/quantifiers/ce_guided_instantiation.cpp
@@ -29,18 +29,18 @@ using namespace std;
namespace CVC4 {
-CegConjecture::CegConjecture( context::Context* c ) : d_active( c, false ), d_infeasible( c, false ), d_curr_lit( c, 0 ){
+CegConjecture::CegConjecture( QuantifiersEngine * qe, context::Context* c ) : d_qe( qe ), d_active( c, false ), d_infeasible( c, false ), d_curr_lit( c, 0 ){
d_refine_count = 0;
- d_ceg_si = new CegConjectureSingleInv( this );
+ d_ceg_si = new CegConjectureSingleInv( qe, this );
}
-void CegConjecture::assign( QuantifiersEngine * qe, Node q ) {
+void CegConjecture::assign( Node q ) {
Assert( d_quant.isNull() );
Assert( q.getKind()==FORALL );
d_assert_quant = q;
//register with single invocation if applicable
- if( qe->getTermDatabase()->isQAttrSygus( d_assert_quant ) && options::cegqiSingleInv() ){
- d_ceg_si->initialize( qe, q );
+ if( d_qe->getTermDatabase()->isQAttrSygus( d_assert_quant ) && options::cegqiSingleInv() ){
+ d_ceg_si->initialize( q );
if( q!=d_ceg_si->d_quant ){
//Node red_lem = NodeManager::currentNM()->mkNode( OR, q.negate(), d_cegqi_si->d_quant );
//may have rewritten quantified formula (for invariant synthesis)
@@ -53,9 +53,9 @@ void CegConjecture::assign( QuantifiersEngine * qe, Node q ) {
}
Trace("cegqi") << "Base quantified fm is : " << q << std::endl;
//construct base instantiation
- d_base_inst = Rewriter::rewrite( qe->getInstantiation( q, d_candidates ) );
+ d_base_inst = Rewriter::rewrite( d_qe->getInstantiation( q, d_candidates ) );
Trace("cegqi") << "Base instantiation is : " << d_base_inst << std::endl;
- if( qe->getTermDatabase()->isQAttrSygus( d_assert_quant ) ){
+ if( d_qe->getTermDatabase()->isQAttrSygus( d_assert_quant ) ){
CegInstantiation::collectDisjuncts( d_base_inst, d_base_disj );
Trace("cegqi") << "Conjecture has " << d_base_disj.size() << " disjuncts." << std::endl;
//store the inner variables for each disjunct
@@ -70,7 +70,7 @@ void CegConjecture::assign( QuantifiersEngine * qe, Node q ) {
}
}
d_syntax_guided = true;
- }else if( qe->getTermDatabase()->isQAttrSynthesis( d_assert_quant ) ){
+ }else if( d_qe->getTermDatabase()->isQAttrSynthesis( d_assert_quant ) ){
d_syntax_guided = false;
}else{
Assert( false );
@@ -87,16 +87,17 @@ void CegConjecture::initializeGuard( QuantifiersEngine * qe ){
if( !d_syntax_guided ){
//add immediate lemma
Node lem = NodeManager::currentNM()->mkNode( OR, d_guard.negate(), d_base_inst.negate() );
- Trace("cegqi") << "Add candidate lemma : " << lem << std::endl;
+ Trace("cegqi-lemma") << "Add candidate lemma : " << lem << std::endl;
qe->getOutputChannel().lemma( lem );
}else if( d_ceg_si ){
- Node lem = d_ceg_si->getSingleInvLemma( d_guard );
- if( !lem.isNull() ){
- Trace("cegqi") << "Add single invocation lemma : " << lem << std::endl;
- qe->getOutputChannel().lemma( lem );
+ std::vector< Node > lems;
+ d_ceg_si->getSingleInvLemma( d_guard, lems );
+ for( unsigned i=0; i<lems.size(); i++ ){
+ Trace("cegqi-lemma") << "Add single invocation lemma " << i << " : " << lems[i] << std::endl;
+ qe->getOutputChannel().lemma( lems[i] );
if( Trace.isOn("cegqi-debug") ){
- lem = Rewriter::rewrite( lem );
- Trace("cegqi-debug") << "...rewritten : " << lem << std::endl;
+ Node rlem = Rewriter::rewrite( lems[i] );
+ Trace("cegqi-debug") << "...rewritten : " << rlem << std::endl;
}
}
}
@@ -149,8 +150,12 @@ bool CegConjecture::needsCheck() {
return d_active && !d_infeasible && ( !isSingleInvocation() || d_ceg_si->needsCheck() );
}
+void CegConjecture::preregisterConjecture( Node q ) {
+ d_ceg_si->preregisterConjecture( q );
+}
+
CegInstantiation::CegInstantiation( QuantifiersEngine * qe, context::Context* c ) : QuantifiersModule( qe ){
- d_conj = new CegConjecture( qe->getSatContext() );
+ d_conj = new CegConjecture( qe, qe->getSatContext() );
d_last_inst_si = false;
}
@@ -178,7 +183,7 @@ void CegInstantiation::registerQuantifier( Node q ) {
if( d_quantEngine->getOwner( q )==this ){
if( !d_conj->isAssigned() ){
Trace("cegqi") << "Register conjecture : " << q << std::endl;
- d_conj->assign( d_quantEngine, q );
+ d_conj->assign( q );
//fairness
if( d_conj->getCegqiFairMode()!=CEGQI_FAIR_NONE ){
@@ -279,7 +284,7 @@ void CegInstantiation::checkCegConjecture( CegConjecture * conj ) {
if( !lems.empty() ){
d_last_inst_si = true;
for( unsigned j=0; j<lems.size(); j++ ){
- Trace("cegqi-lemma") << "Single invocation lemma : " << lems[j] << std::endl;
+ Trace("cegqi-lemma") << "Single invocation instantiation lemma : " << lems[j] << std::endl;
d_quantEngine->addLemma( lems[j] );
}
d_statistics.d_cegqi_si_lemmas += lems.size();
@@ -591,6 +596,24 @@ void CegInstantiation::collectDisjuncts( Node n, std::vector< Node >& d ) {
}
}
+void CegInstantiation::preregisterAssertion( Node n ) {
+ //check if it sygus conjecture
+ if( n.getKind()==FORALL ){
+ if( n.getNumChildren()==3 ){
+ for( unsigned i=0; i<n[2].getNumChildren(); i++ ){
+ if( n[2][i].getKind()==INST_ATTRIBUTE ){
+ Node avar = n[2][i][0];
+ if( avar.getAttribute(SygusAttribute()) ){
+ //this is a sygus conjecture
+ Trace("cegqi") << "Preregister sygus conjecture : " << n << std::endl;
+ d_conj->preregisterConjecture( n );
+ }
+ }
+ }
+ }
+ }
+}
+
CegInstantiation::Statistics::Statistics():
d_cegqi_lemmas_ce("CegInstantiation::cegqi_lemmas_ce", 0),
d_cegqi_lemmas_refine("CegInstantiation::cegqi_lemmas_refine", 0),
diff --git a/src/theory/quantifiers/ce_guided_instantiation.h b/src/theory/quantifiers/ce_guided_instantiation.h
index af3a19d62..8aa2e2c26 100644
--- a/src/theory/quantifiers/ce_guided_instantiation.h
+++ b/src/theory/quantifiers/ce_guided_instantiation.h
@@ -29,8 +29,10 @@ namespace quantifiers {
/** a synthesis conjecture */
class CegConjecture {
+private:
+ QuantifiersEngine * d_qe;
public:
- CegConjecture( context::Context* c );
+ CegConjecture( QuantifiersEngine * qe, context::Context* c );
/** is conjecture active */
context::CDO< bool > d_active;
/** is conjecture infeasible */
@@ -65,7 +67,7 @@ public:
/** refine count */
unsigned d_refine_count;
/** assign */
- void assign( QuantifiersEngine * qe, Node q );
+ void assign( Node q );
/** is assigned */
bool isAssigned() { return !d_quant.isNull(); }
/** current extential quantifeirs whose couterexamples we must refine */
@@ -87,6 +89,8 @@ public: //for fairness
bool isSingleInvocation();
/** needs check */
bool needsCheck();
+ /** preregister conjecture */
+ void preregisterConjecture( Node q );
};
@@ -137,6 +141,8 @@ public:
void printSynthSolution( std::ostream& out );
/** collect disjuncts */
static void collectDisjuncts( Node n, std::vector< Node >& ex );
+ /** preregister assertion (before rewrite) */
+ void preregisterAssertion( Node n );
public:
class Statistics {
public:
diff --git a/src/theory/quantifiers/ce_guided_single_inv.cpp b/src/theory/quantifiers/ce_guided_single_inv.cpp
index 17d85eb9b..19cf9b008 100644
--- a/src/theory/quantifiers/ce_guided_single_inv.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv.cpp
@@ -45,14 +45,21 @@ bool CegqiOutputSingleInv::addLemma( Node n ) {
}
-CegConjectureSingleInv::CegConjectureSingleInv( CegConjecture * p ) : d_parent( p ){
- d_sol = NULL;
- d_c_inst_match_trie = NULL;
- d_cinst = NULL;
+CegConjectureSingleInv::CegConjectureSingleInv( QuantifiersEngine * qe, CegConjecture * p ) : d_qe( qe ), d_parent( p ){
d_has_ites = true;
+ if( options::incrementalSolving() ){
+ d_c_inst_match_trie = new inst::CDInstMatchTrie( qe->getUserContext() );
+ }else{
+ d_c_inst_match_trie = NULL;
+ }
+ CegqiOutputSingleInv * cosi = new CegqiOutputSingleInv( this );
+ // third and fourth arguments set to (false,false) until we have solution reconstruction for delta and infinity
+ d_cinst = new CegInstantiator( qe, cosi, false, false );
+
+ d_sol = new CegConjectureSingleInvSol( qe );
}
-Node CegConjectureSingleInv::getSingleInvLemma( Node guard ) {
+void CegConjectureSingleInv::getSingleInvLemma( Node guard, std::vector< Node >& lems ) {
if( !d_single_inv.isNull() ) {
d_single_inv_var.clear();
d_single_inv_sk.clear();
@@ -73,30 +80,16 @@ Node CegConjectureSingleInv::getSingleInvLemma( Node guard ) {
inst = TermDb::simpleNegate( inst );
Trace("cegqi-si") << "Single invocation initial lemma : " << inst << std::endl;
- //initialize the instantiator for this
- if( !d_single_inv_sk.empty() ){
- CegqiOutputSingleInv * cosi = new CegqiOutputSingleInv( this );
- // third and fourth arguments set to (false,false) until we have solution reconstruction for delta and infinity
- d_cinst = new CegInstantiator( d_qe, cosi, false, false );
- d_cinst->d_vars.insert( d_cinst->d_vars.end(), d_single_inv_sk.begin(), d_single_inv_sk.end() );
- }else{
- d_cinst = NULL;
- }
-
- return NodeManager::currentNM()->mkNode( OR, guard.negate(), inst );
- }else{
- return Node::null();
+ //register with the instantiator
+ Node ginst = NodeManager::currentNM()->mkNode( OR, guard.negate(), inst );
+ lems.push_back( ginst );
+ d_cinst->registerCounterexampleLemma( lems, d_single_inv_sk );
}
}
-void CegConjectureSingleInv::initialize( QuantifiersEngine * qe, Node q ) {
+void CegConjectureSingleInv::initialize( Node q ) {
//initialize data
- d_sol = new CegConjectureSingleInvSol( qe );
- d_qe = qe;
d_quant = q;
- if( options::incrementalSolving() ){
- d_c_inst_match_trie = new inst::CDInstMatchTrie( qe->getUserContext() );
- }
//process
Trace("cegqi-si") << "Initialize cegqi-si for " << q << std::endl;
// conj -> conj*
@@ -457,63 +450,9 @@ void CegConjectureSingleInv::initialize( QuantifiersEngine * qe, Node q ) {
exit( 0 );
}
}else{
- if( options::cegqiSingleInvPreRegInst() && d_single_inv.getKind()==FORALL ){
- Trace("cegqi-si-presolve") << "Check " << d_single_inv << std::endl;
- //at preregister time, add proxy of obvious instantiations up front, which helps learning during preprocessing
- std::vector< Node > vars;
- std::map< Node, std::vector< Node > > teq;
- for( unsigned i=0; i<d_single_inv[0].getNumChildren(); i++ ){
- vars.push_back( d_single_inv[0][i] );
- teq[d_single_inv[0][i]].clear();
- }
- collectPresolveEqTerms( d_single_inv[1], teq );
- std::vector< Node > terms;
- std::vector< Node > conj;
- getPresolveEqConjuncts( vars, terms, teq, d_single_inv, conj );
-
- if( !conj.empty() ){
- Node lem = conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( AND, conj );
- Node g = NodeManager::currentNM()->mkSkolem( "g", NodeManager::currentNM()->booleanType() );
- lem = NodeManager::currentNM()->mkNode( OR, g, lem );
- d_qe->getOutputChannel().lemma( lem, false, true );
- }
- }
- }
-}
-
-void CegConjectureSingleInv::collectPresolveEqTerms( Node n, std::map< Node, std::vector< Node > >& teq ) {
- if( n.getKind()==EQUAL ){
- for( unsigned i=0; i<2; i++ ){
- std::map< Node, std::vector< Node > >::iterator it = teq.find( n[i] );
- if( it!=teq.end() ){
- Node nn = n[ i==0 ? 1 : 0 ];
- if( std::find( it->second.begin(), it->second.end(), nn )==it->second.end() ){
- it->second.push_back( nn );
- Trace("cegqi-si-presolve") << " - " << n[i] << " = " << nn << std::endl;
- }
- }
- }
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- collectPresolveEqTerms( n[i], teq );
- }
-}
-
-void CegConjectureSingleInv::getPresolveEqConjuncts( std::vector< Node >& vars, std::vector< Node >& terms,
- std::map< Node, std::vector< Node > >& teq, Node f, std::vector< Node >& conj ) {
- if( conj.size()<1000 ){
- if( terms.size()==f[0].getNumChildren() ){
- Node c = f[1].substitute( vars.begin(), vars.end(), terms.begin(), terms.end() );
- conj.push_back( c );
- }else{
- unsigned i = terms.size();
- Node v = f[0][i];
- terms.push_back( Node::null() );
- for( unsigned j=0; j<teq[v].size(); j++ ){
- terms[i] = teq[v][j];
- getPresolveEqConjuncts( vars, terms, teq, f, conj );
- }
- terms.pop_back();
+ if( options::cbqiPreRegInst() && d_single_inv.getKind()==FORALL ){
+ //just invoke the presolve now
+ d_cinst->presolve( d_single_inv );
}
}
}
@@ -719,10 +658,7 @@ bool CegConjectureSingleInv::addInstantiation( std::vector< Node >& subs ){
}else{
Trace("cegqi-engine") << siss.str() << std::endl;
Node lem = d_single_inv[1].substitute( d_single_inv_var.begin(), d_single_inv_var.end(), subs.begin(), subs.end() );
- Node delta = d_qe->getTermDatabase()->getVtsDelta( false, false );
- Node inf = d_qe->getTermDatabase()->getVtsInfinity( false, false );
- if( ( !delta.isNull() && TermDb::containsTerm( lem, delta ) ) ||
- ( !inf.isNull() && TermDb::containsTerm( lem, inf ) ) ){
+ if( d_qe->getTermDatabase()->containsVtsTerm( lem ) ){
Trace("cegqi-engine-debug") << "Rewrite based on vts symbols..." << std::endl;
lem = d_qe->getTermDatabase()->rewriteVtsSymbols( lem );
}
@@ -749,7 +685,7 @@ bool CegConjectureSingleInv::addLemma( Node n ) {
}
void CegConjectureSingleInv::check( std::vector< Node >& lems ) {
- if( !d_single_inv.isNull() && d_cinst!=NULL ) {
+ if( !d_single_inv.isNull() ) {
d_curr_lemmas.clear();
//call check for instantiator
d_cinst->check();
@@ -870,6 +806,7 @@ Node CegConjectureSingleInv::reconstructToSyntax( Node s, TypeNode stn, int& rec
//reconstruct the solution into sygus if necessary
reconstructed = 0;
if( options::cegqiSingleInvReconstruct() && !dt.getSygusAllowAll() && !stn.isNull() ){
+ d_sol->preregisterConjecture( d_orig_conjecture );
d_sygus_solution = d_sol->reconstructSolution( s, stn, reconstructed );
if( reconstructed==1 ){
Trace("csi-sol") << "Solution (post-reconstruction into Sygus): " << d_sygus_solution << std::endl;
@@ -923,5 +860,8 @@ bool CegConjectureSingleInv::needsCheck() {
return true;
}
+void CegConjectureSingleInv::preregisterConjecture( Node q ) {
+ d_orig_conjecture = q;
+}
} \ No newline at end of file
diff --git a/src/theory/quantifiers/ce_guided_single_inv.h b/src/theory/quantifiers/ce_guided_single_inv.h
index 2c955db5d..e814df110 100644
--- a/src/theory/quantifiers/ce_guided_single_inv.h
+++ b/src/theory/quantifiers/ce_guided_single_inv.h
@@ -84,6 +84,8 @@ private:
//lemmas produced
inst::InstMatchTrie d_inst_match_trie;
inst::CDInstMatchTrie * d_c_inst_match_trie;
+ //original conjecture
+ Node d_orig_conjecture;
// solution
std::vector< Node > d_varList;
Node d_orig_solution;
@@ -103,7 +105,7 @@ private:
// add lemma
bool addLemma( Node lem );
public:
- CegConjectureSingleInv( CegConjecture * p );
+ CegConjectureSingleInv( QuantifiersEngine * qe, CegConjecture * p );
// original conjecture
Node d_quant;
// single invocation version of quant
@@ -113,10 +115,10 @@ public:
std::map< Node, Node > d_trans_post;
std::map< Node, std::vector< Node > > d_prog_templ_vars;
public:
- //get the single invocation lemma
- Node getSingleInvLemma( Node guard );
+ //get the single invocation lemma(s)
+ void getSingleInvLemma( Node guard, std::vector< Node >& lems );
//initialize
- void initialize( QuantifiersEngine * qe, Node q );
+ void initialize( Node q );
//check
void check( std::vector< Node >& lems );
//get solution
@@ -129,6 +131,8 @@ public:
bool isSingleInvocation() { return !d_single_inv.isNull(); }
//needs check
bool needsCheck();
+ /** preregister conjecture */
+ void preregisterConjecture( Node q );
};
}
diff --git a/src/theory/quantifiers/ce_guided_single_inv_sol.cpp b/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
index 413fd9ba2..8fd935368 100644
--- a/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
+++ b/src/theory/quantifiers/ce_guided_single_inv_sol.cpp
@@ -618,9 +618,27 @@ Node CegConjectureSingleInvSol::simplifySolutionNode( Node sol, TypeNode stn, st
}
-
-
-
+void CegConjectureSingleInvSol::preregisterConjecture( Node q ) {
+ Trace("csi-sol") << "Preregister conjecture : " << q << std::endl;
+ Node n = q;
+ if( n.getKind()==FORALL ){
+ n = n[1];
+ }
+ if( n.getKind()==EXISTS ){
+ if( n[0].getNumChildren()==d_varList.size() ){
+ std::vector< Node > evars;
+ for( unsigned i=0; i<n[0].getNumChildren(); i++ ){
+ evars.push_back( n[0][i] );
+ }
+ n = n[1].substitute( evars.begin(), evars.end(), d_varList.begin(), d_varList.end() );
+ }else{
+ Trace("csi-sol") << "Not the same number of variables, return." << std::endl;
+ return;
+ }
+ }
+ Trace("csi-sol") << "Preregister node for solution reconstruction : " << n << std::endl;
+ registerEquivalentTerms( n );
+}
Node CegConjectureSingleInvSol::reconstructSolution( Node sol, TypeNode stn, int& reconstructed ) {
Trace("csi-rcons") << "Solution (pre-reconstruction) is : " << sol << std::endl;
@@ -1054,6 +1072,7 @@ void CegConjectureSingleInvSol::setReconstructed( int id, Node n ) {
}
void CegConjectureSingleInvSol::getEquivalentTerms( Kind k, Node n, std::vector< Node >& equiv ) {
+ Assert( n.getKind()!=k ); //?
if( k==AND || k==OR ){
equiv.push_back( NodeManager::currentNM()->mkNode( k, n, n ) );
equiv.push_back( NodeManager::currentNM()->mkNode( k, n, NodeManager::currentNM()->mkConst( k==AND ) ) );
@@ -1108,7 +1127,68 @@ void CegConjectureSingleInvSol::getEquivalentTerms( Kind k, Node n, std::vector<
nn = Rewriter::rewrite( nn );
equiv.push_back( NodeManager::currentNM()->mkNode( MINUS, NodeManager::currentNM()->mkConst( Rational(0) ), nn ) );
}
- }
+ }
+ //inequalities
+ if( k==GEQ || k==LEQ || k==LT || k==GT || k==NOT ){
+ Node atom = n.getKind()==NOT ? n[0] : n;
+ bool pol = n.getKind()!=NOT;
+ Kind ak = atom.getKind();
+ if( ( ak==GEQ || ak==LEQ || ak==LT || ak==GT ) && ( pol || k!=NOT ) ){
+ Node t1 = atom[0];
+ Node t2 = atom[1];
+ if( !pol ){
+ ak = ak==GEQ ? LT : ( ak==LEQ ? GT : ( ak==LT ? GEQ : LEQ ) );
+ }
+ if( k==NOT ){
+ equiv.push_back( NodeManager::currentNM()->mkNode( ak==GEQ ? LT : ( ak==LEQ ? GT : ( ak==LT ? GEQ : LEQ ) ), t1, t2 ).negate() );
+ }else if( k==ak ){
+ equiv.push_back( NodeManager::currentNM()->mkNode( k, t1, t2 ) );
+ }else if( (k==GEQ || k==LEQ)==(ak==GEQ || ak==LEQ) ){
+ equiv.push_back( NodeManager::currentNM()->mkNode( k, t2, t1 ) );
+ }else if( t1.getType().isInteger() && t2.getType().isInteger() ){
+ if( (k==GEQ || k==GT)!=(ak==GEQ || ak==GT) ){
+ Node ts = t1;
+ t1 = t2;
+ t2 = ts;
+ ak = ak==GEQ ? LEQ : ( ak==LEQ ? GEQ : ( ak==LT ? GT : LT ) );
+ }
+ t2 = NodeManager::currentNM()->mkNode( PLUS, t2, NodeManager::currentNM()->mkConst( Rational( (ak==GT || ak==LEQ) ? 1 : -1 ) ) );
+ t2 = Rewriter::rewrite( t2 );
+ equiv.push_back( NodeManager::currentNM()->mkNode( k, t1, t2 ) );
+ }
+ }
+ }
+
+ //based on eqt cache
+ std::map< Node, Node >::iterator itet = d_eqt_rep.find( n );
+ if( itet!=d_eqt_rep.end() ){
+ Node rn = itet->second;
+ for( unsigned i=0; i<d_eqt_eqc[rn].size(); i++ ){
+ if( d_eqt_eqc[rn][i]!=n && d_eqt_eqc[rn][i].getKind()==k ){
+ if( std::find( equiv.begin(), equiv.end(), d_eqt_eqc[rn][i] )==equiv.end() ){
+ equiv.push_back( d_eqt_eqc[rn][i] );
+ }
+ }
+ }
+ }
}
-
+
+void CegConjectureSingleInvSol::registerEquivalentTerms( Node n ) {
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ registerEquivalentTerms( n[i] );
+ }
+ Node rn = Rewriter::rewrite( n );
+ if( rn!=n ){
+ Trace("csi-equiv") << " eq terms : " << n << " " << rn << std::endl;
+ d_eqt_rep[n] = rn;
+ d_eqt_rep[rn] = rn;
+ if( std::find( d_eqt_eqc[rn].begin(), d_eqt_eqc[rn].end(), rn )==d_eqt_eqc[rn].end() ){
+ d_eqt_eqc[rn].push_back( rn );
+ }
+ if( std::find( d_eqt_eqc[rn].begin(), d_eqt_eqc[rn].end(), n )==d_eqt_eqc[rn].end() ){
+ d_eqt_eqc[rn].push_back( n );
+ }
+ }
+}
+
}
diff --git a/src/theory/quantifiers/ce_guided_single_inv_sol.h b/src/theory/quantifiers/ce_guided_single_inv_sol.h
index 1d84986b4..adcc7bf85 100644
--- a/src/theory/quantifiers/ce_guided_single_inv_sol.h
+++ b/src/theory/quantifiers/ce_guided_single_inv_sol.h
@@ -65,6 +65,10 @@ private:
std::map< int, std::vector< int > > d_eqc;
std::map< int, int > d_rep;
+
+ //equivalent terms
+ std::map< Node, Node > d_eqt_rep;
+ std::map< Node, std::vector< Node > > d_eqt_eqc;
//cache when reconstructing solutions
std::vector< int > d_tmp_fail;
@@ -80,8 +84,11 @@ private:
void setReconstructed( int id, Node n );
//get equivalent terms to n with top symbol k
void getEquivalentTerms( Kind k, Node n, std::vector< Node >& equiv );
+ //register equivalent terms
+ void registerEquivalentTerms( Node n );
public:
Node reconstructSolution( Node sol, TypeNode stn, int& reconstructed );
+ void preregisterConjecture( Node q );
public:
CegConjectureSingleInvSol( QuantifiersEngine * qe );
};
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.cpp b/src/theory/quantifiers/inst_strategy_cbqi.cpp
index dcbb79a35..073cba525 100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.cpp
+++ b/src/theory/quantifiers/inst_strategy_cbqi.cpp
@@ -9,7 +9,7 @@
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Implementation of cbqi instantiation strategies
+ ** \brief Implementation of counterexample-guided quantifier instantiation strategies
**/
#include "theory/quantifiers/inst_strategy_cbqi.h"
@@ -20,6 +20,7 @@
#include "theory/quantifiers/options.h"
#include "theory/quantifiers/term_database.h"
#include "theory/quantifiers/first_order_model.h"
+#include "util/ite_removal.h"
using namespace std;
using namespace CVC4;
@@ -28,13 +29,11 @@ using namespace CVC4::context;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
using namespace CVC4::theory::arith;
-using namespace CVC4::theory::datatypes;
#define ARITH_INSTANTIATOR_USE_MINUS_DELTA
//#define MBP_STRICT_ASSERTIONS
-
CegInstantiator::CegInstantiator( QuantifiersEngine * qe, CegqiOutput * out, bool use_vts_delta, bool use_vts_inf ) :
d_qe( qe ), d_out( out ), d_use_vts_delta( use_vts_delta ), d_use_vts_inf( use_vts_inf ){
d_zero = NodeManager::currentNM()->mkConst( Rational( 0 ) );
@@ -65,28 +64,35 @@ void CegInstantiator::computeProgVars( Node n ){
}
bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector< Node >& vars,
- std::vector< Node >& coeff, std::vector< Node >& has_coeff, Node theta,
- unsigned i, unsigned effort ){
+ std::vector< Node >& coeff, std::vector< int >& btyp,
+ std::vector< Node >& has_coeff, Node theta, unsigned i, unsigned effort ){
if( i==d_vars.size() ){
- return addInstantiationCoeff( subs, vars, coeff, has_coeff, 0 );
+ return addInstantiationCoeff( subs, vars, coeff, btyp, has_coeff, 0 );
}else{
- eq::EqualityEngine* ee = d_qe->getMasterEqualityEngine();
std::map< Node, std::map< Node, bool > > subs_proc;
//Node v = d_single_inv_map_to_prog[d_single_inv[0][i]];
Node pv = d_vars[i];
TypeNode pvtn = pv.getType();
+ Trace("cbqi-inst-debug") << "[Find instantiation for " << pv << "]" << std::endl;
+ Node pv_value;
+ if( options::cbqiModel() ){
+ pv_value = d_qe->getModel()->getValue( pv );
+ Trace("cbqi-bound2") << "...M( " << pv << " ) = " << pv_value << std::endl;
+ }
//if in effort=2, we must choose at least one model value
if( (i+1)<d_vars.size() || effort!=2 ){
+
//[1] easy case : pv is in the equivalence class as another term not containing pv
- if( ee->hasTerm( pv ) ){
- //std::vector< Node > eqc_sk;
- Node pvr = ee->getRepresentative( pv );
- eq::EqClassIterator eqc_i = eq::EqClassIterator( pvr, ee );
- while( !eqc_i.isFinished() ){
- Node n = *eqc_i;
+ Trace("cbqi-inst-debug") << "[1] try based on equivalence class." << std::endl;
+ std::map< Node, Node >::iterator itr = d_curr_rep.find( pv );
+ if( itr!=d_curr_rep.end() ){
+ std::map< Node, std::vector< Node > >::iterator it_eqc = d_curr_eqc.find( itr->second );
+ Assert( it_eqc!=d_curr_eqc.end() );
+ for( unsigned k=0; k<it_eqc->second.size(); k++ ){
+ Node n = it_eqc->second[k];
if( n!=pv ){
- Trace("cbqi-inst-debug") << "[1] " << i << "...try based on equal term " << n << std::endl;
+ Trace("cbqi-inst-debug") << "..[1] " << i << "...try based on equal term " << n << std::endl;
//compute d_subs_fv, which program variables are contained in n
computeProgVars( n );
//must be an eligible term
@@ -108,136 +114,123 @@ bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector<
if( proc ){
//try the substitution
subs_proc[ns][pv_coeff] = true;
- if( addInstantiationInc( ns, pv, pv_coeff, subs, vars, coeff, has_coeff, theta, i, effort ) ){
+ if( addInstantiationInc( ns, pv, pv_coeff, 0, subs, vars, coeff, btyp, has_coeff, theta, i, effort ) ){
return true;
}
}
}
- //record this as skolem
- //if( n.getKind()==SKOLEM ){
- // eqc_sk.push_back( n );
- //}
}
- ++eqc_i;
}
}
//[2] : we can solve an equality for pv
///iterate over equivalence classes to find cases where we can solve for the variable
- Node vts_inf = d_qe->getTermDatabase()->getVtsInfinity( false, false );
if( pvtn.isInteger() || pvtn.isReal() ){
- eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
- while( !eqcs_i.isFinished() ){
- Node r = *eqcs_i;
- TypeNode rtn = r.getType();
- if( rtn.isInteger() || rtn.isReal() ){
- std::vector< Node > lhs;
- std::vector< bool > lhs_v;
- std::vector< Node > lhs_coeff;
- eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
- while( !eqc_i.isFinished() ){
- Node n = *eqc_i;
- computeProgVars( n );
- //must be an eligible term
- if( d_inelig.find( n )==d_inelig.end() ){
- Node ns;
- Node pv_coeff;
- if( !d_prog_var[n].empty() ){
- ns = applySubstitution( n, subs, vars, coeff, has_coeff, pv_coeff );
- if( !ns.isNull() ){
- computeProgVars( ns );
- }
- }else{
- ns = n;
- }
+ Trace("cbqi-inst-debug") << "[2] try based on solving in arithmetic equivalence class." << std::endl;
+ for( unsigned k=0; k<d_curr_arith_eqc.size(); k++ ){
+ Node r = d_curr_arith_eqc[k];
+ std::vector< Node > lhs;
+ std::vector< bool > lhs_v;
+ std::vector< Node > lhs_coeff;
+ std::map< Node, std::vector< Node > >::iterator it_eqc = d_curr_eqc.find( r );
+ Assert( it_eqc!=d_curr_eqc.end() );
+ for( unsigned kk=0; kk<it_eqc->second.size(); kk++ ){
+ Node n = it_eqc->second[kk];
+ Trace("cbqi-inst-debug2") << "...look at term " << n << std::endl;
+ //compute the variables in n
+ computeProgVars( n );
+ //must be an eligible term
+ if( d_inelig.find( n )==d_inelig.end() ){
+ Node ns;
+ Node pv_coeff;
+ if( !d_prog_var[n].empty() ){
+ ns = applySubstitution( n, subs, vars, coeff, has_coeff, pv_coeff );
if( !ns.isNull() ){
- bool hasVar = d_prog_var[ns].find( pv )!=d_prog_var[ns].end();
- for( unsigned j=0; j<lhs.size(); j++ ){
- //if this term or the another has pv in it, try to solve for it
- if( hasVar || lhs_v[j] ){
- Trace("cbqi-inst-debug") << "[2] " << i << "...try based on equality " << lhs[j] << " = " << ns << std::endl;
- Node eq_lhs = lhs[j];
- Node eq_rhs = ns;
- //make the same coefficient
- if( pv_coeff!=lhs_coeff[j] ){
- if( !pv_coeff.isNull() ){
- Trace("cbqi-inst-debug") << "...mult lhs by " << pv_coeff << std::endl;
- eq_lhs = NodeManager::currentNM()->mkNode( MULT, pv_coeff, eq_lhs );
- eq_lhs = Rewriter::rewrite( eq_lhs );
- }
- if( !lhs_coeff[j].isNull() ){
- Trace("cbqi-inst-debug") << "...mult rhs by " << lhs_coeff[j] << std::endl;
- eq_rhs = NodeManager::currentNM()->mkNode( MULT, lhs_coeff[j], eq_rhs );
- eq_rhs = Rewriter::rewrite( eq_rhs );
- }
+ computeProgVars( ns );
+ }
+ }else{
+ ns = n;
+ }
+ if( !ns.isNull() ){
+ bool hasVar = d_prog_var[ns].find( pv )!=d_prog_var[ns].end();
+ for( unsigned j=0; j<lhs.size(); j++ ){
+ //if this term or the another has pv in it, try to solve for it
+ if( hasVar || lhs_v[j] ){
+ Trace("cbqi-inst-debug") << "..[2] " << i << "...try based on equality " << lhs[j] << " = " << ns << std::endl;
+ Node eq_lhs = lhs[j];
+ Node eq_rhs = ns;
+ //make the same coefficient
+ if( pv_coeff!=lhs_coeff[j] ){
+ if( !pv_coeff.isNull() ){
+ Trace("cbqi-inst-debug") << "...mult lhs by " << pv_coeff << std::endl;
+ eq_lhs = NodeManager::currentNM()->mkNode( MULT, pv_coeff, eq_lhs );
+ eq_lhs = Rewriter::rewrite( eq_lhs );
+ }
+ if( !lhs_coeff[j].isNull() ){
+ Trace("cbqi-inst-debug") << "...mult rhs by " << lhs_coeff[j] << std::endl;
+ eq_rhs = NodeManager::currentNM()->mkNode( MULT, lhs_coeff[j], eq_rhs );
+ eq_rhs = Rewriter::rewrite( eq_rhs );
+ }
+ }
+ Node eq = eq_lhs.eqNode( eq_rhs );
+ eq = Rewriter::rewrite( eq );
+ //cannot contain infinity?
+ //if( !d_qe->getTermDatabase()->containsVtsInfinity( eq ) ){
+ Trace("cbqi-inst-debug") << "...equality is " << eq << std::endl;
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSumLit( eq, msum ) ){
+ if( Trace.isOn("cbqi-inst-debug") ){
+ Trace("cbqi-inst-debug") << "...got monomial sum: " << std::endl;
+ QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
+ Trace("cbqi-inst-debug") << "isolate for " << pv << "..." << std::endl;
}
- Node eq = eq_lhs.eqNode( eq_rhs );
- eq = Rewriter::rewrite( eq );
- //cannot contain infinity
- if( vts_inf.isNull() || !TermDb::containsTerm( eq, vts_inf ) ){
- Trace("cbqi-inst-debug") << "...equality is " << eq << std::endl;
- std::map< Node, Node > msum;
- if( QuantArith::getMonomialSumLit( eq, msum ) ){
- if( Trace.isOn("cbqi-inst-debug") ){
- Trace("cbqi-inst-debug") << "...got monomial sum: " << std::endl;
- QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
- Trace("cbqi-inst-debug") << "isolate for " << pv << "..." << std::endl;
+ Node veq;
+ if( QuantArith::isolate( pv, msum, veq, EQUAL, true )!=0 ){
+ Trace("cbqi-inst-debug") << "...isolated equality " << veq << "." << std::endl;
+ Node veq_c;
+ if( veq[0]!=pv ){
+ Node veq_v;
+ if( QuantArith::getMonomial( veq[0], veq_c, veq_v ) ){
+ Assert( veq_v==pv );
}
- Node veq;
- if( QuantArith::isolate( pv, msum, veq, EQUAL, true )!=0 ){
- Trace("cbqi-inst-debug") << "...isolated equality " << veq << "." << std::endl;
- Node veq_c;
- if( veq[0]!=pv ){
- Node veq_v;
- if( QuantArith::getMonomial( veq[0], veq_c, veq_v ) ){
- Assert( veq_v==pv );
- }
- }
- Node val = veq[1];
- //eliminate coefficient if real
- if( !pvtn.isInteger() && !veq_c.isNull() ){
- val = NodeManager::currentNM()->mkNode( MULT, val, NodeManager::currentNM()->mkConst( Rational(1) / veq_c.getConst<Rational>() ) );
- val = Rewriter::rewrite( val );
- veq_c = Node::null();
- }
- if( subs_proc[val].find( veq_c )==subs_proc[val].end() ){
- subs_proc[val][veq_c] = true;
- if( addInstantiationInc( val, pv, veq_c, subs, vars, coeff, has_coeff, theta, i, effort ) ){
- return true;
- }
- }
+ }
+ Node val = veq[1];
+ if( subs_proc[val].find( veq_c )==subs_proc[val].end() ){
+ subs_proc[val][veq_c] = true;
+ if( addInstantiationInc( val, pv, veq_c, 0, subs, vars, coeff, btyp, has_coeff, theta, i, effort ) ){
+ return true;
}
}
}
}
}
- lhs.push_back( ns );
- lhs_v.push_back( hasVar );
- lhs_coeff.push_back( pv_coeff );
}
+ lhs.push_back( ns );
+ lhs_v.push_back( hasVar );
+ lhs_coeff.push_back( pv_coeff );
}
- ++eqc_i;
}
}
- ++eqcs_i;
}
}
//[3] directly look at assertions
+ Trace("cbqi-inst-debug") << "[3] try based on assertions." << std::endl;
+ Node vts_sym[2];
+ vts_sym[0] = d_qe->getTermDatabase()->getVtsInfinity( pvtn, false, false );
+ vts_sym[1] = d_qe->getTermDatabase()->getVtsDelta( false, false );
std::vector< Node > mbp_bounds[2];
std::vector< Node > mbp_coeff[2];
- std::vector< bool > mbp_strict[2];
+ std::vector< Node > mbp_vts_coeff[2][2];
std::vector< Node > mbp_lit[2];
unsigned rmax = Theory::theoryOf( pv )==Theory::theoryOf( pv.getType() ) ? 1 : 2;
for( unsigned r=0; r<rmax; r++ ){
TheoryId tid = r==0 ? Theory::theoryOf( pv ) : Theory::theoryOf( pv.getType() );
- Theory* theory = d_qe->getTheoryEngine()->theoryOf( tid );
- Trace("cbqi-inst-debug2") << "Theory of " << pv << " (r=" << r << ") is " << tid << std::endl;
- if (theory && d_qe->getTheoryEngine()->isTheoryEnabled(tid)) {
- Trace("cbqi-inst-debug2") << "Look at assertions of " << tid << std::endl;
- context::CDList<Assertion>::const_iterator it = theory->facts_begin(), it_end = theory->facts_end();
- for (unsigned j = 0; it != it_end; ++ it, ++j) {
- Node lit = (*it).assertion;
+ Trace("cbqi-inst-debug2") << " look at assertions of " << tid << std::endl;
+ std::map< TheoryId, std::vector< Node > >::iterator ita = d_curr_asserts.find( tid );
+ if( ita!=d_curr_asserts.end() ){
+ for (unsigned j = 0; j<ita->second.size(); j++) {
+ Node lit = ita->second[j];
Trace("cbqi-inst-debug2") << " look at " << lit << std::endl;
Node atom = lit.getKind()==NOT ? lit[0] : lit;
bool pol = lit.getKind()!=NOT;
@@ -272,96 +265,153 @@ bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector<
//if it contains pv, not infinity
if( !atom_lhs.isNull() && d_prog_var[atom_lhs].find( pv )!=d_prog_var[atom_lhs].end() ){
Node satom = NodeManager::currentNM()->mkNode( atom.getKind(), atom_lhs, atom_rhs );
- //cannot contain infinity
- if( vts_inf.isNull() || !TermDb::containsTerm( atom_lhs, vts_inf ) ){
- Trace("cbqi-inst-debug") << "[3] From assertion : " << atom << ", pol = " << pol << std::endl;
- Trace("cbqi-inst-debug") << " substituted : " << satom << ", pol = " << pol << std::endl;
- std::map< Node, Node > msum;
- if( QuantArith::getMonomialSumLit( satom, msum ) ){
- if( Trace.isOn("cbqi-inst-debug") ){
- Trace("cbqi-inst-debug") << "...got monomial sum: " << std::endl;
- QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
- Trace("cbqi-inst-debug") << "isolate for " << pv << "..." << std::endl;
- }
- Node vatom;
- //isolate pv in the inequality
- int ires = QuantArith::isolate( pv, msum, vatom, atom.getKind(), true );
- if( ires!=0 ){
- Trace("cbqi-inst-debug") << "...isolated atom " << vatom << "." << std::endl;
- Node val = vatom[ ires==1 ? 1 : 0 ];
- Node pvm = vatom[ ires==1 ? 0 : 1 ];
- //get monomial
- Node veq_c;
- if( pvm!=pv ){
- Node veq_v;
- if( QuantArith::getMonomial( pvm, veq_c, veq_v ) ){
- Assert( veq_v==pv );
+ //cannot contain infinity?
+ //if( !d_qe->getTermDatabase()->containsVtsInfinity( atom_lhs ) ){
+ Trace("cbqi-inst-debug") << "..[3] From assertion : " << atom << ", pol = " << pol << std::endl;
+ Trace("cbqi-inst-debug") << " substituted : " << satom << ", pol = " << pol << std::endl;
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSumLit( satom, msum ) ){
+ if( Trace.isOn("cbqi-inst-debug") ){
+ Trace("cbqi-inst-debug") << "...got monomial sum: " << std::endl;
+ QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" );
+ }
+ //get the coefficient of infinity and remove it from msum
+ Node vts_coeff[2];
+ for( unsigned t=0; t<2; t++ ){
+ if( !vts_sym[t].isNull() ){
+ std::map< Node, Node >::iterator itminf = msum.find( vts_sym[t] );
+ if( itminf!=msum.end() ){
+ vts_coeff[t] = itminf->second;
+ if( vts_coeff[t].isNull() ){
+ vts_coeff[t] = NodeManager::currentNM()->mkConst( Rational( 1 ) );
}
+ //negate if coefficient on variable is positive
+ std::map< Node, Node >::iterator itv = msum.find( pv );
+ if( itv!=msum.end() ){
+ //multiply by the coefficient we will isolate for
+ if( itv->second.isNull() ){
+ vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
+ }else{
+ if( !pvtn.isInteger() ){
+ vts_coeff[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) / itv->second.getConst<Rational>() ), vts_coeff[t] );
+ vts_coeff[t] = Rewriter::rewrite( vts_coeff[t] );
+ }else if( itv->second.getConst<Rational>().sgn()==1 ){
+ vts_coeff[t] = QuantArith::negate(vts_coeff[t]);
+ }
+ }
+ }
+ Trace("cbqi-inst-debug") << "vts[" << t << "] coefficient is " << vts_coeff[t] << std::endl;
+ msum.erase( vts_sym[t] );
}
- //eliminate coefficient if real
- if( !pvtn.isInteger() && !veq_c.isNull() ){
- val = NodeManager::currentNM()->mkNode( MULT, val, NodeManager::currentNM()->mkConst( Rational(1) / veq_c.getConst<Rational>() ) );
- val = Rewriter::rewrite( val );
- veq_c = Node::null();
+ }
+ }
+
+ Trace("cbqi-inst-debug") << "isolate for " << pv << "..." << std::endl;
+ Node vatom;
+ //isolate pv in the inequality
+ int ires = QuantArith::isolate( pv, msum, vatom, atom.getKind(), true );
+ if( ires!=0 ){
+ Trace("cbqi-inst-debug") << "...isolated atom " << vatom << "." << std::endl;
+ Node val = vatom[ ires==1 ? 1 : 0 ];
+ Node pvm = vatom[ ires==1 ? 0 : 1 ];
+ //get monomial
+ Node veq_c;
+ if( pvm!=pv ){
+ Node veq_v;
+ if( QuantArith::getMonomial( pvm, veq_c, veq_v ) ){
+ Assert( veq_v==pv );
}
+ }
- //disequalities are both strict upper and lower bounds
- unsigned rmax = atom.getKind()==GEQ ? 1 : 2;
- for( unsigned r=0; r<rmax; r++ ){
- int uires = ires;
- Node uval = val;
- if( atom.getKind()==GEQ ){
- //push negation downwards
- if( !pol ){
- uires = -ires;
- if( pvtn.isInteger() ){
- uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
- uval = Rewriter::rewrite( uval );
- }else{
- Assert( pvtn.isReal() );
- //now is strict inequality
- uires = uires*2;
- }
- }
- }else{
- Assert( atom.getKind()==EQUAL && !pol );
+ //disequalities are either strict upper or lower bounds
+ unsigned rmax = ( atom.getKind()==GEQ && options::cbqiModel() ) ? 1 : 2;
+ for( unsigned r=0; r<rmax; r++ ){
+ int uires = ires;
+ Node uval = val;
+ if( atom.getKind()==GEQ ){
+ //push negation downwards
+ if( !pol ){
+ uires = -ires;
if( pvtn.isInteger() ){
- uires = r==0 ? -1 : 1;
uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
uval = Rewriter::rewrite( uval );
}else{
Assert( pvtn.isReal() );
- uires = r==0 ? -2 : 2;
+ //now is strict inequality
+ uires = uires*2;
}
}
- Trace("cbqi-bound-inf") << "From " << lit << ", got : ";
- if( !veq_c.isNull() ){
- Trace("cbqi-bound-inf") << veq_c << " * ";
- }
- Trace("cbqi-bound-inf") << pv << " -> " << uval << ", styp = " << uires << std::endl;
+ }else{
+ bool is_upper = ( r==0 );
if( options::cbqiModel() ){
- //just store bounds, will choose based on tighest bound
- unsigned index = uires>0 ? 0 : 1;
- mbp_bounds[index].push_back( uval );
- mbp_coeff[index].push_back( veq_c );
- mbp_strict[index].push_back( uires==2 || uires==-2 );
- mbp_lit[index].push_back( lit );
- }else{
- //take into account delta
- if( uires==2 || uires==-2 ){
- if( d_use_vts_delta ){
- Node delta = d_qe->getTermDatabase()->getVtsDelta();
- uval = NodeManager::currentNM()->mkNode( uires==2 ? PLUS : MINUS, uval, delta );
- uval = Rewriter::rewrite( uval );
+ // disequality is a disjunction : only consider the bound in the direction of the model
+ //first check if there is an infinity...
+ if( !vts_coeff[0].isNull() ){
+ //coefficient or val won't make a difference, just compare with zero
+ Trace("cbqi-inst-debug") << "Disequality : check infinity polarity " << vts_coeff[0] << std::endl;
+ Assert( vts_coeff[0].isConst() );
+ is_upper = ( vts_coeff[0].getConst<Rational>().sgn()==1 );
+ }else{
+ Node rhs_value = d_qe->getModel()->getValue( val );
+ Node lhs_value = pv_value;
+ if( !veq_c.isNull() ){
+ lhs_value = NodeManager::currentNM()->mkNode( MULT, lhs_value, veq_c );
+ lhs_value = Rewriter::rewrite( lhs_value );
}
+ Trace("cbqi-inst-debug") << "Disequality : check model values " << lhs_value << " " << rhs_value << std::endl;
+ Assert( lhs_value!=rhs_value );
+ Node cmp = NodeManager::currentNM()->mkNode( GEQ, lhs_value, rhs_value );
+ cmp = Rewriter::rewrite( cmp );
+ Assert( cmp.isConst() );
+ is_upper = ( cmp!=d_true );
}
- if( subs_proc[uval].find( veq_c )==subs_proc[uval].end() ){
- subs_proc[uval][veq_c] = true;
- if( addInstantiationInc( uval, pv, veq_c, subs, vars, coeff, has_coeff, theta, i, effort ) ){
- return true;
- }
+ }
+ Assert( atom.getKind()==EQUAL && !pol );
+ if( pvtn.isInteger() ){
+ uires = is_upper ? -1 : 1;
+ uval = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkConst( Rational( uires ) ) );
+ uval = Rewriter::rewrite( uval );
+ }else{
+ Assert( pvtn.isReal() );
+ uires = is_upper ? -2 : 2;
+ }
+ }
+ Trace("cbqi-bound-inf") << "From " << lit << ", got : ";
+ if( !veq_c.isNull() ){
+ Trace("cbqi-bound-inf") << veq_c << " * ";
+ }
+ Trace("cbqi-bound-inf") << pv << " -> " << uval << ", styp = " << uires << std::endl;
+ //take into account delta
+ if( d_use_vts_delta && ( uires==2 || uires==-2 ) ){
+ if( options::cbqiModel() ){
+ Node delta_coeff = NodeManager::currentNM()->mkConst( Rational( uires > 0 ? 1 : -1 ) );
+ if( vts_coeff[1].isNull() ){
+ vts_coeff[1] = delta_coeff;
}else{
- Trace("cbqi-inst-debug") << "...already processed." << std::endl;
+ vts_coeff[1] = NodeManager::currentNM()->mkNode( PLUS, vts_coeff[1], delta_coeff );
+ vts_coeff[1] = Rewriter::rewrite( vts_coeff[1] );
+ }
+ }else{
+ Node delta = d_qe->getTermDatabase()->getVtsDelta();
+ uval = NodeManager::currentNM()->mkNode( uires==2 ? PLUS : MINUS, uval, delta );
+ uval = Rewriter::rewrite( uval );
+ }
+ }
+ if( options::cbqiModel() ){
+ //just store bounds, will choose based on tighest bound
+ unsigned index = uires>0 ? 0 : 1;
+ mbp_bounds[index].push_back( uval );
+ mbp_coeff[index].push_back( veq_c );
+ for( unsigned t=0; t<2; t++ ){
+ mbp_vts_coeff[index][t].push_back( vts_coeff[t] );
+ }
+ mbp_lit[index].push_back( lit );
+ }else{
+ //try this bound
+ if( subs_proc[uval].find( veq_c )==subs_proc[uval].end() ){
+ subs_proc[uval][veq_c] = true;
+ if( addInstantiationInc( uval, pv, veq_c, uires>0 ? 1 : -1, subs, vars, coeff, btyp, has_coeff, theta, i, effort ) ){
+ return true;
}
}
}
@@ -376,83 +426,160 @@ bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector<
}
if( options::cbqiModel() ){
if( pvtn.isInteger() || pvtn.isReal() ){
+ bool use_inf = d_use_vts_inf && ( pvtn.isInteger() ? options::cbqiUseInfInt() : options::cbqiUseInfReal() );
bool upper_first = false;
+ if( options::cbqiMinBounds() ){
+ upper_first = mbp_bounds[1].size()<mbp_bounds[0].size();
+ }
unsigned best_used[2];
- std::vector< Node > t_values[2];
- Node pv_value = d_qe->getModel()->getValue( pv );
- Trace("cbqi-bound2") << "...M( " << pv << " ) = " << pv_value << std::endl;
+ std::vector< Node > t_values[3];
//try optimal bounds
for( unsigned r=0; r<2; r++ ){
int rr = upper_first ? (1-r) : r;
if( mbp_bounds[rr].empty() ){
- /*
- if( d_use_vts_inf ){
+ if( use_inf ){
Trace("cbqi-bound") << "No " << ( rr==0 ? "lower" : "upper" ) << " bounds for " << pv << " (type=" << pvtn << ")" << std::endl;
//no bounds, we do +- infinity
- Node val = d_qe->getTermDatabase()->getVtsInfinity();
+ Node val = d_qe->getTermDatabase()->getVtsInfinity( pvtn );
+ //TODO : rho value for infinity?
if( rr==0 ){
val = NodeManager::currentNM()->mkNode( UMINUS, val );
val = Rewriter::rewrite( val );
}
- if( addInstantiationInc( val, pv, Node::null(), subs, vars, coeff, has_coeff, theta, i, effort ) ){
+ if( addInstantiationInc( val, pv, Node::null(), 0, subs, vars, coeff, btyp, has_coeff, theta, i, effort ) ){
return true;
}
}
- */
}else{
Trace("cbqi-bound") << ( rr==0 ? "Lower" : "Upper" ) << " bounds for " << pv << " (type=" << pvtn << ") : " << std::endl;
int best = -1;
- Node best_bound_value;
+ Node best_bound_value[3];
for( unsigned j=0; j<mbp_bounds[rr].size(); j++ ){
- Node t_value = d_qe->getModel()->getValue( mbp_bounds[rr][j] );
- t_values[rr].push_back( t_value );
- Trace("cbqi-bound2") << "...M( " << mbp_bounds[rr][j] << " ) = " << t_value << std::endl;
- Node value = t_value;
- Trace("cbqi-bound") << " " << j << ": " << mbp_bounds[rr][j];
- if( !mbp_coeff[rr][j].isNull() ){
- Trace("cbqi-bound") << " (div " << mbp_coeff[rr][j] << ")";
- Assert( mbp_coeff[rr][j].isConst() );
- value = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(1) / mbp_coeff[rr][j].getConst<Rational>() ), value );
- value = Rewriter::rewrite( value );
- }
- if( mbp_strict[rr][j] ){
- Trace("cbqi-bound") << " (strict)";
+ Node value[3];
+ if( Trace.isOn("cbqi-bound") ){
+ Assert( !mbp_bounds[rr][j].isNull() );
+ Trace("cbqi-bound") << " " << j << ": " << mbp_bounds[rr][j];
+ if( !mbp_vts_coeff[rr][0][j].isNull() ){
+ Trace("cbqi-bound") << " (+ " << mbp_vts_coeff[rr][0][j] << " * INF)";
+ }
+ if( !mbp_vts_coeff[rr][1][j].isNull() ){
+ Trace("cbqi-bound") << " (+ " << mbp_vts_coeff[rr][1][j] << " * DELTA)";
+ }
+ if( !mbp_coeff[rr][j].isNull() ){
+ Trace("cbqi-bound") << " (div " << mbp_coeff[rr][j] << ")";
+ }
+ Trace("cbqi-bound") << ", value = ";
}
- Trace("cbqi-bound") << ", value = " << value << std::endl;
- bool new_best = false;
- if( best==-1 ){
- new_best = true;
- }else{
- Kind k = rr==0 ? GEQ : LEQ;
- Node cmp_bound = NodeManager::currentNM()->mkNode( k, value, best_bound_value );
- cmp_bound = Rewriter::rewrite( cmp_bound );
- if( cmp_bound==d_true && ( !mbp_strict[rr][best] || mbp_strict[rr][j] ) ){
- new_best = true;
+ t_values[rr].push_back( Node::null() );
+ //check if it is better than the current best bound : lexicographic order infinite/finite/infinitesimal parts
+ bool new_best = true;
+ for( unsigned t=0; t<3; t++ ){
+ //get the value
+ if( t==0 ){
+ value[0] = mbp_vts_coeff[rr][0][j];
+ if( !value[0].isNull() ){
+ Trace("cbqi-bound") << "( " << value[0] << " * INF ) + ";
+ }else{
+ value[0] = d_zero;
+ }
+ }else if( t==1 ){
+ Node t_value = d_qe->getModel()->getValue( mbp_bounds[rr][j] );
+ t_values[rr][j] = t_value;
+ value[1] = t_value;
+ Trace("cbqi-bound") << value[1];
+ }else{
+ value[2] = mbp_vts_coeff[rr][1][j];
+ if( !value[2].isNull() ){
+ Trace("cbqi-bound") << " + ( " << value[2] << " * DELTA )";
+ }else{
+ value[2] = d_zero;
+ }
+ }
+ //multiply by coefficient
+ if( value[t]!=d_zero && !mbp_coeff[rr][j].isNull() ){
+ Assert( mbp_coeff[rr][j].isConst() );
+ value[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(1) / mbp_coeff[rr][j].getConst<Rational>() ), value[t] );
+ value[t] = Rewriter::rewrite( value[t] );
+ }
+ //check if new best
+ if( best!=-1 ){
+ Assert( !value[t].isNull() && !best_bound_value[t].isNull() );
+ if( value[t]!=best_bound_value[t] ){
+ Kind k = rr==0 ? GEQ : LEQ;
+ Node cmp_bound = NodeManager::currentNM()->mkNode( k, value[t], best_bound_value[t] );
+ cmp_bound = Rewriter::rewrite( cmp_bound );
+ if( cmp_bound!=d_true ){
+ new_best = false;
+ break;
+ }
+ }
}
}
+ Trace("cbqi-bound") << std::endl;
if( new_best ){
- best_bound_value = value;
+ for( unsigned t=0; t<3; t++ ){
+ best_bound_value[t] = value[t];
+ }
best = j;
}
}
if( best!=-1 ){
- Trace("cbqi-bound") << "...best bound is " << best << " : " << best_bound_value << std::endl;
+ Trace("cbqi-bound") << "...best bound is " << best << " : ";
+ if( best_bound_value[0]!=d_zero ){
+ Trace("cbqi-bound") << "( " << best_bound_value[0] << " * INF ) + ";
+ }
+ Trace("cbqi-bound") << best_bound_value[1];
+ if( best_bound_value[2]!=d_zero ){
+ Trace("cbqi-bound") << " + ( " << best_bound_value[2] << " * DELTA )";
+ }
+ Trace("cbqi-bound") << std::endl;
best_used[rr] = (unsigned)best;
- Node val = getModelBasedProjectionValue( mbp_bounds[rr][best], mbp_strict[rr][best], rr==0, mbp_coeff[rr][best], pv_value, t_values[rr][best], theta );
- if( !val.isNull() && addInstantiationInc( val, pv, mbp_coeff[rr][best], subs, vars, coeff, has_coeff, theta, i, effort ) ){
+ Node val = mbp_bounds[rr][best];
+ val = getModelBasedProjectionValue( val, rr==0, mbp_coeff[rr][best], pv_value, t_values[rr][best], theta,
+ mbp_vts_coeff[rr][0][best], vts_sym[0], mbp_vts_coeff[rr][1][best], vts_sym[1] );
+ if( !val.isNull() ){
+ if( subs_proc[val].find( mbp_coeff[rr][best] )==subs_proc[val].end() ){
+ subs_proc[val][mbp_coeff[rr][best]] = true;
+ if( addInstantiationInc( val, pv, mbp_coeff[rr][best], rr==0 ? 1 : -1, subs, vars, coeff, btyp, has_coeff, theta, i, effort ) ){
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ //if not using infinity, use model value of zero
+ if( !use_inf && mbp_bounds[0].empty() && mbp_bounds[1].empty() ){
+ Node val = d_zero;
+ Node c; //null (one) coefficient
+ val = getModelBasedProjectionValue( val, true, c, pv_value, d_zero, theta, Node::null(), vts_sym[0], Node::null(), vts_sym[1] );
+ if( !val.isNull() ){
+ if( subs_proc[val].find( c )==subs_proc[val].end() ){
+ subs_proc[val][c] = true;
+ if( addInstantiationInc( val, pv, c, 0, subs, vars, coeff, btyp, has_coeff, theta, i, effort ) ){
return true;
}
}
}
}
- //try non-optimal bounds (heuristic)
+#ifdef MBP_STRICT_ASSERTIONS
+ Assert( false );
+#endif
+ //try non-optimal bounds (heuristic, may help when nested quantification) ?
+ Trace("cbqi-bound") << "Try non-optimal bounds..." << std::endl;
for( unsigned r=0; r<2; r++ ){
int rr = upper_first ? (1-r) : r;
for( unsigned j=0; j<mbp_bounds[rr].size(); j++ ){
if( j!=best_used[rr] ){
- Node val = getModelBasedProjectionValue( mbp_bounds[rr][j], mbp_strict[rr][j], rr==0, mbp_coeff[rr][j], pv_value, t_values[rr][j], theta );
- if( !val.isNull() && addInstantiationInc( val, pv, mbp_coeff[rr][j], subs, vars, coeff, has_coeff, theta, i, effort ) ){
- return true;
+ Node val = getModelBasedProjectionValue( mbp_bounds[rr][j], rr==0, mbp_coeff[rr][j], pv_value, t_values[rr][j], theta,
+ mbp_vts_coeff[rr][0][j], vts_sym[0], mbp_vts_coeff[rr][1][j], vts_sym[1] );
+ if( !val.isNull() ){
+ if( subs_proc[val].find( mbp_coeff[rr][j] )==subs_proc[val].end() ){
+ subs_proc[val][mbp_coeff[rr][j]] = true;
+ if( addInstantiationInc( val, pv, mbp_coeff[rr][j], rr==0 ? 1 : -1, subs, vars, coeff, btyp, has_coeff, theta, i, effort ) ){
+ return true;
+ }
+ }
}
}
}
@@ -462,30 +589,33 @@ bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector<
}
//[4] resort to using value in model
- if( effort>0 || ( pvtn.isBoolean() && ( (i+1)<d_vars.size() || effort!=2 ) ) ){
+ if( effort>0 || pvtn.isBoolean() ){
Node mv = d_qe->getModel()->getValue( pv );
Node pv_coeff_m;
Trace("cbqi-inst-debug") << "[4] " << i << "...try model value " << mv << std::endl;
int new_effort = pvtn.isBoolean() ? effort : 1;
#ifdef MBP_STRICT_ASSERTIONS
//we only resort to values in the case of booleans
- Assert( pvtn.isBoolean() );
+ Assert( ( pvtn.isInteger() ? !options::cbqiUseInfInt() : !options::cbqiUseInfReal() ) || pvtn.isBoolean() );
#endif
- return addInstantiationInc( mv, pv, pv_coeff_m, subs, vars, coeff, has_coeff, theta, i, new_effort );
- }else{
- return false;
+ if( addInstantiationInc( mv, pv, pv_coeff_m, 0, subs, vars, coeff, btyp, has_coeff, theta, i, new_effort ) ){
+ return true;
+ }
}
+ Trace("cbqi-inst-debug") << "[No instantiation found for " << pv << "]" << std::endl;
+ return false;
}
}
-bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, std::vector< Node >& subs, std::vector< Node >& vars,
- std::vector< Node >& coeff, std::vector< Node >& has_coeff, Node theta, unsigned i, unsigned effort ) {
+bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, std::vector< Node >& subs, std::vector< Node >& vars,
+ std::vector< Node >& coeff, std::vector< int >& btyp,
+ std::vector< Node >& has_coeff, Node theta, unsigned i, unsigned effort ) {
if( Trace.isOn("cbqi-inst") ){
- for( unsigned i=0; i<subs.size(); i++ ){
+ for( unsigned j=0; j<subs.size(); j++ ){
Trace("cbqi-inst") << " ";
}
- Trace("cbqi-inst") << "i: ";
+ Trace("cbqi-inst") << subs.size() << ": ";
if( !pv_coeff.isNull() ){
Trace("cbqi-inst") << pv_coeff << " * ";
}
@@ -545,14 +675,10 @@ bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, std::
subs.push_back( n );
vars.push_back( pv );
coeff.push_back( pv_coeff );
+ btyp.push_back( bt );
if( !pv_coeff.isNull() ){
has_coeff.push_back( pv );
}
- Trace("cbqi-inst-debug") << i << ": ";
- if( !pv_coeff.isNull() ){
- Trace("cbqi-inst-debug") << pv_coeff << "*";
- }
- Trace("cbqi-inst-debug") << pv << " -> " << n << std::endl;
Node new_theta = theta;
if( !pv_coeff.isNull() ){
if( new_theta.isNull() ){
@@ -562,11 +688,12 @@ bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, std::
new_theta = Rewriter::rewrite( new_theta );
}
}
- success = addInstantiation( subs, vars, coeff, has_coeff, new_theta, i+1, effort );
+ success = addInstantiation( subs, vars, coeff, btyp, has_coeff, new_theta, i+1, effort );
if( !success ){
subs.pop_back();
vars.pop_back();
coeff.pop_back();
+ btyp.pop_back();
if( !pv_coeff.isNull() ){
has_coeff.pop_back();
}
@@ -590,7 +717,7 @@ bool CegInstantiator::addInstantiationInc( Node n, Node pv, Node pv_coeff, std::
}
bool CegInstantiator::addInstantiationCoeff( std::vector< Node >& subs, std::vector< Node >& vars,
- std::vector< Node >& coeff, std::vector< Node >& has_coeff, unsigned j ) {
+ std::vector< Node >& coeff, std::vector< int >& btyp, std::vector< Node >& has_coeff, unsigned j ) {
if( j==has_coeff.size() ){
return addInstantiation( subs, vars );
}else{
@@ -621,8 +748,9 @@ bool CegInstantiator::addInstantiationCoeff( std::vector< Node >& subs, std::vec
subs[index] = veq[1];
if( !veq_c.isNull() ){
subs[index] = NodeManager::currentNM()->mkNode( INTS_DIVISION, veq[1], veq_c );
- /*
- if( subs_typ[index]>=1 && subs_typ[index]<=2 ){
+ Trace("cbqi-inst-debug") << "...bound type is : " << btyp[index] << std::endl;
+ //intger division rounding up if from a lower bound
+ if( btyp[index]==1 ){
subs[index] = NodeManager::currentNM()->mkNode( PLUS, subs[index],
NodeManager::currentNM()->mkNode( ITE,
NodeManager::currentNM()->mkNode( EQUAL,
@@ -631,28 +759,11 @@ bool CegInstantiator::addInstantiationCoeff( std::vector< Node >& subs, std::vec
d_zero, d_one )
);
}
- */
}
Trace("cbqi-inst-debug") << "...normalize integers : " << subs[index] << std::endl;
- if( addInstantiationCoeff( subs, vars, coeff, has_coeff, j+1 ) ){
+ if( addInstantiationCoeff( subs, vars, coeff, btyp, has_coeff, j+1 ) ){
return true;
}
- //equalities are both upper and lower bounds
- /*
- if( subs_typ[index]==0 && !veq_c.isNull() ){
- subs[index] = NodeManager::currentNM()->mkNode( PLUS, subs[index],
- NodeManager::currentNM()->mkNode( ITE,
- NodeManager::currentNM()->mkNode( EQUAL,
- NodeManager::currentNM()->mkNode( INTS_MODULUS, veq[1], veq_c ),
- NodeManager::currentNM()->mkConst( Rational( 0 ) ) ),
- NodeManager::currentNM()->mkConst( Rational( 0 ) ),
- NodeManager::currentNM()->mkConst( Rational( 1 ) ) )
- );
- if( addInstantiationCoeff( subs, vars, coeff, has_coeff, j+1 ) ){
- return true;
- }
- }
- */
}
}
subs[index] = prev;
@@ -671,7 +782,7 @@ bool CegInstantiator::addInstantiation( std::vector< Node >& subs, std::vector<
Node CegInstantiator::applySubstitution( Node n, std::vector< Node >& subs, std::vector< Node >& vars,
- std::vector< Node >& coeff, std::vector< Node >& has_coeff, Node& pv_coeff, bool try_coeff ) {
+ std::vector< Node >& coeff, std::vector< Node >& has_coeff, Node& pv_coeff, bool try_coeff ) {
Assert( d_prog_var.find( n )!=d_prog_var.end() );
Assert( n==Rewriter::rewrite( n ) );
bool req_coeff = false;
@@ -752,21 +863,10 @@ Node CegInstantiator::applySubstitution( Node n, std::vector< Node >& subs, std:
}
}
-Node CegInstantiator::getModelBasedProjectionValue( Node t, bool strict, bool isLower, Node c, Node me, Node mt, Node theta ) {
+Node CegInstantiator::getModelBasedProjectionValue( Node t, bool isLower, Node c, Node me, Node mt, Node theta,
+ Node inf_coeff, Node vts_inf, Node delta_coeff, Node vts_delta ) {
Node val = t;
Trace("cbqi-bound2") << "Value : " << val << std::endl;
- //take into account strictness
- if( strict ){
- if( !d_use_vts_delta ){
- return Node::null();
- }else{
- Node delta = d_qe->getTermDatabase()->getVtsDelta();
- Kind k = isLower ? PLUS : MINUS;
- val = NodeManager::currentNM()->mkNode( k, val, delta );
- val = Rewriter::rewrite( val );
- Trace("cbqi-bound2") << "(after strict) : " << val << std::endl;
- }
- }
//add rho value
//get the value of c*e
Node ceValue = me;
@@ -801,6 +901,19 @@ Node CegInstantiator::getModelBasedProjectionValue( Node t, bool strict, bool is
val = Rewriter::rewrite( val );
Trace("cbqi-bound2") << "(after rho) : " << val << std::endl;
}
+ if( !inf_coeff.isNull() ){
+ Assert( !vts_inf.isNull() );
+ val = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkNode( MULT, inf_coeff, vts_inf ) );
+ val = Rewriter::rewrite( val );
+ }
+ if( !delta_coeff.isNull() ){
+ //create delta here if necessary
+ if( vts_delta.isNull() ){
+ vts_delta = d_qe->getTermDatabase()->getVtsDelta();
+ }
+ val = NodeManager::currentNM()->mkNode( PLUS, val, NodeManager::currentNM()->mkNode( MULT, delta_coeff, vts_delta ) );
+ val = Rewriter::rewrite( val );
+ }
return val;
}
@@ -809,14 +922,16 @@ bool CegInstantiator::check() {
Trace("cegqi-engine") << " CEGQI instantiator : wait until all ground theories are finished." << std::endl;
return false;
}
+ processAssertions();
for( unsigned r=0; r<2; r++ ){
std::vector< Node > subs;
std::vector< Node > vars;
std::vector< Node > coeff;
+ std::vector< int > btyp;
std::vector< Node > has_coeff;
Node theta;
//try to add an instantiation
- if( addInstantiation( subs, vars, coeff, has_coeff, theta, 0, r==0 ? 0 : 2 ) ){
+ if( addInstantiation( subs, vars, coeff, btyp, has_coeff, theta, 0, r==0 ? 0 : 2 ) ){
return true;
}
}
@@ -824,6 +939,279 @@ bool CegInstantiator::check() {
return false;
}
+void collectPresolveEqTerms( Node n, std::map< Node, std::vector< Node > >& teq ) {
+ if( n.getKind()==FORALL || n.getKind()==EXISTS ){
+ //do nothing
+ }else{
+ if( n.getKind()==EQUAL ){
+ for( unsigned i=0; i<2; i++ ){
+ std::map< Node, std::vector< Node > >::iterator it = teq.find( n[i] );
+ if( it!=teq.end() ){
+ Node nn = n[ i==0 ? 1 : 0 ];
+ if( std::find( it->second.begin(), it->second.end(), nn )==it->second.end() ){
+ it->second.push_back( nn );
+ Trace("cbqi-presolve") << " - " << n[i] << " = " << nn << std::endl;
+ }
+ }
+ }
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ collectPresolveEqTerms( n[i], teq );
+ }
+ }
+}
+
+void getPresolveEqConjuncts( std::vector< Node >& vars, std::vector< Node >& terms,
+ std::map< Node, std::vector< Node > >& teq, Node f, std::vector< Node >& conj ) {
+ if( conj.size()<1000 ){
+ if( terms.size()==f[0].getNumChildren() ){
+ Node c = f[1].substitute( vars.begin(), vars.end(), terms.begin(), terms.end() );
+ conj.push_back( c );
+ }else{
+ unsigned i = terms.size();
+ Node v = f[0][i];
+ terms.push_back( Node::null() );
+ for( unsigned j=0; j<teq[v].size(); j++ ){
+ terms[i] = teq[v][j];
+ getPresolveEqConjuncts( vars, terms, teq, f, conj );
+ }
+ terms.pop_back();
+ }
+ }
+}
+
+void CegInstantiator::presolve( Node q ) {
+ Trace("cbqi-presolve") << "CBQI presolve " << q << std::endl;
+ //at preregister time, add proxy of obvious instantiations up front, which helps learning during preprocessing
+ std::vector< Node > vars;
+ std::map< Node, std::vector< Node > > teq;
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
+ vars.push_back( q[0][i] );
+ teq[q[0][i]].clear();
+ }
+ collectPresolveEqTerms( q[1], teq );
+ std::vector< Node > terms;
+ std::vector< Node > conj;
+ getPresolveEqConjuncts( vars, terms, teq, q, conj );
+
+ if( !conj.empty() ){
+ Node lem = conj.size()==1 ? conj[0] : NodeManager::currentNM()->mkNode( AND, conj );
+ Node g = NodeManager::currentNM()->mkSkolem( "g", NodeManager::currentNM()->booleanType() );
+ lem = NodeManager::currentNM()->mkNode( OR, g, lem );
+ Trace("cbqi-presolve-debug") << "Presolve lemma : " << lem << std::endl;
+ d_qe->getOutputChannel().lemma( lem, false, true );
+ }
+}
+
+void CegInstantiator::processAssertions() {
+ Trace("cbqi-proc") << "--- Process assertions, #var = " << d_vars.size() << ", #aux-var = " << d_aux_vars.size() << std::endl;
+ d_curr_asserts.clear();
+ d_curr_eqc.clear();
+ d_curr_rep.clear();
+ d_curr_arith_eqc.clear();
+
+ eq::EqualityEngine* ee = d_qe->getMasterEqualityEngine();
+ //to eliminate identified illegal terms
+ std::map< Node, Node > aux_subs;
+
+ //for each variable
+ bool has_arith_var = false;
+ for( unsigned i=0; i<d_vars.size(); i++ ){
+ Node pv = d_vars[i];
+ TypeNode pvtn = pv.getType();
+ //collect current assertions
+ unsigned rmax = Theory::theoryOf( pv )==Theory::theoryOf( pv.getType() ) ? 1 : 2;
+ for( unsigned r=0; r<rmax; r++ ){
+ TheoryId tid = r==0 ? Theory::theoryOf( pv ) : Theory::theoryOf( pv.getType() );
+ Theory* theory = d_qe->getTheoryEngine()->theoryOf( tid );
+ Trace("cbqi-proc-debug") << "...theory of " << pv << " (r=" << r << ") is " << tid << std::endl;
+ if( d_curr_asserts.find( tid )==d_curr_asserts.end() ){
+ if (theory && d_qe->getTheoryEngine()->isTheoryEnabled(tid)) {
+ Trace("cbqi-proc") << "Collect assertions from " << tid << std::endl;
+ d_curr_asserts[tid].clear();
+ //collect all assertions from theory
+ for( context::CDList<Assertion>::const_iterator it = theory->facts_begin(); it != theory->facts_end(); ++ it) {
+ Node lit = (*it).assertion;
+ d_curr_asserts[tid].push_back( lit );
+ Trace("cbqi-proc-debug") << "...add : " << lit << std::endl;
+ if( lit.getKind()==EQUAL ){
+ std::map< Node, std::map< Node, Node > >::iterator itae = d_aux_eq.find( lit );
+ if( itae!=d_aux_eq.end() ){
+ for( std::map< Node, Node >::iterator itae2 = itae->second.begin(); itae2 != itae->second.end(); ++itae2 ){
+ aux_subs[ itae2->first ] = itae2->second;
+ Trace("cbqi-proc") << "......add substitution : " << itae2->first << " -> " << itae2->second << std::endl;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ //collect information about eqc
+ if( ee->hasTerm( pv ) ){
+ Node pvr = ee->getRepresentative( pv );
+ d_curr_rep[pv] = pvr;
+ if( d_curr_eqc.find( pvr )==d_curr_eqc.end() ){
+ Trace("cbqi-proc") << "Collect equivalence class " << pvr << std::endl;
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( pvr, ee );
+ while( !eqc_i.isFinished() ){
+ d_curr_eqc[pvr].push_back( *eqc_i );
+ ++eqc_i;
+ }
+ }
+ }
+ //has arith var
+ if( pvtn.isInteger() || pvtn.isReal() ){
+ has_arith_var = true;
+ }
+ }
+ //must process all arithmetic eqc if any arithmetic variable
+ if( has_arith_var ){
+ Trace("cbqi-proc-debug") << "...collect arithmetic equivalence classes" << std::endl;
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );
+ while( !eqcs_i.isFinished() ){
+ Node r = *eqcs_i;
+ TypeNode rtn = r.getType();
+ if( rtn.isInteger() || rtn.isReal() ){
+ Trace("cbqi-proc-debug") << "...arith eqc: " << r << std::endl;
+ d_curr_arith_eqc.push_back( r );
+ if( d_curr_eqc.find( r )==d_curr_eqc.end() ){
+ Trace("cbqi-proc") << "Collect equivalence class " << r << std::endl;
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );
+ while( !eqc_i.isFinished() ){
+ d_curr_eqc[r].push_back( *eqc_i );
+ ++eqc_i;
+ }
+ }
+ }
+ ++eqcs_i;
+ }
+ }
+ //construct substitution from union find
+ std::vector< Node > subs_lhs;
+ std::vector< Node > subs_rhs;
+ for( unsigned i=0; i<d_aux_vars.size(); i++ ){
+ Node r = d_aux_vars[i];
+ std::map< Node, Node >::iterator it = aux_subs.find( r );
+ if( it!=aux_subs.end() ){
+ addToAuxVarSubstitution( subs_lhs, subs_rhs, r, it->second );
+ }else{
+ Trace("cbqi-proc") << "....no substitution found for auxiliary variable " << r << "!!!" << std::endl;
+#ifdef MBP_STRICT_ASSERTIONS
+ Assert( false );
+#endif
+ }
+ }
+
+ //apply substitutions to everything, if necessary
+ if( !subs_lhs.empty() ){
+ Trace("cbqi-proc") << "Applying substitution : " << std::endl;
+ for( unsigned i=0; i<subs_lhs.size(); i++ ){
+ Trace("cbqi-proc") << " " << subs_lhs[i] << " -> " << subs_rhs[i] << std::endl;
+ }
+
+ for( std::map< TheoryId, std::vector< Node > >::iterator it = d_curr_asserts.begin(); it != d_curr_asserts.end(); ++it ){
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Node lit = it->second[i];
+ lit = lit.substitute( subs_lhs.begin(), subs_lhs.end(), subs_rhs.begin(), subs_rhs.end() );
+ lit = Rewriter::rewrite( lit );
+ it->second[i] = lit;
+ }
+ }
+ for( std::map< Node, std::vector< Node > >::iterator it = d_curr_eqc.begin(); it != d_curr_eqc.end(); ++it ){
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Node n = it->second[i];
+ n = n.substitute( subs_lhs.begin(), subs_lhs.end(), subs_rhs.begin(), subs_rhs.end() );
+ n = Rewriter::rewrite( n );
+ it->second[i] = n;
+ }
+ }
+ }
+
+ //remove unecessary assertions
+ for( std::map< TheoryId, std::vector< Node > >::iterator it = d_curr_asserts.begin(); it != d_curr_asserts.end(); ++it ){
+ std::vector< Node > akeep;
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ Node n = it->second[i];
+ //compute the variables in assertion
+ computeProgVars( n );
+ //must be an eligible term
+ if( d_inelig.find( n )==d_inelig.end() ){
+ //must contain at least one variable
+ if( !d_prog_var[n].empty() ){
+ Trace("cbqi-proc") << "...literal[" << it->first << "] : " << n << std::endl;
+ akeep.push_back( n );
+ }else{
+ Trace("cbqi-proc") << "...remove literal from " << it->first << " : " << n << " since it contains no relevant variables." << std::endl;
+ }
+ }else{
+ Trace("cbqi-proc") << "...remove literal from " << it->first << " : " << n << " since it contains ineligible terms." << std::endl;
+ }
+ }
+ it->second.clear();
+ it->second.insert( it->second.end(), akeep.begin(), akeep.end() );
+ }
+
+ //remove duplicate terms from eqc
+ for( std::map< Node, std::vector< Node > >::iterator it = d_curr_eqc.begin(); it != d_curr_eqc.end(); ++it ){
+ std::vector< Node > new_eqc;
+ for( unsigned i=0; i<it->second.size(); i++ ){
+ if( std::find( new_eqc.begin(), new_eqc.end(), it->second[i] )==new_eqc.end() ){
+ new_eqc.push_back( it->second[i] );
+ }
+ }
+ it->second.clear();
+ it->second.insert( it->second.end(), new_eqc.begin(), new_eqc.end() );
+ }
+}
+
+void CegInstantiator::addToAuxVarSubstitution( std::vector< Node >& subs_lhs, std::vector< Node >& subs_rhs, Node l, Node r ) {
+ r = r.substitute( subs_lhs.begin(), subs_lhs.end(), subs_rhs.begin(), subs_rhs.end() );
+
+ std::vector< Node > cl;
+ cl.push_back( l );
+ std::vector< Node > cr;
+ cr.push_back( r );
+ for( unsigned i=0; i<subs_lhs.size(); i++ ){
+ Node nr = subs_rhs[i].substitute( cl.begin(), cl.end(), cr.begin(), cr.end() );
+ nr = Rewriter::rewrite( nr );
+ subs_rhs[i] = nr;
+ }
+
+ subs_lhs.push_back( l );
+ subs_rhs.push_back( r );
+}
+
+void CegInstantiator::registerCounterexampleLemma( std::vector< Node >& lems, std::vector< Node >& ce_vars ) {
+ Assert( d_vars.empty() );
+ d_vars.insert( d_vars.end(), ce_vars.begin(), ce_vars.end() );
+ IteSkolemMap iteSkolemMap;
+ d_qe->getTheoryEngine()->getIteRemover()->run(lems, iteSkolemMap);
+ Assert( d_aux_vars.empty() );
+ for(IteSkolemMap::iterator i = iteSkolemMap.begin(); i != iteSkolemMap.end(); ++i) {
+ Trace("cbqi-debug") << " Auxiliary var (from ITE) : " << i->first << std::endl;
+ d_aux_vars.push_back( i->first );
+ }
+ for( unsigned i=0; i<lems.size(); i++ ){
+ Trace("cbqi-debug") << "Counterexample lemma (pre-rewrite) " << i << " : " << lems[i] << std::endl;
+ Node rlem = lems[i];
+ rlem = Rewriter::rewrite( rlem );
+ Trace("cbqi-debug") << "Counterexample lemma (post-rewrite) " << i << " : " << rlem << std::endl;
+ //record the literals that imply auxiliary variables to be equal to terms
+ if( lems[i].getKind()==ITE && rlem.getKind()==ITE ){
+ if( lems[i][1].getKind()==EQUAL && lems[i][2].getKind()==EQUAL && lems[i][1][0]==lems[i][2][0] ){
+ if( std::find( d_aux_vars.begin(), d_aux_vars.end(), lems[i][1][0] )!=d_aux_vars.end() ){
+ Node v = lems[i][1][0];
+ for( unsigned r=1; r<=2; r++ ){
+ d_aux_eq[rlem[r]][v] = lems[i][r][1];
+ Trace("cbqi-debug") << " " << rlem[r] << " implies " << v << " = " << lems[i][r][1] << std::endl;
+ }
+ }
+ }
+ }
+ lems[i] = rlem;
+ }
+}
//old implementation
@@ -1173,17 +1561,7 @@ int InstStrategyCegqi::process( Node f, Theory::Effort effort, int e ) {
if( e<1 ){
return STATUS_UNFINISHED;
}else if( e==1 ){
- CegInstantiator * cinst;
- std::map< Node, CegInstantiator * >::iterator it = d_cinst.find( f );
- if( it==d_cinst.end() ){
- cinst = new CegInstantiator( d_quantEngine, d_out );
- for( int i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
- cinst->d_vars.push_back( d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) );
- }
- d_cinst[f] = cinst;
- }else{
- cinst = it->second;
- }
+ CegInstantiator * cinst = getInstantiator( f );
Trace("inst-alg") << "-> Run cegqi for " << f << std::endl;
d_curr_quant = f;
bool addedLemma = cinst->check();
@@ -1192,23 +1570,22 @@ int InstStrategyCegqi::process( Node f, Theory::Effort effort, int e ) {
}else if( e==2 ){
//minimize the free delta heuristically on demand
if( d_check_vts_lemma_lc ){
+ d_check_vts_lemma_lc = false;
+ d_small_const = NodeManager::currentNM()->mkNode( MULT, d_small_const, d_small_const );
+ d_small_const = Rewriter::rewrite( d_small_const );
+ //heuristic for now, until we know how to do nested quantification
Node delta = d_quantEngine->getTermDatabase()->getVtsDelta( true, false );
- Node inf = d_quantEngine->getTermDatabase()->getVtsInfinity( true, false );
- if( !delta.isNull() || !inf.isNull() ){
- d_check_vts_lemma_lc = false;
- d_small_const = NodeManager::currentNM()->mkNode( MULT, d_small_const, d_small_const );
- d_small_const = Rewriter::rewrite( d_small_const );
- //heuristic for now, until we know how to do nested quantification
- if( !delta.isNull() ){
- Trace("cegqi") << "Delta lemma for " << d_small_const << std::endl;
- Node delta_lem_ub = NodeManager::currentNM()->mkNode( LT, delta, d_small_const );
- d_quantEngine->getOutputChannel().lemma( delta_lem_ub );
- }
- if( !inf.isNull() ){
- Trace("cegqi") << "Infinity lemma for " << d_small_const << std::endl;
- Node inf_lem_lb = NodeManager::currentNM()->mkNode( GT, inf, NodeManager::currentNM()->mkConst( Rational(1)/d_small_const.getConst<Rational>() ) );
- d_quantEngine->getOutputChannel().lemma( inf_lem_lb );
- }
+ if( !delta.isNull() ){
+ Trace("quant-vts-debug") << "Delta lemma for " << d_small_const << std::endl;
+ Node delta_lem_ub = NodeManager::currentNM()->mkNode( LT, delta, d_small_const );
+ d_quantEngine->getOutputChannel().lemma( delta_lem_ub );
+ }
+ std::vector< Node > inf;
+ d_quantEngine->getTermDatabase()->getVtsTerms( inf, true, false, false );
+ for( unsigned i=0; i<inf.size(); i++ ){
+ Trace("quant-vts-debug") << "Infinity lemma for " << inf[i] << " " << d_small_const << std::endl;
+ Node inf_lem_lb = NodeManager::currentNM()->mkNode( GT, inf[i], NodeManager::currentNM()->mkConst( Rational(1)/d_small_const.getConst<Rational>() ) );
+ d_quantEngine->getOutputChannel().lemma( inf_lem_lb );
}
}
}
@@ -1217,31 +1594,8 @@ int InstStrategyCegqi::process( Node f, Theory::Effort effort, int e ) {
bool InstStrategyCegqi::addInstantiation( std::vector< Node >& subs ) {
Assert( !d_curr_quant.isNull() );
- /*
- std::stringstream siss;
- if( Trace.isOn("inst-cegqi") || Trace.isOn("inst-cegqi-debug") ){
- for( unsigned j=0; j<d_single_inv_sk.size(); j++ ){
- Node v = d_single_inv_map_to_prog[d_single_inv[0][j]];
- siss << " * " << v;
- siss << " (" << d_single_inv_sk[j] << ")";
- siss << " -> " << ( subs_typ[j]==9 ? "M:" : "") << subs[j] << std::endl;
- }
- }
- */
- //check if we need virtual term substitution (if used delta)
- bool used_vts = false;
- Node delta = d_quantEngine->getTermDatabase()->getVtsDelta( false, false );
- Node inf = d_quantEngine->getTermDatabase()->getVtsInfinity( false, false );
- if( !delta.isNull() || !inf.isNull() ){
- for( unsigned i=0; i<subs.size(); i++ ){
- if( !delta.isNull() && TermDb::containsTerm( subs[i], delta ) ){
- used_vts = true;
- }
- if( !inf.isNull() && TermDb::containsTerm( subs[i], inf ) ){
- used_vts = true;
- }
- }
- }
+ //check if we need virtual term substitution (if used delta or infinity)
+ bool used_vts = d_quantEngine->getTermDatabase()->containsVtsTerm( subs, false );
return d_quantEngine->addInstantiation( d_curr_quant, subs, false, false, false, used_vts );
}
@@ -1258,15 +1612,28 @@ bool InstStrategyCegqi::isEligibleForInstantiation( Node n ) {
}
}
+CegInstantiator * InstStrategyCegqi::getInstantiator( Node q ) {
+ std::map< Node, CegInstantiator * >::iterator it = d_cinst.find( q );
+ if( it==d_cinst.end() ){
+ CegInstantiator * cinst = new CegInstantiator( d_quantEngine, d_out, true, true );
+ d_cinst[q] = cinst;
+ return cinst;
+ }else{
+ return it->second;
+ }
+}
+void InstStrategyCegqi::registerQuantifier( Node q ) {
+ if( options::cbqiPreRegInst() ){
+ //just get the instantiator
+ getInstantiator( q );
+ }
+}
-
-
-
-
-
-
-
-
-
-
+void InstStrategyCegqi::presolve() {
+ if( options::cbqiPreRegInst() ){
+ for( std::map< Node, CegInstantiator * >::iterator it = d_cinst.begin(); it != d_cinst.end(); ++it ){
+ it->second->presolve( it->first );
+ }
+ }
+}
diff --git a/src/theory/quantifiers/inst_strategy_cbqi.h b/src/theory/quantifiers/inst_strategy_cbqi.h
index 4f5049cd8..f882da110 100644
--- a/src/theory/quantifiers/inst_strategy_cbqi.h
+++ b/src/theory/quantifiers/inst_strategy_cbqi.h
@@ -9,14 +9,14 @@
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief instantiator_arith_instantiator
+ ** \brief counterexample-guided quantifier instantiation
**/
#include "cvc4_private.h"
-#ifndef __CVC4__INST_STRATEGT_CBQI_H
-#define __CVC4__INST_STRATEGT_CBQI_H
+#ifndef __CVC4__INST_STRATEGY_CBQI_H
+#define __CVC4__INST_STRATEGY_CBQI_H
#include "theory/quantifiers/instantiation_engine.h"
#include "theory/arith/arithvar.h"
@@ -30,10 +30,6 @@ namespace arith {
class TheoryArith;
}
-namespace datatypes {
- class TheoryDatatypes;
-}
-
namespace quantifiers {
class CegqiOutput
@@ -59,28 +55,46 @@ private:
//program variable contains cache
std::map< Node, std::map< Node, bool > > d_prog_var;
std::map< Node, bool > d_inelig;
+ //current assertions
+ std::map< TheoryId, std::vector< Node > > d_curr_asserts;
+ std::map< Node, std::vector< Node > > d_curr_eqc;
+ std::map< Node, Node > d_curr_rep;
+ std::vector< Node > d_curr_arith_eqc;
+ //auxiliary variables
+ std::vector< Node > d_aux_vars;
+ //literals to equalities for aux vars
+ std::map< Node, std::map< Node, Node > > d_aux_eq;
+ //the CE variables
+ std::vector< Node > d_vars;
private:
//for adding instantiations during check
void computeProgVars( Node n );
// effort=0 : do not use model value, 1: use model value, 2: one must use model value
bool addInstantiation( std::vector< Node >& subs, std::vector< Node >& vars,
- std::vector< Node >& coeff, std::vector< Node >& has_coeff, Node theta,
+ std::vector< Node >& coeff, std::vector< int >& btyp,
+ std::vector< Node >& has_coeff, Node theta,
unsigned i, unsigned effort );
- bool addInstantiationInc( Node n, Node pv, Node pv_coeff, std::vector< Node >& subs, std::vector< Node >& vars,
- std::vector< Node >& coeff, std::vector< Node >& has_coeff, Node theta, unsigned i, unsigned effort );
+ bool addInstantiationInc( Node n, Node pv, Node pv_coeff, int bt, std::vector< Node >& subs, std::vector< Node >& vars,
+ std::vector< Node >& coeff, std::vector< int >& btyp,
+ std::vector< Node >& has_coeff, Node theta, unsigned i, unsigned effort );
bool addInstantiationCoeff( std::vector< Node >& subs, std::vector< Node >& vars,
- std::vector< Node >& coeff, std::vector< Node >& has_coeff,
- unsigned j );
+ std::vector< Node >& coeff, std::vector< int >& btyp,
+ std::vector< Node >& has_coeff, unsigned j );
bool addInstantiation( std::vector< Node >& subs, std::vector< Node >& vars );
Node applySubstitution( Node n, std::vector< Node >& subs, std::vector< Node >& vars,
std::vector< Node >& coeff, std::vector< Node >& has_coeff, Node& pv_coeff, bool try_coeff = true );
- Node getModelBasedProjectionValue( Node t, bool strict, bool isLower, Node c, Node me, Node mt, Node theta );
+ Node getModelBasedProjectionValue( Node t, bool isLower, Node c, Node me, Node mt, Node theta,
+ Node inf_coeff, Node vts_inf, Node delta_coeff, Node vts_delta );
+ void processAssertions();
+ void addToAuxVarSubstitution( std::vector< Node >& subs_lhs, std::vector< Node >& subs_rhs, Node l, Node r );
public:
CegInstantiator( QuantifiersEngine * qe, CegqiOutput * out, bool use_vts_delta = true, bool use_vts_inf = true );
- //the CE variables
- std::vector< Node > d_vars;
//check : add instantiations based on valuation of d_vars
bool check();
+ //presolve for quantified formula
+ void presolve( Node q );
+ //register the counterexample lemma (stored in lems), modify vector
+ void registerCounterexampleLemma( std::vector< Node >& lems, std::vector< Node >& ce_vars );
};
class InstStrategySimplex : public InstStrategy{
@@ -159,6 +173,13 @@ public:
bool addLemma( Node lem );
/** identify */
std::string identify() const { return std::string("Cegqi"); }
+
+ //get instantiator for quantifier
+ CegInstantiator * getInstantiator( Node q );
+ //register quantifier
+ void registerQuantifier( Node q );
+ //presolve
+ void presolve();
};
}
diff --git a/src/theory/quantifiers/instantiation_engine.cpp b/src/theory/quantifiers/instantiation_engine.cpp
index b686ddb3b..699208fba 100644
--- a/src/theory/quantifiers/instantiation_engine.cpp
+++ b/src/theory/quantifiers/instantiation_engine.cpp
@@ -76,6 +76,11 @@ void InstantiationEngine::finishInit(){
}
}
+void InstantiationEngine::presolve() {
+ for( unsigned i=0; i<d_instStrategies.size(); ++i ){
+ d_instStrategies[i]->presolve();
+ }
+}
bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
unsigned lastWaiting = d_quantEngine->d_lemmas_waiting.size();
@@ -101,7 +106,26 @@ bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
//add counterexample lemma
lem = Rewriter::rewrite( lem );
Trace("cbqi") << "Counterexample lemma : " << lem << std::endl;
- d_quantEngine->addLemma( lem, false );
+
+ if( d_i_cegqi ){
+ //must register with the instantiator
+ //must explicitly remove ITEs so that we record dependencies
+ std::vector< Node > ce_vars;
+ for( int i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+ ce_vars.push_back( d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) );
+ }
+ std::vector< Node > lems;
+ lems.push_back( lem );
+ CegInstantiator * cinst = d_i_cegqi->getInstantiator( f );
+ cinst->registerCounterexampleLemma( lems, ce_vars );
+ for( unsigned i=0; i<lems.size(); i++ ){
+ Trace("cbqi-debug") << "Counterexample lemma " << i << " : " << lems[i] << std::endl;
+ d_quantEngine->addLemma( lems[i], false );
+ }
+ }else{
+ Trace("cbqi-debug") << "Counterexample lemma : " << lem << std::endl;
+ d_quantEngine->addLemma( lem, false );
+ }
addedLemma = true;
}
}
@@ -250,6 +274,9 @@ bool InstantiationEngine::checkComplete() {
void InstantiationEngine::registerQuantifier( Node f ){
if( d_quantEngine->hasOwnership( f, this ) ){
+ for( unsigned i=0; i<d_instStrategies.size(); ++i ){
+ d_instStrategies[i]->registerQuantifier( f );
+ }
//Notice() << "do cbqi " << f << " ? " << std::endl;
if( options::cbqi() ){
Node ceBody = d_quantEngine->getTermDatabase()->getInstConstantBody( f );
diff --git a/src/theory/quantifiers/instantiation_engine.h b/src/theory/quantifiers/instantiation_engine.h
index 44612a85c..1f321917b 100644
--- a/src/theory/quantifiers/instantiation_engine.h
+++ b/src/theory/quantifiers/instantiation_engine.h
@@ -43,12 +43,16 @@ protected:
public:
InstStrategy( QuantifiersEngine* qe ) : d_quantEngine( qe ){}
virtual ~InstStrategy(){}
+ /** presolve */
+ virtual void presolve() {}
/** reset instantiation */
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
/** process method, returns a status */
virtual int process( Node f, Theory::Effort effort, int e ) = 0;
/** identify */
virtual std::string identify() const { return std::string("Unknown"); }
+ /** register quantifier */
+ virtual void registerQuantifier( Node q ) {}
};/* class InstStrategy */
class InstantiationEngine : public QuantifiersModule
@@ -96,7 +100,7 @@ public:
~InstantiationEngine();
/** initialize */
void finishInit();
-
+ void presolve();
bool needsCheck( Theory::Effort e );
unsigned needsModel( Theory::Effort e );
void reset_round( Theory::Effort e );
diff --git a/src/theory/quantifiers/options b/src/theory/quantifiers/options
index 48a9fdea2..ec71e5348 100644
--- a/src/theory/quantifiers/options
+++ b/src/theory/quantifiers/options
@@ -17,7 +17,8 @@ option miniscopeQuant --miniscope-quant bool :default true :read-write
# ( forall x. P( x ) ) V Q
option miniscopeQuantFreeVar --miniscope-quant-fv bool :default true :read-write
disable miniscope quantifiers for ground subformulas
-# Whether to prenex (nested universal) quantifiers
+option clauseSplit --clause-split bool :default true
+ apply clause splitting to quantified formulas
option prenexQuant --prenex-quant=MODE CVC4::theory::quantifiers::PrenexQuantMode :default CVC4::theory::quantifiers::PRENEX_NO_USER_PAT :include "theory/quantifiers/modes.h" :read-write :handler CVC4::theory::quantifiers::stringToPrenexQuantMode :handler-include "theory/quantifiers/options_handlers.h"
prenex mode for quantified formulas
# Whether to variable-eliminate quantifiers.
@@ -37,11 +38,8 @@ option iteDtTesterSplitQuant --ite-dtt-split-quant bool :read-write :default fal
# Whether to CNF quantifier bodies
# option cnfQuant --cnf-quant bool :default false
# apply CNF conversion to quantified formulas
-# Whether to NNF quantifier bodies
option nnfQuant --nnf-quant bool :default true
apply NNF conversion to quantified formulas
-option clauseSplit --clause-split bool :default true
- apply clause splitting to quantified formulas
# Whether to pre-skolemize quantifier bodies.
# For example, forall x. ( P( x ) => (exists y. f( y ) = x) ) will be rewritten to
# forall x. P( x ) => f( S( x ) ) = x
@@ -51,10 +49,8 @@ option preSkolemQuantNested --pre-skolem-quant-nested bool :read-write :default
apply skolemization to nested quantified formulass
option preSkolemQuantAgg --pre-skolem-quant-agg bool :read-write :default true
apply skolemization to quantified formulas aggressively
-# Whether to perform agressive miniscoping
option aggressiveMiniscopeQuant --ag-miniscope-quant bool :default false
perform aggressive miniscoping for quantifiers
-# Whether to CNF quantifier bodies
option elimTautQuant --elim-taut-quant bool :default true
eliminate tautological disjuncts of quantified formulas
@@ -212,8 +208,6 @@ option cegqiSingleInvReconstruct --cegqi-si-reconstruct bool :default true
reconstruct solutions for single invocation conjectures in original grammar
option cegqiSingleInvReconstructConst --cegqi-si-reconstruct-const bool :default true
include constants when reconstruct solutions for single invocation conjectures in original grammar
-option cegqiSingleInvPreRegInst --cegqi-si-prereg-inst bool :default true
- preregister ground instantiations when single invocation
option cegqiSingleInvAbort --cegqi-si-abort bool :default false
abort if synthesis conjecture is not single invocation
option cegqiSingleInvMultiInstAbort --cegqi-si-multi-inst-abort bool :default false
@@ -240,12 +234,20 @@ option cbqi --cbqi bool :read-write :default false
turns on counterexample-based quantifier instantiation
option cbqi2 --cbqi2 bool :read-write :default false
turns on new implementation of counterexample-based quantifier instantiation
-option recurseCbqi --cbqi-recurse bool :default false
+option recurseCbqi --cbqi-recurse bool :default true
turns on recursive counterexample-based quantifier instantiation
option cbqiSat --cbqi-sat bool :read-write :default true
answer sat when quantifiers are asserted with counterexample-based quantifier instantiation
option cbqiModel --cbqi-model bool :read-write :default true
guide instantiations by model values for counterexample-based quantifier instantiation
+option cbqiUseInfInt --cbqi-use-inf-int bool :read-write :default false
+ use integer infinity for vts in counterexample-based quantifier instantiation
+option cbqiUseInfReal --cbqi-use-inf-real bool :read-write :default false
+ use real infinity for vts in counterexample-based quantifier instantiation
+option cbqiPreRegInst --cbqi-prereg-inst bool :read-write :default false
+ preregister ground instantiations in counterexample-based quantifier instantiation
+option cbqiMinBounds --cbqi-min-bounds bool :default false
+ use minimally constrained lower/upper bound for counterexample-based quantifier instantiation
### local theory extensions options
diff --git a/src/theory/quantifiers/quant_util.cpp b/src/theory/quantifiers/quant_util.cpp
index 2c65b62b3..ebeb4b871 100644
--- a/src/theory/quantifiers/quant_util.cpp
+++ b/src/theory/quantifiers/quant_util.cpp
@@ -115,10 +115,14 @@ int QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind
(children.size()==1 ? children[0] : NodeManager::currentNM()->mkConst( Rational(0) ));
Node vc = v;
if( !r.isOne() && !r.isNegativeOne() ){
- if( doCoeff ){
- vc = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( r.abs() ), vc );
+ if( vc.getType().isInteger() ){
+ if( doCoeff ){
+ vc = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( r.abs() ), vc );
+ }else{
+ return 0;
+ }
}else{
- return 0;
+ veq = NodeManager::currentNM()->mkNode( MULT, veq, NodeManager::currentNM()->mkConst( Rational(1) / r.abs() ) );
}
}
if( r.sgn()==1 ){
@@ -313,15 +317,20 @@ void QuantPhaseReq::computePhaseReqs( Node n, bool polarity, std::map< Node, int
}
void QuantPhaseReq::getPolarity( Node n, int child, bool hasPol, bool pol, bool& newHasPol, bool& newPol ) {
- newHasPol = hasPol;
- newPol = pol;
- if( n.getKind()==NOT || ( n.getKind()==IMPLIES && child==0 ) ){
+ if( n.getKind()==AND || n.getKind()==OR ){
+ newHasPol = hasPol;
+ newPol = pol;
+ }else if( n.getKind()==IMPLIES ){
+ newHasPol = hasPol;
+ newPol = child==0 ? !pol : pol;
+ }else if( n.getKind()==NOT ){
+ newHasPol = hasPol;
newPol = !pol;
- }else if( n.getKind()==IFF || n.getKind()==XOR ){
- newHasPol = false;
}else if( n.getKind()==ITE ){
- if( child==0 ){
- newHasPol = false;
- }
+ newHasPol = (child!=0) && hasPol;
+ newPol = pol;
+ }else{
+ newHasPol = false;
+ newPol = pol;
}
}
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index d6cbe386c..c32aeeb78 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -415,89 +415,105 @@ void QuantifiersRewriter::computeDtTesterIteSplit( Node n, std::map< Node, Node
}
}
-Node QuantifiersRewriter::computeProcessIte( Node body, bool hasPol, bool pol ) {
- if( body.getType().isBoolean() ){
- if( body.getKind()==EQUAL && options::iteLiftQuant()!=ITE_LIFT_QUANT_MODE_NONE ){
- for( size_t i=0; i<2; i++ ){
- if( body[i].getKind()==ITE ){
- Node no = i==0 ? body[1] : body[0];
- if( no.getKind()!=ITE ){
- bool doRewrite = options::iteLiftQuant()==ITE_LIFT_QUANT_MODE_ALL;
- std::vector< Node > children;
- children.push_back( body[i][0] );
- for( size_t j=1; j<=2; j++ ){
- //check if it rewrites to a constant
- Node nn = NodeManager::currentNM()->mkNode( EQUAL, no, body[i][j] );
- nn = Rewriter::rewrite( nn );
- children.push_back( nn );
- if( nn.isConst() ){
- doRewrite = true;
- }
- }
- if( doRewrite ){
- return NodeManager::currentNM()->mkNode( ITE, children );
+Node QuantifiersRewriter::computeProcessIte( Node body, bool hasPol, bool pol, std::map< Node, bool >& currCond ) {
+ if( body.getKind()==EQUAL && options::iteLiftQuant()!=ITE_LIFT_QUANT_MODE_NONE ){
+ for( size_t i=0; i<2; i++ ){
+ if( body[i].getKind()==ITE ){
+ Node no = i==0 ? body[1] : body[0];
+ if( no.getKind()!=ITE ){
+ bool doRewrite = options::iteLiftQuant()==ITE_LIFT_QUANT_MODE_ALL;
+ std::vector< Node > children;
+ children.push_back( body[i][0] );
+ for( size_t j=1; j<=2; j++ ){
+ //check if it rewrites to a constant
+ Node nn = NodeManager::currentNM()->mkNode( EQUAL, no, body[i][j] );
+ nn = Rewriter::rewrite( nn );
+ children.push_back( nn );
+ if( nn.isConst() ){
+ doRewrite = true;
}
}
+ if( doRewrite ){
+ return NodeManager::currentNM()->mkNode( ITE, children );
+ }
}
}
- }else if( body.getKind()==ITE && hasPol ){
- if( options::iteCondVarSplitQuant() ){
- Trace("quantifiers-rewrite-ite-debug") << "Conditional var eq split " << body << std::endl;
- for( unsigned r=0; r<2; r++ ){
- //check if there is a variable elimination
- Node b = r==0 ? body[0] : body[0].negate();
- QuantPhaseReq qpr( b );
- std::vector< Node > vars;
- std::vector< Node > subs;
- Trace("quantifiers-rewrite-ite-debug") << "phase req " << body[0] << " #: " << qpr.d_phase_reqs.size() << std::endl;
- for( std::map< Node, bool >::iterator it = qpr.d_phase_reqs.begin(); it != qpr.d_phase_reqs.end(); ++it ){
- Trace("quantifiers-rewrite-ite-debug") << "phase req " << it->first << " -> " << it->second << std::endl;
- if( it->second ){
- if( it->first.getKind()==EQUAL ){
- for( unsigned i=0; i<2; i++ ){
- if( it->first[i].getKind()==BOUND_VARIABLE ){
- unsigned j = i==0 ? 1 : 0;
- if( !hasArg1( it->first[i], it->first[j] ) ){
- vars.push_back( it->first[i] );
- subs.push_back( it->first[j] );
- break;
- }
+ }
+ }else if( body.getKind()==ITE ){
+ if( body.getType().isBoolean() && hasPol && options::iteCondVarSplitQuant() ){
+ Trace("quantifiers-rewrite-ite-debug") << "Conditional var eq split " << body << std::endl;
+ for( unsigned r=0; r<2; r++ ){
+ //check if there is a variable elimination
+ Node b = r==0 ? body[0] : body[0].negate();
+ QuantPhaseReq qpr( b );
+ std::vector< Node > vars;
+ std::vector< Node > subs;
+ Trace("quantifiers-rewrite-ite-debug") << "phase req " << body[0] << " #: " << qpr.d_phase_reqs.size() << std::endl;
+ for( std::map< Node, bool >::iterator it = qpr.d_phase_reqs.begin(); it != qpr.d_phase_reqs.end(); ++it ){
+ Trace("quantifiers-rewrite-ite-debug") << "phase req " << it->first << " -> " << it->second << std::endl;
+ if( it->second ){
+ if( it->first.getKind()==EQUAL ){
+ for( unsigned i=0; i<2; i++ ){
+ if( it->first[i].getKind()==BOUND_VARIABLE ){
+ unsigned j = i==0 ? 1 : 0;
+ if( !hasArg1( it->first[i], it->first[j] ) ){
+ vars.push_back( it->first[i] );
+ subs.push_back( it->first[j] );
+ break;
}
}
}
}
}
- if( !vars.empty() ){
- //bool cpol = (r==1);
- Node pos = NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] );
- //pos = pos.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- //pos = Rewriter::rewrite( pos );
- Node neg = NodeManager::currentNM()->mkNode( OR, body[0], body[2] );
- Trace("quantifiers-rewrite-ite") << "*** Split ITE (conditional variable eq) " << body << " into : " << std::endl;
- Trace("quantifiers-rewrite-ite") << " " << pos << std::endl;
- Trace("quantifiers-rewrite-ite") << " " << neg << std::endl;
- return NodeManager::currentNM()->mkNode( AND, pos, neg );
- }
+ }
+ if( !vars.empty() ){
+ //bool cpol = (r==1);
+ Node pos = NodeManager::currentNM()->mkNode( OR, body[0].negate(), body[1] );
+ //pos = pos.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
+ //pos = Rewriter::rewrite( pos );
+ Node neg = NodeManager::currentNM()->mkNode( OR, body[0], body[2] );
+ Trace("quantifiers-rewrite-ite") << "*** Split ITE (conditional variable eq) " << body << " into : " << std::endl;
+ Trace("quantifiers-rewrite-ite") << " " << pos << std::endl;
+ Trace("quantifiers-rewrite-ite") << " " << neg << std::endl;
+ return NodeManager::currentNM()->mkNode( AND, pos, neg );
}
}
}
- if( body.getKind()!=EQUAL && body.getKind()!=APPLY_UF ){
- bool changed = false;
- std::vector< Node > children;
- for( size_t i=0; i<body.getNumChildren(); i++ ){
- bool newHasPol;
- bool newPol;
- QuantPhaseReq::getPolarity( body, i, hasPol, pol, newHasPol, newPol );
- Node nn = computeProcessIte( body[i], newHasPol, newPol );
- children.push_back( nn );
- changed = changed || nn!=body[i];
- }
- if( changed ){
- return NodeManager::currentNM()->mkNode( body.getKind(), children );
+ }
+ bool changed = false;
+ std::vector< Node > children;
+ for( size_t i=0; i<body.getNumChildren(); i++ ){
+ bool newHasPol;
+ bool newPol;
+ QuantPhaseReq::getPolarity( body, i, hasPol, pol, newHasPol, newPol );
+ if( body.getKind()==ITE && i>0 ){
+ currCond[children[0]] = (i==1);
+ }
+ Node nn = computeProcessIte( body[i], newHasPol, newPol, currCond );
+ if( body.getKind()==ITE && i==0 ){
+ std::map< Node, bool >::iterator itc = currCond.find( nn );
+ if( itc!=currCond.end() ){
+ if( itc->second ){
+ return computeProcessIte( body[1], hasPol, pol, currCond );
+ }else{
+ return computeProcessIte( body[2], hasPol, pol, currCond );
+ }
}
}
+ children.push_back( nn );
+ changed = changed || nn!=body[i];
+ }
+ if( body.getKind()==ITE ){
+ currCond.erase( children[0] );
+ }
+ if( changed ){
+ if( body.getMetaKind() == kind::metakind::PARAMETERIZED ){
+ children.insert( children.begin(), body.getOperator() );
+ }
+ return NodeManager::currentNM()->mkNode( body.getKind(), children );
+ }else{
+ return body;
}
- return body;
}
Node QuantifiersRewriter::computeProcessIte2( Node body ){
@@ -1140,7 +1156,9 @@ bool QuantifiersRewriter::doOperation( Node f, bool isNested, int computeOption
}else if( computeOption==COMPUTE_NNF ){
return options::nnfQuant();
}else if( computeOption==COMPUTE_PROCESS_ITE ){
- return options::iteLiftQuant()!=ITE_LIFT_QUANT_MODE_NONE || options::iteCondVarSplitQuant();
+ //always eliminate redundant conditions in ITE
+ return true;
+ //return options::iteLiftQuant()!=ITE_LIFT_QUANT_MODE_NONE || options::iteCondVarSplitQuant();
}else if( computeOption==COMPUTE_PROCESS_ITE_2 ){
return options::iteDtTesterSplitQuant();
}else if( computeOption==COMPUTE_PRENEX ){
@@ -1182,7 +1200,8 @@ Node QuantifiersRewriter::computeOperation( Node f, bool isNested, int computeOp
}else if( computeOption==COMPUTE_NNF ){
n = computeNNF( n );
}else if( computeOption==COMPUTE_PROCESS_ITE ){
- n = computeProcessIte( n, true, true );
+ std::map< Node, bool > curr_cond;
+ n = computeProcessIte( n, true, true, curr_cond );
}else if( computeOption==COMPUTE_PROCESS_ITE_2 ){
n = computeProcessIte2( n );
}else if( computeOption==COMPUTE_PRENEX ){
diff --git a/src/theory/quantifiers/quantifiers_rewriter.h b/src/theory/quantifiers/quantifiers_rewriter.h
index d01677171..7db80c84b 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.h
+++ b/src/theory/quantifiers/quantifiers_rewriter.h
@@ -46,7 +46,7 @@ private:
static Node computeMiniscoping( Node f, std::vector< Node >& args, Node body, Node ipl );
static Node computeAggressiveMiniscoping( std::vector< Node >& args, Node body );
static Node computeNNF( Node body );
- static Node computeProcessIte( Node body, bool hasPol, bool pol );
+ static Node computeProcessIte( Node body, bool hasPol, bool pol, std::map< Node, bool >& currCond );
static Node computeProcessIte2( Node body );
static Node computeVarElimination( Node body, std::vector< Node >& args, Node& ipl );
static Node computeCNF( Node body, std::vector< Node >& args, NodeBuilder<>& defs, bool forcePred );
diff --git a/src/theory/quantifiers/term_database.cpp b/src/theory/quantifiers/term_database.cpp
index eefa45770..52aee392b 100644
--- a/src/theory/quantifiers/term_database.cpp
+++ b/src/theory/quantifiers/term_database.cpp
@@ -1294,11 +1294,25 @@ Node TermDb::getCanonicalTerm( TNode n, bool apply_torder ){
return getCanonicalTerm( n, var_count, subs, apply_torder );
}
+void TermDb::getVtsTerms( std::vector< Node >& t, bool isFree, bool create, bool inc_delta ) {
+ if( inc_delta ){
+ Node delta = getVtsDelta( isFree, create );
+ if( !delta.isNull() ){
+ t.push_back( delta );
+ }
+ }
+ for( unsigned r=0; r<2; r++ ){
+ Node inf = getVtsInfinityIndex( r, isFree, create );
+ if( !inf.isNull() ){
+ t.push_back( inf );
+ }
+ }
+}
Node TermDb::getVtsDelta( bool isFree, bool create ) {
if( create ){
if( d_vts_delta_free.isNull() ){
- d_vts_delta_free = NodeManager::currentNM()->mkSkolem( "delta", NodeManager::currentNM()->realType(), "free delta for virtual term substitution" );
+ d_vts_delta_free = NodeManager::currentNM()->mkSkolem( "delta_free", NodeManager::currentNM()->realType(), "free delta for virtual term substitution" );
Node delta_lem = NodeManager::currentNM()->mkNode( GT, d_vts_delta_free, NodeManager::currentNM()->mkConst( Rational( 0 ) ) );
d_quantEngine->getOutputChannel().lemma( delta_lem );
}
@@ -1309,90 +1323,127 @@ Node TermDb::getVtsDelta( bool isFree, bool create ) {
return isFree ? d_vts_delta_free : d_vts_delta;
}
-Node TermDb::getVtsInfinity( bool isFree, bool create ) {
+Node TermDb::getVtsInfinity( TypeNode tn, bool isFree, bool create ) {
if( create ){
- if( d_vts_inf_free.isNull() ){
- d_vts_inf_free = NodeManager::currentNM()->mkSkolem( "inf", NodeManager::currentNM()->integerType(), "free infinity for virtual term substitution" );
+ if( d_vts_inf_free[tn].isNull() ){
+ d_vts_inf_free[tn] = NodeManager::currentNM()->mkSkolem( "inf_free", tn, "free infinity for virtual term substitution" );
}
- if( d_vts_inf.isNull() ){
- d_vts_inf = NodeManager::currentNM()->mkSkolem( "inf", NodeManager::currentNM()->integerType(), "infinity for virtual term substitution" );
+ if( d_vts_inf[tn].isNull() ){
+ d_vts_inf[tn] = NodeManager::currentNM()->mkSkolem( "inf", tn, "infinity for virtual term substitution" );
}
}
- return isFree ? d_vts_inf_free : d_vts_inf;
+ return isFree ? d_vts_inf_free[tn] : d_vts_inf[tn];
+}
+
+Node TermDb::getVtsInfinityIndex( int i, bool isFree, bool create ) {
+ if( i==0 ){
+ return getVtsInfinity( NodeManager::currentNM()->realType(), isFree, create );
+ }else if( i==1 ){
+ return getVtsInfinity( NodeManager::currentNM()->integerType(), isFree, create );
+ }else{
+ Assert( false );
+ return Node::null();
+ }
+}
+
+Node TermDb::substituteVtsFreeTerms( Node n ) {
+ std::vector< Node > vars;
+ getVtsTerms( vars, false, false );
+ std::vector< Node > vars_free;
+ getVtsTerms( vars_free, true, false );
+ Assert( vars.size()==vars_free.size() );
+ if( !vars.empty() ){
+ return n.substitute( vars.begin(), vars.end(), vars_free.begin(), vars_free.end() );
+ }else{
+ return n;
+ }
}
Node TermDb::rewriteVtsSymbols( Node n ) {
if( ( n.getKind()==EQUAL || n.getKind()==GEQ ) ){
Trace("quant-vts-debug") << "VTS : process " << n << std::endl;
- bool rew_inf = false;
+ Node rew_vts_inf;
bool rew_delta = false;
//rewriting infinity always takes precedence over rewriting delta
- if( !d_vts_inf.isNull() && containsTerm( n, d_vts_inf ) ){
- rew_inf = true;
- }else if( !d_vts_delta.isNull() && containsTerm( n, d_vts_delta ) ){
- rew_delta = true;
- }
- if( rew_inf || rew_delta ){
- if( n.getKind()==EQUAL ){
- return d_false;
- }else{
- std::map< Node, Node > msum;
- if( QuantArith::getMonomialSumLit( n, msum ) ){
- if( Trace.isOn("quant-vts-debug") ){
- Trace("quant-vts-debug") << "VTS got monomial sum : " << std::endl;
- QuantArith::debugPrintMonomialSum( msum, "quant-vts-debug" );
+ for( unsigned r=0; r<2; r++ ){
+ Node inf = getVtsInfinityIndex( r, false, false );
+ if( !inf.isNull() && containsTerm( n, inf ) ){
+ if( rew_vts_inf.isNull() ){
+ rew_vts_inf = inf;
+ }else{
+ //for mixed int/real with multiple infinities
+ Trace("quant-vts-debug") << "Multiple infinities...equate " << inf << " = " << rew_vts_inf << std::endl;
+ std::vector< Node > subs_lhs;
+ subs_lhs.push_back( inf );
+ std::vector< Node > subs_rhs;
+ subs_lhs.push_back( rew_vts_inf );
+ n = n.substitute( subs_lhs.begin(), subs_lhs.end(), subs_rhs.begin(), subs_rhs.end() );
+ n = Rewriter::rewrite( n );
+ //may have cancelled
+ if( !containsTerm( n, rew_vts_inf ) ){
+ rew_vts_inf = Node::null();
}
- Node vts_sym = rew_inf ? d_vts_inf : d_vts_delta;
- Assert( !vts_sym.isNull() );
- Node iso_n;
- int res = QuantArith::isolate( vts_sym, msum, iso_n, n.getKind(), true );
- if( res!=0 ){
- Trace("quant-vts-debug") << "VTS isolated : -> " << iso_n << ", res = " << res << std::endl;
- int index = res==1 ? 0 : 1;
- Node slv = iso_n[res==1 ? 1 : 0];
- if( iso_n[index]!=vts_sym ){
- if( iso_n[index].getKind()==MULT && iso_n[index].getNumChildren()==2 && iso_n[index][0].isConst() && iso_n[index][1]==vts_sym ){
- slv = NodeManager::currentNM()->mkNode( MULT, slv, NodeManager::currentNM()->mkConst( Rational(1)/iso_n[index][0].getConst<Rational>() ) );
- }else{
- Trace("quant-vts-debug") << "Failed, return " << n << std::endl;
- return n;
- }
- }
- Node nlit;
- if( res==1 ){
- if( rew_inf ){
- nlit = d_true;
- }else{
- nlit = NodeManager::currentNM()->mkNode( GEQ, d_zero, slv );
- }
+ }
+ }
+ }
+ if( rew_vts_inf.isNull() ){
+ if( !d_vts_delta.isNull() && containsTerm( n, d_vts_delta ) ){
+ rew_delta = true;
+ }
+ }
+ if( !rew_vts_inf.isNull() || rew_delta ){
+ std::map< Node, Node > msum;
+ if( QuantArith::getMonomialSumLit( n, msum ) ){
+ if( Trace.isOn("quant-vts-debug") ){
+ Trace("quant-vts-debug") << "VTS got monomial sum : " << std::endl;
+ QuantArith::debugPrintMonomialSum( msum, "quant-vts-debug" );
+ }
+ Node vts_sym = !rew_vts_inf.isNull() ? rew_vts_inf : d_vts_delta;
+ Assert( !vts_sym.isNull() );
+ Node iso_n;
+ Node nlit;
+ int res = QuantArith::isolate( vts_sym, msum, iso_n, n.getKind(), true );
+ if( res!=0 ){
+ Trace("quant-vts-debug") << "VTS isolated : -> " << iso_n << ", res = " << res << std::endl;
+ Node slv = iso_n[res==1 ? 1 : 0];
+ //ensure the vts terms have been eliminated
+ if( containsVtsTerm( slv ) ){
+ Trace("quant-vts-warn") << "Bad vts literal : " << n << ", contains " << vts_sym << " but bad solved form " << slv << "." << std::endl;
+ nlit = substituteVtsFreeTerms( n );
+ Trace("quant-vts-debug") << "...return " << nlit << std::endl;
+ //Assert( false );
+ //safe case: just convert to free symbols
+ return nlit;
+ }else{
+ if( !rew_vts_inf.isNull() ){
+ nlit = ( n.getKind()==GEQ && res==1 ) ? d_true : d_false;
}else{
- if( rew_inf ){
+ Assert( iso_n[res==1 ? 0 : 1]==d_vts_delta );
+ if( n.getKind()==EQUAL ){
nlit = d_false;
+ }else if( res==1 ){
+ nlit = NodeManager::currentNM()->mkNode( GEQ, d_zero, slv );
}else{
nlit = NodeManager::currentNM()->mkNode( GT, slv, d_zero );
}
}
- Trace("quant-vts-debug") << "Return " << nlit << std::endl;
- return nlit;
}
+ Trace("quant-vts-debug") << "Return " << nlit << std::endl;
+ return nlit;
+ }else{
+ Trace("quant-vts-warn") << "Bad vts literal : " << n << ", contains " << vts_sym << " but could not isolate." << std::endl;
+ //safe case: just convert to free symbols
+ nlit = substituteVtsFreeTerms( n );
+ Trace("quant-vts-debug") << "...return " << nlit << std::endl;
+ //Assert( false );
+ return nlit;
}
}
}
return n;
}else if( n.getKind()==FORALL ){
//cannot traverse beneath quantifiers
- std::vector< Node > vars;
- std::vector< Node > vars_free;
- if( !d_vts_inf.isNull() ){
- vars.push_back( d_vts_inf );
- vars_free.push_back( d_vts_inf_free );
- }
- if( !d_vts_delta.isNull() ){
- vars.push_back( d_vts_delta );
- vars_free.push_back( d_vts_delta_free );
- }
- n = n.substitute( vars.begin(), vars.end(), vars_free.begin(), vars_free.end() );
- return n;
+ return substituteVtsFreeTerms( n );
}else{
bool childChanged = false;
std::vector< Node > children;
@@ -1414,19 +1465,77 @@ Node TermDb::rewriteVtsSymbols( Node n ) {
}
}
-bool TermDb::containsTerm( Node n, Node t ) {
+bool TermDb::containsVtsTerm( Node n, bool isFree ) {
+ std::vector< Node > t;
+ getVtsTerms( t, isFree, false );
+ return containsTerms( n, t );
+}
+
+bool TermDb::containsVtsTerm( std::vector< Node >& n, bool isFree ) {
+ std::vector< Node > t;
+ getVtsTerms( t, isFree, false );
+ if( !t.empty() ){
+ for( unsigned i=0; i<n.size(); i++ ){
+ if( containsTerms( n[i], t ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool TermDb::containsVtsInfinity( Node n, bool isFree ) {
+ std::vector< Node > t;
+ getVtsTerms( t, isFree, false, false );
+ return containsTerms( n, t );
+}
+
+bool TermDb::containsTerm2( Node n, Node t, std::map< Node, bool >& visited ) {
if( n==t ){
return true;
}else{
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( containsTerm( n[i], t ) ){
- return true;
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( containsTerm2( n[i], t, visited ) ){
+ return true;
+ }
}
}
return false;
}
}
+bool TermDb::containsTerms2( Node n, std::vector< Node >& t, std::map< Node, bool >& visited ) {
+ if( std::find( t.begin(), t.end(), n )!=t.end() ){
+ return true;
+ }else{
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ if( containsTerms2( n[i], t, visited ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+
+bool TermDb::containsTerm( Node n, Node t ) {
+ std::map< Node, bool > visited;
+ return containsTerm2( n, t, visited );
+}
+
+bool TermDb::containsTerms( Node n, std::vector< Node >& t ) {
+ if( t.empty() ){
+ return false;
+ }else{
+ std::map< Node, bool > visited;
+ return containsTerms2( n, t, visited );
+ }
+}
+
Node TermDb::simpleNegate( Node n ){
if( n.getKind()==OR || n.getKind()==AND ){
std::vector< Node > children;
@@ -1457,7 +1566,8 @@ void TermDb::registerTrigger( theory::inst::Trigger* tr, Node op ){
bool TermDb::isInductionTerm( Node n ) {
if( options::dtStcInduction() && datatypes::DatatypesRewriter::isTermDatatype( n ) ){
- return true;
+ const Datatype& dt = ((DatatypeType)(n.getType()).toType()).getDatatype();
+ return !dt.isCodatatype();
}
if( options::intWfInduction() && n.getType().isInteger() ){
return true;
diff --git a/src/theory/quantifiers/term_database.h b/src/theory/quantifiers/term_database.h
index 416761ce8..9c5a7cc56 100644
--- a/src/theory/quantifiers/term_database.h
+++ b/src/theory/quantifiers/term_database.h
@@ -348,21 +348,39 @@ public:
//for virtual term substitution
private:
Node d_vts_delta;
- Node d_vts_inf;
+ std::map< TypeNode, Node > d_vts_inf;
Node d_vts_delta_free;
- Node d_vts_inf_free;
+ std::map< TypeNode, Node > d_vts_inf_free;
+ /** get vts infinity index */
+ Node getVtsInfinityIndex( int i, bool isFree = false, bool create = true );
+ /** substitute vts free terms */
+ Node substituteVtsFreeTerms( Node n );
public:
/** get vts delta */
Node getVtsDelta( bool isFree = false, bool create = true );
/** get vts infinity */
- Node getVtsInfinity( bool isFree = false, bool create = true );
+ Node getVtsInfinity( TypeNode tn, bool isFree = false, bool create = true );
+ /** get all vts terms */
+ void getVtsTerms( std::vector< Node >& t, bool isFree = false, bool create = true, bool inc_delta = true );
/** rewrite delta */
Node rewriteVtsSymbols( Node n );
-
+ /** simple check for contains term */
+ bool containsVtsTerm( Node n, bool isFree = false );
+ /** simple check for contains term */
+ bool containsVtsTerm( std::vector< Node >& n, bool isFree = false );
+ /** simple check for contains term */
+ bool containsVtsInfinity( Node n, bool isFree = false );
+
+private:
+ //helper for contains term
+ static bool containsTerm2( Node n, Node t, std::map< Node, bool >& visited );
+ static bool containsTerms2( Node n, std::vector< Node >& t, std::map< Node, bool >& visited );
//general utilities
public:
/** simple check for contains term */
static bool containsTerm( Node n, Node t );
+ /** simple check for contains term */
+ static bool containsTerms( Node n, std::vector< Node >& t );
/** simple negate */
static Node simpleNegate( Node n );
/** is assoc */
diff --git a/src/theory/quantifiers/theory_quantifiers.cpp b/src/theory/quantifiers/theory_quantifiers.cpp
index 649d34922..48891732b 100644
--- a/src/theory/quantifiers/theory_quantifiers.cpp
+++ b/src/theory/quantifiers/theory_quantifiers.cpp
@@ -77,6 +77,9 @@ void TheoryQuantifiers::preRegisterTerm(TNode n) {
void TheoryQuantifiers::presolve() {
Debug("quantifiers-presolve") << "TheoryQuantifiers::presolve()" << endl;
+ if( getQuantifiersEngine() ){
+ getQuantifiersEngine()->presolve();
+ }
}
Node TheoryQuantifiers::getValue(TNode n) {
@@ -169,7 +172,7 @@ Node TheoryQuantifiers::getNextDecisionRequest(){
void TheoryQuantifiers::assertUniversal( Node n ){
Assert( n.getKind()==FORALL );
- if( options::recurseCbqi() || !TermDb::hasInstConstAttr(n) ){
+ if( !options::cbqi() || options::recurseCbqi() || !TermDb::hasInstConstAttr(n) ){
getQuantifiersEngine()->assertQuantifier( n, true );
}
}
diff --git a/src/theory/quantifiers_engine.cpp b/src/theory/quantifiers_engine.cpp
index 13c408d85..1a5be5a57 100644
--- a/src/theory/quantifiers_engine.cpp
+++ b/src/theory/quantifiers_engine.cpp
@@ -252,6 +252,7 @@ Valuation& QuantifiersEngine::getValuation(){
}
void QuantifiersEngine::finishInit(){
+ Trace("quant-engine-debug") << "QuantifiersEngine : finishInit " << std::endl;
for( int i=0; i<(int)d_modules.size(); i++ ){
d_modules[i]->finishInit();
}
@@ -281,6 +282,13 @@ bool QuantifiersEngine::hasOwnership( Node q, QuantifiersModule * m ) {
return mo==m || mo==NULL;
}
+void QuantifiersEngine::presolve() {
+ Trace("quant-engine-debug") << "QuantifiersEngine : presolve " << std::endl;
+ for( unsigned i=0; i<d_modules.size(); i++ ){
+ d_modules[i]->presolve();
+ }
+}
+
void QuantifiersEngine::check( Theory::Effort e ){
CodeTimer codeTimer(d_time);
if( !getMasterEqualityEngine()->consistent() ){
@@ -329,6 +337,10 @@ void QuantifiersEngine::check( Theory::Effort e ){
Trace("quant-engine-ee") << "Equality engine : " << std::endl;
debugPrintEqualityEngine( "quant-engine-ee" );
}
+ if( Trace.isOn("quant-engine-assert") ){
+ Trace("quant-engine-assert") << "Assertions : " << std::endl;
+ getTheoryEngine()->printAssertions("quant-engine-assert");
+ }
//reset relevant information
d_conflict = false;
@@ -616,9 +628,9 @@ bool QuantifiersEngine::addInstantiation( Node f, std::vector< Node >& vars, std
//do virtual term substitution
if( doVts ){
body = Rewriter::rewrite( body );
- Trace("inst-debug") << "Rewrite vts symbols in " << body << std::endl;
+ Trace("quant-vts-debug") << "Rewrite vts symbols in " << body << std::endl;
Node body_r = d_term_db->rewriteVtsSymbols( body );
- Trace("inst-debug") << " ...result: " << body_r << std::endl;
+ Trace("quant-vts-debug") << " ...result: " << body_r << std::endl;
body = body_r;
}
Trace("inst-assert") << "(assert " << body << ")" << std::endl;
@@ -800,15 +812,15 @@ bool QuantifiersEngine::existsInstantiation( Node f, InstMatch& m, bool modEq, b
bool QuantifiersEngine::addLemma( Node lem, bool doCache ){
if( doCache ){
lem = Rewriter::rewrite(lem);
- Trace("inst-add-debug2") << "Adding lemma : " << lem << std::endl;
+ Trace("inst-add-debug") << "Adding lemma : " << lem << std::endl;
if( d_lemmas_produced_c.find( lem )==d_lemmas_produced_c.end() ){
//d_curr_out->lemma( lem, false, true );
d_lemmas_produced_c[ lem ] = true;
d_lemmas_waiting.push_back( lem );
- Trace("inst-add-debug2") << "Added lemma" << std::endl;
+ Trace("inst-add-debug") << "Added lemma" << std::endl;
return true;
}else{
- Trace("inst-add-debug2") << "Duplicate." << std::endl;
+ Trace("inst-add-debug") << "Duplicate." << std::endl;
return false;
}
}else{
diff --git a/src/theory/quantifiers_engine.h b/src/theory/quantifiers_engine.h
index 101aa43cd..2658d09f0 100644
--- a/src/theory/quantifiers_engine.h
+++ b/src/theory/quantifiers_engine.h
@@ -53,6 +53,8 @@ public:
QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
/** initialize */
virtual void finishInit() {}
+ /** presolve */
+ virtual void presolve() {}
/* whether this module needs to check this round */
virtual bool needsCheck( Theory::Effort e ) { return e>=Theory::EFFORT_LAST_CALL; }
/* whether this module needs a model built */
@@ -251,6 +253,8 @@ public:
public:
/** initialize */
void finishInit();
+ /** presolve */
+ void presolve();
/** check at level */
void check( Theory::Effort e );
/** register quantifier */
diff --git a/src/theory/strings/theory_strings_rewriter.cpp b/src/theory/strings/theory_strings_rewriter.cpp
index 7023f7c41..872933cbd 100644
--- a/src/theory/strings/theory_strings_rewriter.cpp
+++ b/src/theory/strings/theory_strings_rewriter.cpp
@@ -948,8 +948,9 @@ RewriteResponse TheoryStringsRewriter::postRewrite(TNode node) {
bool flag = false;
unsigned n1 = node[0].getNumChildren();
unsigned n2 = node[1].getNumChildren();
- if(n1 - n2) {
- for(unsigned i=0; i<=n1 - n2; i++) {
+ if( n1>n2 ){
+ unsigned diff = n1-n2;
+ for(unsigned i=0; i<diff; i++) {
if(node[0][i] == node[1][0]) {
flag = true;
for(unsigned j=1; j<n2; j++) {
diff --git a/src/theory/theory_engine.h b/src/theory/theory_engine.h
index 0c1a7c081..b28a73b9d 100644
--- a/src/theory/theory_engine.h
+++ b/src/theory/theory_engine.h
@@ -798,9 +798,6 @@ private:
/** Visitor for collecting shared terms */
SharedTermsVisitor d_sharedTermsVisitor;
- /** Prints the assertions to the debug stream */
- void printAssertions(const char* tag);
-
/** Dump the assertions to the dump */
void dumpAssertions(const char* tag);
@@ -830,8 +827,14 @@ public:
SharedTermsDatabase* getSharedTermsDatabase() { return &d_sharedTerms; }
theory::eq::EqualityEngine* getMasterEqualityEngine() { return d_masterEqualityEngine; }
+
+ RemoveITE* getIteRemover() { return &d_iteRemover; }
SortInference* getSortInference() { return &d_sortInfer; }
+
+ /** Prints the assertions to the debug stream */
+ void printAssertions(const char* tag);
+
private:
std::map< std::string, std::vector< theory::Theory* > > d_attr_handle;
public:
diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp
index c15074d8c..d913cb76a 100644
--- a/src/theory/uf/theory_uf_strong_solver.cpp
+++ b/src/theory/uf/theory_uf_strong_solver.cpp
@@ -1047,6 +1047,7 @@ void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){
//add splitting lemma for cardinality constraint
Assert( !d_cardinality_term.isNull() );
Node lem = getCardinalityLiteral( d_aloc_cardinality );
+ Trace("uf-ss-lemma") << "*** Cardinality split on : " << lem << std::endl;
lem = NodeManager::currentNM()->mkNode( OR, lem, lem.notNode() );
d_cardinality_lemma[ d_aloc_cardinality ] = lem;
//add as lemma to output channel
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback