int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){ if( e<5 ){ return STATUS_UNFINISHED; }else{ //first, try from relevant domain RelevantDomain * rd = d_quantEngine->getRelevantDomain(); for( unsigned r=0; r<2; r++ ){ if( rd || r==1 ){ if( r==0 ){ Trace("inst-alg") << "-> Relevant domain instantiate " << f << "..." << std::endl; }else{ Trace("inst-alg") << "-> Guess instantiate " << f << "..." << std::endl; } rd->compute(); unsigned final_max_i = 0; std::vector< unsigned > maxs; for(unsigned i=0; i<f[0].getNumChildren(); i++ ){ unsigned ts; if( r==0 ){ ts = rd->getRDomain( f, i )->d_terms.size(); }else{ ts = d_quantEngine->getTermDatabase()->d_type_map[f[0][i].getType()].size(); } maxs.push_back( ts ); Trace("inst-alg-rd") << "Variable " << i << " has " << ts << " in relevant domain." << std::endl; if( ts>final_max_i ){ final_max_i = ts; } } Trace("inst-alg-rd") << "Will do " << final_max_i << " stages of instantiation." << std::endl; unsigned max_i = 0; bool success; while( max_i<=final_max_i ){ Trace("inst-alg-rd") << "Try stage " << max_i << "..." << std::endl; std::vector< unsigned > childIndex; int index = 0; do { while( index>=0 && index<(int)f[0].getNumChildren() ){ if( index==(int)childIndex.size() ){ childIndex.push_back( -1 ); }else{ Assert( index==(int)(childIndex.size())-1 ); unsigned nv = childIndex[index]+1; if( options::cbqi() ){ //skip inst constant nodes while( nv<maxs[index] && nv<=max_i && r==1 && quantifiers::TermDb::hasInstConstAttr( d_quantEngine->getTermDatabase()->d_type_map[f[0][index].getType()][nv] ) ){ childIndex[index]++; nv = childIndex[index]+1; } } if( nv<maxs[index] && nv<=max_i ){ childIndex[index]++; index++; }else{ childIndex.pop_back(); index--; } } } success = index>=0; if( success ){ Trace("inst-alg-rd") << "Try instantiation..." << std::endl; index--; //try instantiation std::vector< Node > terms; for( unsigned i=0; i<f[0].getNumChildren(); i++ ){ if( r==0 ){ terms.push_back( rd->getRDomain( f, i )->d_terms[childIndex[i]] ); }else{ terms.push_back( d_quantEngine->getTermDatabase()->d_type_map[f[0][i].getType()][childIndex[i]] ); } } if( d_quantEngine->addInstantiation( f, terms, false ) ){ Trace("inst-alg-rd") << "Success!" << std::endl; ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_guess); return STATUS_UNKNOWN; } } }while( success ); max_i++; } } if( r==0 ){ if( d_guessed.find( f )==d_guessed.end() ){ Trace("inst-alg") << "-> Guess instantiate " << f << "..." << std::endl; d_guessed[f] = true; InstMatch m( f ); if( d_quantEngine->addInstantiation( f, m ) ){ ++(d_quantEngine->getInstantiationEngine()->d_statistics.d_instantiations_guess); return STATUS_UNKNOWN; } } } } return STATUS_UNKNOWN; } }
void InstStrategyEnum::check(Theory::Effort e, QEffort quant_e) { bool doCheck = false; bool fullEffort = false; if (options::fullSaturateInterleave()) { // we only add when interleaved with other strategies doCheck = quant_e == QEFFORT_STANDARD && d_quantEngine->hasAddedLemma(); } if (options::fullSaturateQuant() && !doCheck) { doCheck = quant_e == QEFFORT_LAST_CALL; fullEffort = !d_quantEngine->hasAddedLemma(); } if (!doCheck) { return; } double clSet = 0; if (Trace.isOn("fs-engine")) { clSet = double(clock()) / double(CLOCKS_PER_SEC); Trace("fs-engine") << "---Full Saturation Round, effort = " << e << "---" << std::endl; } unsigned rstart = options::fullSaturateQuantRd() ? 0 : 1; unsigned rend = fullEffort ? 1 : rstart; unsigned addedLemmas = 0; // First try in relevant domain of all quantified formulas, if no // instantiations exist, try arbitrary ground terms. // Notice that this stratification of effort levels makes it so that some // quantified formulas may not be instantiated (if they have no instances // at effort level r=0 but another quantified formula does). We prefer // this stratification since effort level r=1 may be highly expensive in the // case where we have a quantified formula with many entailed instances. FirstOrderModel* fm = d_quantEngine->getModel(); RelevantDomain* rd = d_quantEngine->getRelevantDomain(); unsigned nquant = fm->getNumAssertedQuantifiers(); std::map<Node, bool> alreadyProc; for (unsigned r = rstart; r <= rend; r++) { if (rd || r > 0) { if (r == 0) { Trace("inst-alg") << "-> Relevant domain instantiate..." << std::endl; Trace("inst-alg-debug") << "Compute relevant domain..." << std::endl; rd->compute(); Trace("inst-alg-debug") << "...finished" << std::endl; } else { Trace("inst-alg") << "-> Ground term instantiate..." << std::endl; } for (unsigned i = 0; i < nquant; i++) { Node q = fm->getAssertedQuantifier(i, true); bool doProcess = d_quantEngine->hasOwnership(q, this) && fm->isQuantifierActive(q) && alreadyProc.find(q) == alreadyProc.end(); if (doProcess) { if (process(q, fullEffort, r == 0)) { // don't need to mark this if we are not stratifying if (!options::fullSaturateStratify()) { alreadyProc[q] = true; } // added lemma addedLemmas++; if (d_quantEngine->inConflict()) { break; } } } } if (d_quantEngine->inConflict() || (addedLemmas > 0 && options::fullSaturateStratify())) { // we break if we are in conflict, or if we added any lemma at this // effort level and we stratify effort levels. break; } } } if (Trace.isOn("fs-engine")) { Trace("fs-engine") << "Added lemmas = " << addedLemmas << std::endl; double clSet2 = double(clock()) / double(CLOCKS_PER_SEC); Trace("fs-engine") << "Finished full saturation engine, time = " << (clSet2 - clSet) << std::endl; } }
bool FullSaturation::process( Node f, bool fullEffort ){ //first, try from relevant domain RelevantDomain * rd = d_quantEngine->getRelevantDomain(); unsigned rstart = options::fullSaturateQuantRd() ? 0 : 1; unsigned rend = fullEffort ? 1 : rstart; for( unsigned r=rstart; r<=rend; r++ ){ if( rd || r>0 ){ if( r==0 ){ Trace("inst-alg") << "-> Relevant domain instantiate " << f << "..." << std::endl; }else{ Trace("inst-alg") << "-> Ground term instantiate " << f << "..." << std::endl; } rd->compute(); unsigned final_max_i = 0; std::vector< unsigned > maxs; std::vector< bool > max_zero; bool has_zero = false; for(unsigned i=0; i<f[0].getNumChildren(); i++ ){ unsigned ts; if( r==0 ){ ts = rd->getRDomain( f, i )->d_terms.size(); }else{ ts = d_quantEngine->getTermDatabase()->getNumTypeGroundTerms( f[0][i].getType() ); } max_zero.push_back( fullEffort && ts==0 ); ts = ( fullEffort && ts==0 ) ? 1 : ts; Trace("inst-alg-rd") << "Variable " << i << " has " << ts << " in relevant domain." << std::endl; if( ts==0 ){ has_zero = true; break; }else{ maxs.push_back( ts ); if( ts>final_max_i ){ final_max_i = ts; } } } if( !has_zero ){ std::vector< TypeNode > ftypes; for( unsigned i=0; i<f[0].getNumChildren(); i++ ){ ftypes.push_back( f[0][i].getType() ); } Trace("inst-alg-rd") << "Will do " << final_max_i << " stages of instantiation." << std::endl; unsigned max_i = 0; bool success; while( max_i<=final_max_i ){ Trace("inst-alg-rd") << "Try stage " << max_i << "..." << std::endl; std::vector< unsigned > childIndex; int index = 0; do { while( index>=0 && index<(int)f[0].getNumChildren() ){ if( index==(int)childIndex.size() ){ childIndex.push_back( -1 ); }else{ Assert( index==(int)(childIndex.size())-1 ); unsigned nv = childIndex[index]+1; if( options::cbqi() && r==1 && !max_zero[index] ){ //skip inst constant nodes while( nv<maxs[index] && nv<=max_i && quantifiers::TermDb::hasInstConstAttr( d_quantEngine->getTermDatabase()->getTypeGroundTerm( ftypes[index], nv ) ) ){ nv++; } } if( nv<maxs[index] && nv<=max_i ){ childIndex[index] = nv; index++; }else{ childIndex.pop_back(); index--; } } } success = index>=0; if( success ){ Trace("inst-alg-rd") << "Try instantiation { "; for( unsigned j=0; j<childIndex.size(); j++ ){ Trace("inst-alg-rd") << childIndex[j] << " "; } Trace("inst-alg-rd") << "}" << std::endl; //try instantiation std::vector< Node > terms; for( unsigned i=0; i<f[0].getNumChildren(); i++ ){ if( max_zero[i] ){ //no terms available, will report incomplete instantiation terms.push_back( Node::null() ); Trace("inst-alg-rd") << " null" << std::endl; }else if( r==0 ){ terms.push_back( rd->getRDomain( f, i )->d_terms[childIndex[i]] ); Trace("inst-alg-rd") << " " << rd->getRDomain( f, i )->d_terms[childIndex[i]] << std::endl; }else{ terms.push_back( d_quantEngine->getTermDatabase()->getTypeGroundTerm( ftypes[i], childIndex[i] ) ); Trace("inst-alg-rd") << " " << d_quantEngine->getTermDatabase()->getTypeGroundTerm( ftypes[i], childIndex[i] ) << std::endl; } } if( d_quantEngine->addInstantiation( f, terms ) ){ Trace("inst-alg-rd") << "Success!" << std::endl; ++(d_quantEngine->d_statistics.d_instantiations_guess); return true; }else{ index--; } } }while( success ); max_i++; } } } } //term enumerator? return false; }
bool InstStrategyEnum::process(Node f, bool fullEffort, bool isRd) { // ignore if constant true (rare case of non-standard quantifier whose body is // rewritten to true) if (f[1].isConst() && f[1].getConst<bool>()) { return false; } RelevantDomain* rd = d_quantEngine->getRelevantDomain(); unsigned final_max_i = 0; std::vector<unsigned> maxs; std::vector<bool> max_zero; bool has_zero = false; std::map<TypeNode, std::vector<Node> > term_db_list; std::vector<TypeNode> ftypes; TermDb* tdb = d_quantEngine->getTermDatabase(); EqualityQuery* qy = d_quantEngine->getEqualityQuery(); // iterate over substitutions for variables for (unsigned i = 0; i < f[0].getNumChildren(); i++) { TypeNode tn = f[0][i].getType(); ftypes.push_back(tn); unsigned ts; if (isRd) { ts = rd->getRDomain(f, i)->d_terms.size(); } else { ts = tdb->getNumTypeGroundTerms(tn); std::map<TypeNode, std::vector<Node> >::iterator ittd = term_db_list.find(tn); if (ittd == term_db_list.end()) { std::map<Node, Node> reps_found; for (unsigned j = 0; j < ts; j++) { Node gt = tdb->getTypeGroundTerm(ftypes[i], j); if (!options::cbqi() || !quantifiers::TermUtil::hasInstConstAttr(gt)) { Node rep = qy->getRepresentative(gt); if (reps_found.find(rep) == reps_found.end()) { reps_found[rep] = gt; term_db_list[tn].push_back(gt); } } } ts = term_db_list[tn].size(); } else { ts = ittd->second.size(); } } // consider a default value if at full effort max_zero.push_back(fullEffort && ts == 0); ts = (fullEffort && ts == 0) ? 1 : ts; Trace("inst-alg-rd") << "Variable " << i << " has " << ts << " in relevant domain." << std::endl; if (ts == 0) { has_zero = true; break; } maxs.push_back(ts); if (ts > final_max_i) { final_max_i = ts; } } if (!has_zero) { Trace("inst-alg-rd") << "Will do " << final_max_i << " stages of instantiation." << std::endl; unsigned max_i = 0; bool success; Instantiate* ie = d_quantEngine->getInstantiate(); while (max_i <= final_max_i) { Trace("inst-alg-rd") << "Try stage " << max_i << "..." << std::endl; std::vector<unsigned> childIndex; int index = 0; do { while (index >= 0 && index < (int)f[0].getNumChildren()) { if (index == static_cast<int>(childIndex.size())) { childIndex.push_back(-1); } else { Assert(index == static_cast<int>(childIndex.size()) - 1); unsigned nv = childIndex[index] + 1; if (nv < maxs[index] && nv <= max_i) { childIndex[index] = nv; index++; } else { childIndex.pop_back(); index--; } } } success = index >= 0; if (success) { if (Trace.isOn("inst-alg-rd")) { Trace("inst-alg-rd") << "Try instantiation { "; for (unsigned i : childIndex) { Trace("inst-alg-rd") << i << " "; } Trace("inst-alg-rd") << "}" << std::endl; } // try instantiation std::vector<Node> terms; for (unsigned i = 0, nchild = f[0].getNumChildren(); i < nchild; i++) { if (max_zero[i]) { // no terms available, will report incomplete instantiation terms.push_back(Node::null()); Trace("inst-alg-rd") << " null" << std::endl; } else if (isRd) { terms.push_back(rd->getRDomain(f, i)->d_terms[childIndex[i]]); Trace("inst-alg-rd") << " " << rd->getRDomain(f, i)->d_terms[childIndex[i]] << std::endl; } else { Assert(childIndex[i] < term_db_list[ftypes[i]].size()); terms.push_back(term_db_list[ftypes[i]][childIndex[i]]); Trace("inst-alg-rd") << " " << term_db_list[ftypes[i]][childIndex[i]] << std::endl; } } if (ie->addInstantiation(f, terms)) { Trace("inst-alg-rd") << "Success!" << std::endl; ++(d_quantEngine->d_statistics.d_instantiations_guess); return true; } else { index--; } } } while (success); max_i++; } } // TODO : term enumerator instantiation? return false; }