--- /dev/null
+/********************* */\r
+/*! \file subgoal_generator.cpp\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief conjecture generator class\r
+ **\r
+ **/\r
+\r
+#include "theory/quantifiers/conjecture_generator.h"\r
+#include "theory/theory_engine.h"\r
+#include "theory/quantifiers/options.h"\r
+#include "theory/quantifiers/term_database.h"\r
+#include "theory/quantifiers/trigger.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+using namespace std;\r
+\r
+\r
+namespace CVC4 {\r
+\r
+void OpArgIndex::addTerm( ConjectureGenerator * s, TNode n, unsigned index ){\r
+ if( index==n.getNumChildren() ){\r
+ Assert( n.hasOperator() );\r
+ if( std::find( d_ops.begin(), d_ops.end(), n.getOperator() )==d_ops.end() ){\r
+ d_ops.push_back( n.getOperator() );\r
+ d_op_terms.push_back( n );\r
+ }\r
+ }else{\r
+ d_child[s->getTermDatabase()->d_arg_reps[n][index]].addTerm( s, n, index+1 );\r
+ }\r
+}\r
+\r
+Node OpArgIndex::getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args ) {\r
+ if( d_ops.empty() ){\r
+ for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){\r
+ std::map< TNode, Node >::iterator itf = s->d_ground_eqc_map.find( it->first );\r
+ if( itf!=s->d_ground_eqc_map.end() ){\r
+ args.push_back( itf->second );\r
+ Node n = it->second.getGroundTerm( s, args );\r
+ args.pop_back();\r
+ if( !n.isNull() ){\r
+ return n;\r
+ }\r
+ }\r
+ }\r
+ return Node::null();\r
+ }else{\r
+ std::vector< TNode > args2;\r
+ args2.push_back( d_ops[0] );\r
+ args2.insert( args2.end(), args.begin(), args.end() );\r
+ return NodeManager::currentNM()->mkNode( d_op_terms[0].getKind(), args2 );\r
+ }\r
+}\r
+\r
+void OpArgIndex::getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms ) {\r
+ terms.insert( terms.end(), d_op_terms.begin(), d_op_terms.end() );\r
+ for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){\r
+ if( s->isGroundEqc( it->first ) ){\r
+ it->second.getGroundTerms( s, terms );\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
+ConjectureGenerator::ConjectureGenerator( QuantifiersEngine * qe, context::Context* c ) : QuantifiersModule( qe ),\r
+d_notify( *this ),\r
+d_uequalityEngine(d_notify, c, "ConjectureGenerator::ee"),\r
+d_ee_conjectures( c ){\r
+ d_fullEffortCount = 0;\r
+ d_uequalityEngine.addFunctionKind( kind::APPLY_UF );\r
+ d_uequalityEngine.addFunctionKind( kind::APPLY_CONSTRUCTOR );\r
+ \r
+}\r
+\r
+void ConjectureGenerator::eqNotifyNewClass( TNode t ){\r
+ Trace("thm-ee-debug") << "UEE : new equivalence class " << t << std::endl;\r
+ d_upendingAdds.push_back( t );\r
+}\r
+\r
+void ConjectureGenerator::eqNotifyPreMerge(TNode t1, TNode t2) {\r
+ //get maintained representatives\r
+ TNode rt1 = t1;\r
+ TNode rt2 = t2;\r
+ std::map< Node, EqcInfo* >::iterator it1 = d_eqc_info.find( t1 );\r
+ if( it1!=d_eqc_info.end() && !it1->second->d_rep.get().isNull() ){\r
+ rt1 = it1->second->d_rep.get();\r
+ }\r
+ std::map< Node, EqcInfo* >::iterator it2 = d_eqc_info.find( t2 );\r
+ if( it2!=d_eqc_info.end() && !it2->second->d_rep.get().isNull() ){\r
+ rt2 = it2->second->d_rep.get();\r
+ }\r
+ Trace("thm-ee-debug") << "UEE : equality holds : " << t1 << " == " << t2 << std::endl;\r
+ Trace("thm-ee-debug") << " ureps : " << rt1 << " == " << rt2 << std::endl;\r
+ Trace("thm-ee-debug") << " normal : " << d_pattern_is_normal[rt1] << " " << d_pattern_is_normal[rt2] << std::endl;\r
+ Trace("thm-ee-debug") << " size : " << d_pattern_fun_sum[rt1] << " " << d_pattern_fun_sum[rt2] << std::endl;\r
+\r
+ if( isUniversalLessThan( rt2, rt1 ) ){\r
+ EqcInfo * ei;\r
+ if( it1==d_eqc_info.end() ){\r
+ ei = getOrMakeEqcInfo( t1, true );\r
+ }else{\r
+ ei = it1->second;\r
+ }\r
+ ei->d_rep = t2;\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::eqNotifyPostMerge(TNode t1, TNode t2) {\r
+\r
+}\r
+\r
+void ConjectureGenerator::eqNotifyDisequal(TNode t1, TNode t2, TNode reason) {\r
+ Trace("thm-ee-debug") << "UEE : disequality holds : " << t1 << " != " << t2 << std::endl;\r
+\r
+}\r
+\r
+\r
+ConjectureGenerator::EqcInfo::EqcInfo( context::Context* c ) : d_rep( c, Node::null() ){\r
+\r
+}\r
+\r
+ConjectureGenerator::EqcInfo* ConjectureGenerator::getOrMakeEqcInfo( TNode n, bool doMake ) {\r
+ //Assert( getUniversalRepresentative( n )==n );\r
+ std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );\r
+ if( eqc_i!=d_eqc_info.end() ){\r
+ return eqc_i->second;\r
+ }else if( doMake ){\r
+ EqcInfo* ei = new EqcInfo( d_quantEngine->getSatContext() );\r
+ d_eqc_info[n] = ei;\r
+ return ei;\r
+ }else{\r
+ return NULL;\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::doPendingAddUniversalTerms() {\r
+ //merge all pending equalities\r
+ while( !d_upendingAdds.empty() ){\r
+ Trace("sg-pending") << "Add " << d_upendingAdds.size() << " pending terms..." << std::endl;\r
+ std::vector< Node > pending;\r
+ pending.insert( pending.end(), d_upendingAdds.begin(), d_upendingAdds.end() );\r
+ d_upendingAdds.clear();\r
+ for( unsigned i=0; i<pending.size(); i++ ){\r
+ Node t = pending[i];\r
+ TypeNode tn = t.getType();\r
+ Trace("thm-ee-add") << "UEE : Add universal term " << t << std::endl;\r
+ //get all equivalent terms from conjecture database\r
+ std::vector< Node > eq_terms;\r
+ d_thm_index.getEquivalentTerms( t, eq_terms );\r
+ if( !eq_terms.empty() ){\r
+ Trace("thm-ee-add") << "UEE : Based on theorem database, it is equivalent to " << eq_terms.size() << " terms : " << std::endl;\r
+ //add equivalent terms as equalities to universal engine\r
+ for( unsigned i=0; i<eq_terms.size(); i++ ){\r
+ Trace("thm-ee-add") << " " << eq_terms[i] << std::endl;\r
+ //if( d_urelevant_terms.find( eq_terms[i] )!=d_urelevant_terms.end() ){\r
+ bool assertEq = false;\r
+ if( d_urelevant_terms.find( eq_terms[i] )!=d_urelevant_terms.end() ){\r
+ assertEq = true;\r
+ }else{\r
+ Assert( eq_terms[i].getType()==tn );\r
+ registerPattern( eq_terms[i], tn );\r
+ if( isUniversalLessThan( eq_terms[i], t ) ){\r
+ setUniversalRelevant( eq_terms[i] );\r
+ assertEq = true;\r
+ }\r
+ }\r
+ if( assertEq ){\r
+ Node exp;\r
+ d_uequalityEngine.assertEquality( t.eqNode( eq_terms[i] ), true, exp );\r
+ }\r
+ }\r
+ }else{\r
+ Trace("thm-ee-add") << "UEE : No equivalent terms." << std::endl;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::setUniversalRelevant( TNode n ) {\r
+ //add pattern information\r
+ registerPattern( n, n.getType() );\r
+ d_urelevant_terms[n] = true;\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ setUniversalRelevant( n[i] );\r
+ }\r
+}\r
+\r
+bool ConjectureGenerator::isUniversalLessThan( TNode rt1, TNode rt2 ) {\r
+ //prefer the one that is (normal, smaller) lexographically\r
+ Assert( d_pattern_is_normal.find( rt1 )!=d_pattern_is_normal.end() );\r
+ Assert( d_pattern_is_normal.find( rt2 )!=d_pattern_is_normal.end() );\r
+ Assert( d_pattern_fun_sum.find( rt1 )!=d_pattern_fun_sum.end() );\r
+ Assert( d_pattern_fun_sum.find( rt2 )!=d_pattern_fun_sum.end() );\r
+ \r
+ if( d_pattern_is_normal[rt1] && !d_pattern_is_normal[rt2] ){\r
+ Trace("thm-ee-debug") << "UEE : LT due to normal." << std::endl;\r
+ return true;\r
+ }else if( d_pattern_is_normal[rt1]==d_pattern_is_normal[rt2] ){\r
+ if( d_pattern_fun_sum[rt1]<d_pattern_fun_sum[rt2] ){\r
+ Trace("thm-ee-debug") << "UEE : LT due to size." << std::endl;\r
+ //decide which representative to use : based on size of the term\r
+ return true;\r
+ }else if( d_pattern_fun_sum[rt1]==d_pattern_fun_sum[rt2] ){\r
+ //same size : tie goes to term that has already been reported\r
+ return isReportedCanon( rt1 ) && !isReportedCanon( rt2 );\r
+ }\r
+ }\r
+ return false;\r
+}\r
+\r
+\r
+bool ConjectureGenerator::isReportedCanon( TNode n ) { \r
+ return std::find( d_ue_canon.begin(), d_ue_canon.end(), n )==d_ue_canon.end(); \r
+}\r
+\r
+void ConjectureGenerator::markReportedCanon( TNode n ) {\r
+ if( !isReportedCanon( n ) ){\r
+ d_ue_canon.push_back( n );\r
+ }\r
+}\r
+\r
+bool ConjectureGenerator::areUniversalEqual( TNode n1, TNode n2 ) {\r
+ return n1==n2 || ( d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areEqual( n1, n2 ) );\r
+}\r
+\r
+bool ConjectureGenerator::areUniversalDisequal( TNode n1, TNode n2 ) {\r
+ return n1!=n2 && d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areDisequal( n1, n2, false );\r
+}\r
+\r
+TNode ConjectureGenerator::getUniversalRepresentative( TNode n, bool add ) {\r
+ if( add ){\r
+ if( d_urelevant_terms.find( n )==d_urelevant_terms.end() ){\r
+ setUniversalRelevant( n );\r
+ //add term to universal equality engine\r
+ d_uequalityEngine.addTerm( n );\r
+ Trace("thm-ee-debug") << "Merge equivalence classes based on terms..." << std::endl;\r
+ doPendingAddUniversalTerms();\r
+ }\r
+ }\r
+ if( d_uequalityEngine.hasTerm( n ) ){\r
+ Node r = d_uequalityEngine.getRepresentative( n );\r
+ EqcInfo * ei = getOrMakeEqcInfo( r );\r
+ if( ei && !ei->d_rep.get().isNull() ){\r
+ return ei->d_rep.get();\r
+ }else{\r
+ return r;\r
+ }\r
+ }else{\r
+ return n;\r
+ }\r
+}\r
+\r
+eq::EqualityEngine * ConjectureGenerator::getEqualityEngine() {\r
+ return d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();\r
+}\r
+\r
+bool ConjectureGenerator::areEqual( TNode n1, TNode n2 ) {\r
+ eq::EqualityEngine * ee = getEqualityEngine();\r
+ return n1==n2 || ( ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areEqual( n1, n2 ) );\r
+}\r
+\r
+bool ConjectureGenerator::areDisequal( TNode n1, TNode n2 ) {\r
+ eq::EqualityEngine * ee = getEqualityEngine();\r
+ return n1!=n2 && ee->hasTerm( n1 ) && ee->hasTerm( n2 ) && ee->areDisequal( n1, n2, false );\r
+}\r
+\r
+TNode ConjectureGenerator::getRepresentative( TNode n ) {\r
+ eq::EqualityEngine * ee = getEqualityEngine();\r
+ if( ee->hasTerm( n ) ){\r
+ return ee->getRepresentative( n );\r
+ }else{\r
+ return n;\r
+ }\r
+}\r
+\r
+TermDb * ConjectureGenerator::getTermDatabase() {\r
+ return d_quantEngine->getTermDatabase();\r
+}\r
+\r
+bool ConjectureGenerator::needsCheck( Theory::Effort e ) {\r
+ if( e==Theory::EFFORT_FULL ){\r
+ //d_fullEffortCount++;\r
+ return d_fullEffortCount%optFullCheckFrequency()==0;\r
+ }else{\r
+ return false;\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::reset_round( Theory::Effort e ) {\r
+\r
+}\r
+\r
+Node ConjectureGenerator::getFreeVar( TypeNode tn, unsigned i ) {\r
+ Assert( !tn.isNull() );\r
+ while( d_free_var[tn].size()<=i ){\r
+ std::stringstream oss;\r
+ oss << tn;\r
+ std::stringstream os;\r
+ os << oss.str()[0] << i;\r
+ Node x = NodeManager::currentNM()->mkBoundVar( os.str().c_str(), tn );\r
+ d_free_var_num[x] = d_free_var[tn].size();\r
+ d_free_var[tn].push_back( x );\r
+ }\r
+ return d_free_var[tn][i];\r
+}\r
+\r
+\r
+\r
+Node ConjectureGenerator::getCanonicalTerm( TNode n, std::map< TypeNode, unsigned >& var_count, std::map< TNode, TNode >& subs ) {\r
+ Trace("ajr-temp") << "get canonical term " << n << " " << n.getKind() << " " << n.hasOperator() << std::endl;\r
+ if( n.getKind()==BOUND_VARIABLE ){\r
+ std::map< TNode, TNode >::iterator it = subs.find( n );\r
+ if( it==subs.end() ){\r
+ TypeNode tn = n.getType();\r
+ //allocate variable\r
+ unsigned vn = var_count[tn];\r
+ var_count[tn]++;\r
+ subs[n] = getFreeVar( tn, vn );\r
+ return subs[n];\r
+ }else{\r
+ return it->second;\r
+ }\r
+ }else{\r
+ std::vector< Node > children;\r
+ if( n.getKind()!=EQUAL ){\r
+ if( n.hasOperator() ){\r
+ TNode op = n.getOperator();\r
+ if( std::find( d_funcs.begin(), d_funcs.end(), op )==d_funcs.end() ){\r
+ return Node::null();\r
+ }\r
+ children.push_back( op );\r
+ }else{\r
+ return Node::null();\r
+ }\r
+ }\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ Node cn = getCanonicalTerm( n[i], var_count, subs );\r
+ if( cn.isNull() ){\r
+ return Node::null();\r
+ }else{\r
+ children.push_back( cn );\r
+ }\r
+ }\r
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
+ }\r
+}\r
+\r
+bool ConjectureGenerator::isHandledTerm( TNode n ){\r
+ return !n.getAttribute(NoMatchAttribute()) && inst::Trigger::isAtomicTrigger( n ) && ( n.getKind()!=APPLY_UF || n.getOperator().getKind()!=SKOLEM );\r
+}\r
+\r
+Node ConjectureGenerator::getGroundEqc( TNode r ) {\r
+ std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );\r
+ return it!=d_ground_eqc_map.end() ? it->second : Node::null();\r
+}\r
+\r
+bool ConjectureGenerator::isGroundEqc( TNode r ) {\r
+ return d_ground_eqc_map.find( r )!=d_ground_eqc_map.end();\r
+}\r
+\r
+bool ConjectureGenerator::isGroundTerm( TNode n ) {\r
+ return std::find( d_ground_terms.begin(), d_ground_terms.end(), n )!=d_ground_terms.end();\r
+}\r
+\r
+void ConjectureGenerator::check( Theory::Effort e ) {\r
+ if( e==Theory::EFFORT_FULL ){\r
+ bool doCheck = d_fullEffortCount%optFullCheckFrequency()==0;\r
+ if( d_quantEngine->hasAddedLemma() ){\r
+ doCheck = false;\r
+ }else{\r
+ d_fullEffortCount++;\r
+ }\r
+ if( doCheck ){\r
+ Trace("sg-engine") << "---Subgoal engine, effort = " << e << "--- " << std::endl;\r
+ eq::EqualityEngine * ee = getEqualityEngine();\r
+\r
+ Trace("sg-proc") << "Get eq classes..." << std::endl;\r
+ d_op_arg_index.clear();\r
+ d_ground_eqc_map.clear();\r
+ d_bool_eqc[0] = Node::null();\r
+ d_bool_eqc[1] = Node::null();\r
+ std::vector< TNode > eqcs;\r
+ d_em.clear();\r
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );\r
+ while( !eqcs_i.isFinished() ){\r
+ TNode r = (*eqcs_i);\r
+ eqcs.push_back( r );\r
+ if( r.getType().isBoolean() ){\r
+ if( areEqual( r, getTermDatabase()->d_true ) ){\r
+ d_ground_eqc_map[r] = getTermDatabase()->d_true;\r
+ d_bool_eqc[0] = r;\r
+ }else if( areEqual( r, getTermDatabase()->d_false ) ){\r
+ d_ground_eqc_map[r] = getTermDatabase()->d_false;\r
+ d_bool_eqc[1] = r;\r
+ }\r
+ }\r
+ d_em[r] = eqcs.size();\r
+ eq::EqClassIterator ieqc_i = eq::EqClassIterator( r, ee );\r
+ while( !ieqc_i.isFinished() ){\r
+ TNode n = (*ieqc_i);\r
+ if( isHandledTerm( n ) ){\r
+ d_op_arg_index[r].addTerm( this, n );\r
+ }\r
+ ++ieqc_i;\r
+ }\r
+ ++eqcs_i;\r
+ }\r
+ Assert( !d_bool_eqc[0].isNull() );\r
+ Assert( !d_bool_eqc[1].isNull() );\r
+ d_urelevant_terms.clear();\r
+ Trace("sg-proc") << "...done get eq classes" << std::endl;\r
+\r
+ Trace("sg-proc") << "Determine ground EQC..." << std::endl;\r
+ bool success;\r
+ do{\r
+ success = false;\r
+ for( unsigned i=0; i<eqcs.size(); i++ ){\r
+ TNode r = eqcs[i];\r
+ if( d_ground_eqc_map.find( r )==d_ground_eqc_map.end() ){\r
+ std::vector< TNode > args;\r
+ Trace("sg-pat-debug") << "******* Get ground term for " << r << std::endl;\r
+ Node n;\r
+ if( getTermDatabase()->isInductionTerm( r ) ){\r
+ n = d_op_arg_index[r].getGroundTerm( this, args );\r
+ }else{\r
+ n = r;\r
+ }\r
+ if( !n.isNull() ){\r
+ Trace("sg-pat") << "Ground term for eqc " << r << " : " << std::endl;\r
+ Trace("sg-pat") << " " << n << std::endl;\r
+ d_ground_eqc_map[r] = n;\r
+ success = true;\r
+ }else{\r
+ Trace("sg-pat-debug") << "...could not find ground term." << std::endl;\r
+ }\r
+ }\r
+ }\r
+ }while( success );\r
+ //also get ground terms\r
+ d_ground_terms.clear();\r
+ for( unsigned i=0; i<eqcs.size(); i++ ){\r
+ TNode r = eqcs[i];\r
+ d_op_arg_index[r].getGroundTerms( this, d_ground_terms );\r
+ }\r
+ Trace("sg-proc") << "...done determine ground EQC" << std::endl;\r
+\r
+ //debug printing\r
+ if( Trace.isOn("sg-gen-eqc") ){\r
+ for( unsigned i=0; i<eqcs.size(); i++ ){\r
+ TNode r = eqcs[i];\r
+ //print out members\r
+ bool firstTime = true;\r
+ bool isFalse = areEqual( r, getTermDatabase()->d_false );\r
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee );\r
+ while( !eqc_i.isFinished() ){\r
+ TNode n = (*eqc_i);\r
+ if( !n.getAttribute(NoMatchAttribute()) && ( n.getKind()!=EQUAL || isFalse ) ){\r
+ if( firstTime ){\r
+ Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl;\r
+ firstTime = false;\r
+ }\r
+ if( n.hasOperator() ){\r
+ Trace("sg-gen-eqc") << " (" << n.getOperator();\r
+ getTermDatabase()->computeArgReps( n );\r
+ for( unsigned i=0; i<getTermDatabase()->d_arg_reps[n].size(); i++ ){\r
+ Trace("sg-gen-eqc") << " e" << d_em[getTermDatabase()->d_arg_reps[n][i]];\r
+ }\r
+ Trace("sg-gen-eqc") << ") :: " << n << std::endl;\r
+ }else{\r
+ Trace("sg-gen-eqc") << " " << n << std::endl;\r
+ }\r
+ }\r
+ ++eqc_i;\r
+ }\r
+ if( !firstTime ){\r
+ Trace("sg-gen-eqc") << "}" << std::endl;\r
+ //print out ground term\r
+ std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );\r
+ if( it!=d_ground_eqc_map.end() ){\r
+ Trace("sg-gen-eqc") << "- Ground term : " << it->second << std::endl;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Trace("sg-proc") << "Compute relevant eqc..." << std::endl;\r
+ d_relevant_eqc[0].clear();\r
+ d_relevant_eqc[1].clear();\r
+ for( unsigned i=0; i<eqcs.size(); i++ ){\r
+ TNode r = eqcs[i];\r
+ std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r );\r
+ unsigned index = 1;\r
+ if( it==d_ground_eqc_map.end() ){\r
+ index = 0;\r
+ }\r
+ //based on unproven conjectures? TODO\r
+ d_relevant_eqc[index].push_back( r );\r
+ }\r
+ Trace("sg-gen-tg-debug") << "Initial relevant eqc : ";\r
+ for( unsigned i=0; i<d_relevant_eqc[0].size(); i++ ){\r
+ Trace("sg-gen-tg-debug") << "e" << d_em[d_relevant_eqc[0][i]] << " ";\r
+ }\r
+ Trace("sg-gen-tg-debug") << std::endl;\r
+ Trace("sg-proc") << "...done compute relevant eqc" << std::endl;\r
+\r
+\r
+ Trace("sg-proc") << "Collect signature information..." << std::endl;\r
+ d_funcs.clear();\r
+ d_typ_funcs.clear();\r
+ d_func_kind.clear();\r
+ d_func_args.clear();\r
+ TypeNode tnull;\r
+ for( std::map< Node, TermArgTrie >::iterator it = getTermDatabase()->d_func_map_trie.begin(); it != getTermDatabase()->d_func_map_trie.end(); ++it ){\r
+ if( !getTermDatabase()->d_op_map[it->first].empty() ){\r
+ Node nn = getTermDatabase()->d_op_map[it->first][0];\r
+ if( isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){\r
+ d_funcs.push_back( it->first );\r
+ d_typ_funcs[tnull].push_back( it->first );\r
+ d_typ_funcs[nn.getType()].push_back( it->first );\r
+ for( unsigned i=0; i<nn.getNumChildren(); i++ ){\r
+ d_func_args[it->first].push_back( nn[i].getType() );\r
+ }\r
+ d_func_kind[it->first] = nn.getKind();\r
+ Trace("sg-rel-sig") << "Will enumerate function applications of : " << it->first << ", #args = " << d_func_args[it->first].size() << ", kind = " << nn.getKind() << std::endl;\r
+ getTermDatabase()->computeUfEqcTerms( it->first );\r
+ }\r
+ }\r
+ }\r
+ //shuffle functions\r
+ for( std::map< TypeNode, std::vector< TNode > >::iterator it = d_typ_funcs.begin(); it !=d_typ_funcs.end(); ++it ){\r
+ std::random_shuffle( it->second.begin(), it->second.end() );\r
+ if( it->first.isNull() ){\r
+ Trace("sg-gen-tg-debug") << "In this order : ";\r
+ for( unsigned i=0; i<it->second.size(); i++ ){\r
+ Trace("sg-gen-tg-debug") << it->second[i] << " "; \r
+ }\r
+ Trace("sg-gen-tg-debug") << std::endl;\r
+ }\r
+ }\r
+ Trace("sg-proc") << "...done collect signature information" << std::endl;\r
+\r
+\r
+ Trace("sg-proc") << "Build theorem index..." << std::endl;\r
+ d_ue_canon.clear();\r
+ d_thm_index.clear();\r
+ std::vector< Node > provenConj;\r
+ quantifiers::FirstOrderModel* m = d_quantEngine->getModel();\r
+ for( int i=0; i<m->getNumAssertedQuantifiers(); i++ ){\r
+ Node q = m->getAssertedQuantifier( i );\r
+ Trace("sg-conjecture-debug") << "Is " << q << " a relevant theorem?" << std::endl;\r
+ Node conjEq;\r
+ if( q[1].getKind()==EQUAL ){\r
+ bool isSubsume = false;\r
+ bool inEe = false;\r
+ for( unsigned r=0; r<2; r++ ){\r
+ TNode nl = q[1][r==0 ? 0 : 1];\r
+ TNode nr = q[1][r==0 ? 1 : 0];\r
+ Node eq = nl.eqNode( nr );\r
+ if( r==1 || std::find( d_conjectures.begin(), d_conjectures.end(), q )==d_conjectures.end() ){\r
+ //must make it canonical\r
+ std::map< TypeNode, unsigned > var_count;\r
+ std::map< TNode, TNode > subs;\r
+ Trace("sg-proc-debug") << "get canonical " << eq << std::endl;\r
+ eq = getCanonicalTerm( eq, var_count, subs );\r
+ }\r
+ if( !eq.isNull() ){\r
+ if( r==0 ){\r
+ inEe = d_ee_conjectures.find( q[1] )!=d_ee_conjectures.end();\r
+ if( !inEe ){\r
+ //add to universal equality engine\r
+ Node nl = getUniversalRepresentative( eq[0], true );\r
+ Node nr = getUniversalRepresentative( eq[1], true );\r
+ if( areUniversalEqual( nl, nr ) ){\r
+ isSubsume = true;\r
+ //set inactive (will be ignored by other modules)\r
+ d_quantEngine->getModel()->setQuantifierActive( q, false );\r
+ }else{\r
+ Node exp;\r
+ d_ee_conjectures[q[1]] = true;\r
+ d_uequalityEngine.assertEquality( nl.eqNode( nr ), true, exp );\r
+ }\r
+ }\r
+ Trace("sg-conjecture") << "*** CONJECTURE : currently proven" << (isSubsume ? " and subsumed" : "");\r
+ Trace("sg-conjecture") << " : " << q[1] << std::endl;\r
+ provenConj.push_back( q );\r
+ }\r
+ if( !isSubsume ){\r
+ Trace("thm-db-debug") << "Adding theorem to database " << eq[0] << " == " << eq[1] << std::endl;\r
+ d_thm_index.addTheorem( eq[0], eq[1] );\r
+ }else{\r
+ break;\r
+ }\r
+ }else{\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ //examine status of other conjectures\r
+ for( unsigned i=0; i<d_conjectures.size(); i++ ){\r
+ Node q = d_conjectures[i];\r
+ if( std::find( provenConj.begin(), provenConj.end(), q )==provenConj.end() ){\r
+ //check each skolem variable\r
+ bool disproven = true;\r
+ std::vector< Node > sk;\r
+ getTermDatabase()->getSkolemConstants( q, sk, true );\r
+ Trace("sg-conjecture") << " CONJECTURE : ";\r
+ std::vector< Node > ce;\r
+ for( unsigned j=0; j<sk.size(); j++ ){\r
+ TNode k = sk[j];\r
+ TNode rk = getRepresentative( k );\r
+ std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( rk );\r
+ //check if it is a ground term\r
+ if( git==d_ground_eqc_map.end() ){\r
+ Trace("sg-conjecture") << "ACTIVE : " << q;\r
+ if( Trace.isOn("sg-gen-eqc") ){\r
+ Trace("sg-conjecture") << " { ";\r
+ for( unsigned k=0; k<sk.size(); k++ ){ Trace("sg-conjecture") << sk[k] << ( j==k ? "*" : "" ) << " "; }\r
+ Trace("sg-conjecture") << "}";\r
+ }\r
+ Trace("sg-conjecture") << std::endl;\r
+ disproven = false;\r
+ break;\r
+ }else{\r
+ ce.push_back( git->second );\r
+ }\r
+ }\r
+ if( disproven ){\r
+ Trace("sg-conjecture") << "disproven : " << q << " : ";\r
+ for( unsigned i=0; i<ce.size(); i++ ){\r
+ Trace("sg-conjecture") << q[0][i] << " -> " << ce[i] << " ";\r
+ }\r
+ Trace("sg-conjecture") << std::endl;\r
+ }\r
+ }\r
+ }\r
+ Trace("thm-db") << "Theorem database is : " << std::endl;\r
+ d_thm_index.debugPrint( "thm-db" );\r
+ Trace("thm-db") << std::endl;\r
+ Trace("sg-proc") << "...done build theorem index" << std::endl;\r
+\r
+ //clear patterns\r
+ d_patterns.clear();\r
+ d_pattern_var_id.clear();\r
+ d_pattern_var_duplicate.clear();\r
+ d_pattern_is_normal.clear();\r
+ d_pattern_fun_id.clear();\r
+ d_pattern_fun_sum.clear();\r
+ d_rel_patterns.clear();\r
+ d_rel_pattern_var_sum.clear();\r
+ d_rel_pattern_typ_index.clear();\r
+ d_rel_pattern_subs_index.clear();\r
+ d_gen_lat_maximal.clear();\r
+ d_gen_lat_child.clear();\r
+ d_gen_lat_parent.clear();\r
+ d_gen_depth.clear();\r
+\r
+ //the following generates a set of relevant terms\r
+ d_use_ccand_eqc = true;\r
+ for( unsigned i=0; i<2; i++ ){\r
+ d_ccand_eqc[i].clear();\r
+ d_ccand_eqc[i].push_back( d_relevant_eqc[i] );\r
+ }\r
+ d_rel_term_count = 0;\r
+ //consider all functions\r
+ d_typ_tg_funcs.clear();\r
+ for( std::map< TypeNode, std::vector< TNode > >::iterator it = d_typ_funcs.begin(); it != d_typ_funcs.end(); ++it ){\r
+ d_typ_tg_funcs[it->first].insert( d_typ_tg_funcs[it->first].end(), it->second.begin(), it->second.end() );\r
+ }\r
+ std::map< TypeNode, unsigned > rt_var_max;\r
+ std::vector< TypeNode > rt_types;\r
+ //map from generalization depth to maximum depth\r
+ //std::map< unsigned, unsigned > gdepth_to_tdepth;\r
+ for( unsigned depth=1; depth<3; depth++ ){\r
+ Assert( d_tg_alloc.empty() );\r
+ Trace("sg-proc") << "Generate terms at depth " << depth << "..." << std::endl;\r
+ Trace("sg-rel-term") << "Relevant terms of depth " << depth << " : " << std::endl;\r
+ //set up environment\r
+ d_var_id.clear();\r
+ d_var_limit.clear();\r
+ d_tg_id = 0;\r
+ d_tg_gdepth = 0;\r
+ d_tg_gdepth_limit = -1;\r
+ //consider all types\r
+ d_tg_alloc[0].reset( this, TypeNode::null() );\r
+ while( d_tg_alloc[0].getNextTerm( this, depth ) ){\r
+ Assert( d_tg_alloc[0].getGeneralizationDepth( this )==d_tg_gdepth );\r
+ if( d_tg_alloc[0].getDepth( this )==depth ){\r
+ //construct term\r
+ Node nn = d_tg_alloc[0].getTerm( this );\r
+ if( getUniversalRepresentative( nn )==nn ){\r
+ d_rel_term_count++;\r
+ Trace("sg-rel-term") << "*** Relevant term : ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-rel-term", "sg-rel-term-debug2" );\r
+ Trace("sg-rel-term") << std::endl;\r
+\r
+ for( unsigned r=0; r<2; r++ ){\r
+ Trace("sg-gen-tg-eqc") << "...from equivalence classes (" << r << ") : ";\r
+ int index = d_ccand_eqc[r].size()-1;\r
+ for( unsigned j=0; j<d_ccand_eqc[r][index].size(); j++ ){\r
+ Trace("sg-gen-tg-eqc") << "e" << d_em[d_ccand_eqc[r][index][j]] << " ";\r
+ }\r
+ Trace("sg-gen-tg-eqc") << std::endl;\r
+ }\r
+ TypeNode tnn = nn.getType();\r
+ Trace("sg-gen-tg-debug") << "...term is " << nn << std::endl;\r
+ Assert( getUniversalRepresentative( nn )==nn );\r
+\r
+ //add information about pattern\r
+ Trace("sg-gen-tg-debug") << "Collect pattern information..." << std::endl;\r
+ Assert( std::find( d_rel_patterns[tnn].begin(), d_rel_patterns[tnn].end(), nn )==d_rel_patterns[tnn].end() );\r
+ d_rel_patterns[tnn].push_back( nn );\r
+ //build information concerning the variables in this pattern\r
+ unsigned sum = 0;\r
+ std::map< TypeNode, unsigned > typ_to_subs_index;\r
+ std::vector< TNode > gsubs_vars;\r
+ for( std::map< TypeNode, unsigned >::iterator it = d_var_id.begin(); it != d_var_id.end(); ++it ){\r
+ if( it->second>0 ){\r
+ typ_to_subs_index[it->first] = sum;\r
+ sum += it->second;\r
+ for( unsigned i=0; i<it->second; i++ ){\r
+ gsubs_vars.push_back( getFreeVar( it->first, i ) );\r
+ }\r
+ }\r
+ }\r
+ d_rel_pattern_var_sum[nn] = sum;\r
+ //register the pattern\r
+ registerPattern( nn, tnn );\r
+ Assert( d_pattern_is_normal[nn] );\r
+ Trace("sg-gen-tg-debug") << "...done collect pattern information" << std::endl;\r
+\r
+ //compute generalization relation\r
+ Trace("sg-gen-tg-debug") << "Build generalization information..." << std::endl;\r
+ std::map< TNode, bool > patProc;\r
+ int maxGenDepth = -1;\r
+ unsigned i = d_rel_patterns[tnn].size()-1;\r
+ for( int j=(int)(i-1); j>=0; j-- ){\r
+ TNode np = d_rel_patterns[tnn][j];\r
+ if( patProc.find( np )==patProc.end() ){\r
+ Trace("sg-gen-tg-debug2") << "Check if generalized by " << np << "..." << std::endl;\r
+ if( isGeneralization( np, nn ) ){\r
+ Trace("sg-rel-terms-debug") << " is generalized by : " << np << std::endl;\r
+ d_gen_lat_child[np].push_back( nn );\r
+ d_gen_lat_parent[nn].push_back( np );\r
+ if( d_gen_depth[np]>maxGenDepth ){\r
+ maxGenDepth = d_gen_depth[np];\r
+ }\r
+ //don't consider the transitive closure of generalizes\r
+ Trace("sg-gen-tg-debug2") << "Add generalizations" << std::endl;\r
+ addGeneralizationsOf( np, patProc );\r
+ Trace("sg-gen-tg-debug2") << "Done add generalizations" << std::endl;\r
+ }else{\r
+ Trace("sg-gen-tg-debug2") << " is not generalized by : " << np << std::endl;\r
+ }\r
+ }\r
+ }\r
+ if( d_gen_lat_parent[nn].empty() ){\r
+ d_gen_lat_maximal[tnn].push_back( nn );\r
+ }\r
+ d_gen_depth[nn] = maxGenDepth+1;\r
+ Trace("sg-rel-term-debug") << " -> generalization depth is " << d_gen_depth[nn] << " <> " << depth << std::endl;\r
+ Trace("sg-gen-tg-debug") << "...done build generalization information" << std::endl;\r
+\r
+ //record information about types\r
+ Trace("sg-gen-tg-debug") << "Collect type information..." << std::endl;\r
+ PatternTypIndex * pti = &d_rel_pattern_typ_index;\r
+ for( std::map< TypeNode, unsigned >::iterator it = d_var_id.begin(); it != d_var_id.end(); ++it ){\r
+ pti = &pti->d_children[it->first][it->second];\r
+ //record maximum\r
+ if( rt_var_max.find( it->first )==rt_var_max.end() || it->second>rt_var_max[it->first] ){\r
+ rt_var_max[it->first] = it->second;\r
+ }\r
+ }\r
+ if( std::find( rt_types.begin(), rt_types.end(), tnn )==rt_types.end() ){\r
+ rt_types.push_back( tnn );\r
+ }\r
+ pti->d_terms.push_back( nn );\r
+ Trace("sg-gen-tg-debug") << "...done collect type information" << std::endl;\r
+\r
+ Trace("sg-gen-tg-debug") << "Build substitutions for ground EQC..." << std::endl;\r
+ std::vector< TNode > gsubs_terms;\r
+ gsubs_terms.resize( gsubs_vars.size() );\r
+ int index = d_ccand_eqc[1].size()-1;\r
+ for( unsigned j=0; j<d_ccand_eqc[1][index].size(); j++ ){\r
+ TNode r = d_ccand_eqc[1][index][j];\r
+ Trace("sg-gen-tg-eqc") << " Matches for e" << d_em[r] << ", which is ground term " << d_ground_eqc_map[r] << ":" << std::endl;\r
+ std::map< TypeNode, std::map< unsigned, TNode > > subs;\r
+ std::map< TNode, bool > rev_subs;\r
+ //only get ground terms\r
+ unsigned mode = optFilterConfirmationOnlyGround() ? 2 : 0;\r
+ d_tg_alloc[0].resetMatching( this, r, mode );\r
+ while( d_tg_alloc[0].getNextMatch( this, r, subs, rev_subs ) ){\r
+ //we will be building substitutions\r
+ bool firstTime = true;\r
+ for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+ unsigned tindex = typ_to_subs_index[it->first];\r
+ for( std::map< unsigned, TNode >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
+ if( !firstTime ){\r
+ Trace("sg-gen-tg-eqc") << ", ";\r
+ }else{\r
+ firstTime = false;\r
+ Trace("sg-gen-tg-eqc") << " ";\r
+ }\r
+ Trace("sg-gen-tg-eqc") << it->first << ":x" << it2->first << " -> " << it2->second;\r
+ Assert( tindex+it2->first<gsubs_terms.size() );\r
+ gsubs_terms[tindex+it2->first] = it2->second;\r
+ }\r
+ }\r
+ Trace("sg-gen-tg-eqc") << std::endl;\r
+ d_rel_pattern_subs_index[nn].addSubstitution( r, gsubs_vars, gsubs_terms );\r
+ }\r
+ }\r
+ Trace("sg-gen-tg-debug") << "...done build substitutions for ground EQC" << std::endl;\r
+ }else{\r
+ Trace("sg-gen-tg-debug") << "> not canonical : " << nn << std::endl;\r
+ }\r
+ }else{\r
+ Trace("sg-gen-tg-debug") << "> produced term at previous depth : ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+ Trace("sg-gen-tg-debug") << std::endl;\r
+ }\r
+ }\r
+ Trace("sg-proc") << "...done generate terms at depth " << depth << std::endl;\r
+ \r
+ \r
+ //now generate right hand sides\r
+\r
+\r
+ }\r
+ Trace("sg-stats") << "--------> Total relevant patterns : " << d_rel_term_count << std::endl;\r
+\r
+ Trace("sg-proc") << "Generate properties..." << std::endl;\r
+ //set up environment\r
+ d_use_ccand_eqc = false;\r
+ d_var_id.clear();\r
+ d_var_limit.clear();\r
+ for( std::map< TypeNode, unsigned >::iterator it = rt_var_max.begin(); it != rt_var_max.end(); ++it ){\r
+ d_var_id[ it->first ] = it->second;\r
+ d_var_limit[ it->first ] = it->second;\r
+ }\r
+ //set up environment for candidate conjectures\r
+ d_cconj_at_depth.clear();\r
+ for( unsigned i=0; i<2; i++ ){\r
+ d_cconj[i].clear();\r
+ }\r
+ d_cconj_rhs_paired.clear();\r
+ unsigned totalCount = 0;\r
+ for( unsigned depth=0; depth<5; depth++ ){\r
+ //consider types from relevant terms\r
+ std::random_shuffle( rt_types.begin(), rt_types.end() );\r
+ for( unsigned i=0; i<rt_types.size(); i++ ){\r
+ Assert( d_tg_alloc.empty() );\r
+ Trace("sg-proc") << "Generate relevant RHS terms of type " << rt_types[i] << " at depth " << depth << "..." << std::endl;\r
+ d_tg_id = 0;\r
+ d_tg_alloc[0].reset( this, rt_types[i] );\r
+ while( d_tg_alloc[0].getNextTerm( this, depth ) && totalCount<100 ){\r
+ if( d_tg_alloc[0].getDepth( this )==depth ){\r
+ Node rhs = d_tg_alloc[0].getTerm( this );\r
+ Trace("sg-rel-prop") << "Relevant RHS : " << rhs << std::endl;\r
+ //register pattern\r
+ Assert( rhs.getType()==rt_types[i] );\r
+ registerPattern( rhs, rt_types[i] );\r
+ //for each maximal node of type rt_types[i] in generalization lattice\r
+ for( unsigned j=0; j<d_gen_lat_maximal[rt_types[i]].size(); j++ ){\r
+ //add candidate conjecture\r
+ addCandidateConjecture( d_gen_lat_maximal[rt_types[i]][j], rhs, 0 );\r
+ }\r
+ totalCount++;\r
+ }\r
+ }\r
+ //could have been partial, we must clear\r
+ d_tg_alloc.clear();\r
+ }\r
+ Trace("sg-proc") << "Process candidate conjectures up to RHS term depth " << depth << "..." << std::endl;\r
+ for( unsigned conj_depth=0; conj_depth<depth; conj_depth++ ){\r
+ //process all conjectures waiting at depth\r
+ unsigned sz = d_cconj_at_depth[conj_depth].size();\r
+ for( int i=(int)(sz-1); i>=0; i-- ){\r
+ processCandidateConjecture( d_cconj_at_depth[conj_depth][i], conj_depth );\r
+ }\r
+ Assert( d_cconj_at_depth[conj_depth].size()==sz );\r
+ d_cconj_at_depth[conj_depth].clear();\r
+ }\r
+ Trace("sg-proc") << "...done process candidate conjectures at RHS term depth " << depth << std::endl;\r
+ }\r
+ Trace("sg-proc") << "...done generate properties" << std::endl;\r
+\r
+ if( !d_waiting_conjectures.empty() ){\r
+ Trace("sg-proc") << "Generated " << d_waiting_conjectures.size() << " conjectures." << std::endl;\r
+ d_conjectures.insert( d_conjectures.end(), d_waiting_conjectures.begin(), d_waiting_conjectures.end() );\r
+ for( unsigned i=0; i<d_waiting_conjectures.size(); i++ ){\r
+ Assert( d_waiting_conjectures[i].getKind()==FORALL );\r
+ Node lem = NodeManager::currentNM()->mkNode( OR, d_waiting_conjectures[i].negate(), d_waiting_conjectures[i] );\r
+ d_quantEngine->getOutputChannel().lemma( lem );\r
+ d_quantEngine->getOutputChannel().requirePhase( d_waiting_conjectures[i], false );\r
+ }\r
+ d_waiting_conjectures.clear();\r
+ }\r
+\r
+ Trace("thm-ee") << "Universal equality engine is : " << std::endl;\r
+ eq::EqClassesIterator ueqcs_i = eq::EqClassesIterator( &d_uequalityEngine );\r
+ while( !ueqcs_i.isFinished() ){\r
+ TNode r = (*ueqcs_i);\r
+ bool firstTime = true;\r
+ TNode rr = getUniversalRepresentative( r );\r
+ Trace("thm-ee") << " " << r;\r
+ if( rr!=r ){ Trace("thm-ee") << " [" << rr << "]"; }\r
+ Trace("thm-ee") << " : { ";\r
+ eq::EqClassIterator ueqc_i = eq::EqClassIterator( r, &d_uequalityEngine );\r
+ while( !ueqc_i.isFinished() ){\r
+ TNode n = (*ueqc_i);\r
+ if( r!=n ){\r
+ if( firstTime ){\r
+ Trace("thm-ee") << std::endl;\r
+ firstTime = false;\r
+ }\r
+ Trace("thm-ee") << " " << n << std::endl;\r
+ }\r
+ ++ueqc_i;\r
+ }\r
+ if( !firstTime ){ Trace("thm-ee") << " "; }\r
+ Trace("thm-ee") << "}" << std::endl;\r
+ ++ueqcs_i;\r
+ }\r
+ Trace("thm-ee") << std::endl;\r
+ }\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::registerQuantifier( Node q ) {\r
+\r
+}\r
+\r
+void ConjectureGenerator::assertNode( Node n ) {\r
+\r
+}\r
+\r
+\r
+unsigned ConjectureGenerator::getNumTgVars( TypeNode tn ) {\r
+ //return d_var_tg.size();\r
+ return d_var_id[tn];\r
+}\r
+\r
+bool ConjectureGenerator::allowVar( TypeNode tn ) {\r
+ std::map< TypeNode, unsigned >::iterator it = d_var_limit.find( tn );\r
+ if( it==d_var_limit.end() ){\r
+ return true;\r
+ }else{\r
+ return d_var_id[tn]<it->second;\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::addVar( TypeNode tn ) {\r
+ //d_var_tg.push_back( v );\r
+ d_var_id[tn]++;\r
+ //d_var_eq_tg.push_back( std::vector< unsigned >() );\r
+}\r
+\r
+void ConjectureGenerator::removeVar( TypeNode tn ) {\r
+ d_var_id[tn]--;\r
+ //d_var_eq_tg.pop_back();\r
+ //d_var_tg.pop_back();\r
+}\r
+\r
+unsigned ConjectureGenerator::getNumTgFuncs( TypeNode tn ) {\r
+ return d_typ_tg_funcs[tn].size();\r
+}\r
+\r
+TNode ConjectureGenerator::getTgFunc( TypeNode tn, unsigned i ) {\r
+ return d_typ_tg_funcs[tn][i];\r
+}\r
+\r
+bool ConjectureGenerator::considerCurrentTerm() {\r
+ Assert( !d_tg_alloc.empty() );\r
+ \r
+ //if generalization depth is too large, don't consider it\r
+ unsigned i = d_tg_alloc.size();\r
+ Trace("sg-gen-tg-debug") << "Consider term ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+ Trace("sg-gen-tg-debug") << "? curr term size = " << d_tg_alloc.size() << ", last status = " << d_tg_alloc[i-1].d_status;\r
+ Trace("sg-gen-tg-debug") << std::endl;\r
+ \r
+ Assert( d_tg_alloc[0].getGeneralizationDepth( this )==d_tg_gdepth );\r
+ \r
+ if( d_tg_gdepth_limit>=0 && d_tg_gdepth>(unsigned)d_tg_gdepth_limit ){\r
+ Trace("sg-gen-consider-term") << "-> generalization depth of ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-tg-debug" );\r
+ Trace("sg-gen-consider-term") << " is too high " << d_tg_gdepth << " " << d_tg_alloc[0].getGeneralizationDepth( this ) << ", do not consider." << std::endl;\r
+ return false;\r
+ }\r
+ \r
+ //----optimizations\r
+ if( d_tg_alloc[i-1].d_status==1 ){\r
+ }else if( d_tg_alloc[i-1].d_status==2 ){\r
+ }else if( d_tg_alloc[i-1].d_status==5 ){\r
+ }else{\r
+ Trace("sg-gen-tg-debug") << "Bad tg: " << &d_tg_alloc[i-1] << std::endl;\r
+ Assert( false );\r
+ }\r
+ //if equated two variables, first check if context-independent TODO\r
+ //----end optimizations\r
+\r
+\r
+ //check based on which candidate equivalence classes match\r
+ if( d_use_ccand_eqc ){\r
+ Trace("sg-gen-tg-debug") << "Filter based on relevant ground EQC";\r
+ Trace("sg-gen-tg-debug") << ", #eqc to try = " << d_ccand_eqc[0][i-1].size() << "/" << d_ccand_eqc[1][i-1].size() << std::endl;\r
+\r
+ Assert( d_ccand_eqc[0].size()>=2 );\r
+ Assert( d_ccand_eqc[0].size()==d_ccand_eqc[1].size() );\r
+ Assert( d_ccand_eqc[0].size()==d_tg_id+1 );\r
+ Assert( d_tg_id==d_tg_alloc.size() );\r
+ for( unsigned r=0; r<2; r++ ){\r
+ d_ccand_eqc[r][i].clear();\r
+ }\r
+\r
+ //re-check feasibility of EQC\r
+ for( unsigned r=0; r<2; r++ ){\r
+ for( unsigned j=0; j<d_ccand_eqc[r][i-1].size(); j++ ){\r
+ std::map< TypeNode, std::map< unsigned, TNode > > subs;\r
+ std::map< TNode, bool > rev_subs;\r
+ unsigned mode;\r
+ if( r==0 ){\r
+ mode = optReqDistinctVarPatterns() ? 1 : 0;\r
+ }else{\r
+ mode = (optFilterConfirmation() && optFilterConfirmationOnlyGround() ) ? 2 : 0;\r
+ }\r
+ d_tg_alloc[0].resetMatching( this, d_ccand_eqc[r][i-1][j], mode );\r
+ if( d_tg_alloc[0].getNextMatch( this, d_ccand_eqc[r][i-1][j], subs, rev_subs ) ){\r
+ d_ccand_eqc[r][i].push_back( d_ccand_eqc[r][i-1][j] );\r
+ }\r
+ }\r
+ }\r
+ for( unsigned r=0; r<2; r++ ){\r
+ Trace("sg-gen-tg-debug") << "Current eqc of type " << r << " : ";\r
+ for( unsigned j=0; j<d_ccand_eqc[r][i].size(); j++ ){\r
+ Trace("sg-gen-tg-debug") << "e" << d_em[d_ccand_eqc[r][i][j]] << " ";\r
+ }\r
+ Trace("sg-gen-tg-debug") << std::endl;\r
+ }\r
+ if( d_ccand_eqc[0][i].empty() ){\r
+ Trace("sg-gen-consider-term") << "Do not consider term of form ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );\r
+ Trace("sg-gen-consider-term") << " since no relevant EQC matches it." << std::endl;\r
+ return false;\r
+ }\r
+ if( d_ccand_eqc[1][i].empty() && optFilterConfirmation() ){\r
+ Trace("sg-gen-consider-term") << "Do not consider term of form ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );\r
+ Trace("sg-gen-consider-term") << " since no ground EQC matches it." << std::endl;\r
+ return false;\r
+ }\r
+ }\r
+ Trace("sg-gen-tg-debug") << "Will consider term ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+ Trace("sg-gen-tg-debug") << std::endl;\r
+ Trace("sg-gen-consider-term-debug") << std::endl;\r
+ return true;\r
+}\r
+\r
+bool ConjectureGenerator::considerTermCanon( unsigned tg_id ){\r
+ Assert( tg_id<d_tg_alloc.size() );\r
+ //check based on a canonicity of the term (if there is one)\r
+ Trace("sg-gen-tg-debug") << "Consider term canon ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+ Trace("sg-gen-tg-debug") << ", tg is [" << tg_id << "]..." << std::endl;\r
+\r
+ Node ln = d_tg_alloc[tg_id].getTerm( this );\r
+ Trace("sg-gen-tg-debug") << "Term is " << ln << std::endl;\r
+ if( !ln.isNull() ){\r
+ //do not consider if it is non-canonical, and either:\r
+ // (1) we are not filtering based on matching candidate eqc, or\r
+ // (2) its canonical form is a generalization.\r
+ TNode lnr = getUniversalRepresentative( ln, true );\r
+ if( lnr==ln ){\r
+ markReportedCanon( ln );\r
+ }else if( !d_use_ccand_eqc || isGeneralization( lnr, ln ) ){\r
+ Trace("sg-gen-consider-term") << "Do not consider term of form ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" );\r
+ Trace("sg-gen-consider-term") << " since sub-term " << ln << " is not canonical representation (which is " << lnr << ")." << std::endl;\r
+ return false;\r
+ }\r
+ }\r
+ Trace("sg-gen-tg-debug") << "Will consider term canon ";\r
+ d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" );\r
+ Trace("sg-gen-tg-debug") << std::endl;\r
+ Trace("sg-gen-consider-term-debug") << std::endl;\r
+ return true;\r
+}\r
+\r
+void ConjectureGenerator::changeContext( bool add ) {\r
+ if( add ){\r
+ for( unsigned r=0; r<2; r++ ){\r
+ d_ccand_eqc[r].push_back( std::vector< TNode >() );\r
+ }\r
+ d_tg_id++;\r
+ }else{\r
+ for( unsigned r=0; r<2; r++ ){\r
+ d_ccand_eqc[r].pop_back();\r
+ }\r
+ d_tg_id--;\r
+ Assert( d_tg_alloc.find( d_tg_id )!=d_tg_alloc.end() );\r
+ d_tg_alloc.erase( d_tg_id );\r
+ }\r
+}\r
+\r
+unsigned ConjectureGenerator::collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs,\r
+ std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn ){\r
+ if( pat.hasOperator() ){\r
+ funcs[pat.getOperator()]++;\r
+ unsigned sum = 1;\r
+ for( unsigned i=0; i<pat.getNumChildren(); i++ ){\r
+ sum += collectFunctions( opat, pat[i], funcs, mnvn, mxvn );\r
+ }\r
+ return sum;\r
+ }else{\r
+ Assert( pat.getNumChildren()==0 );\r
+ funcs[pat]++;\r
+ //for variables\r
+ if( pat.getKind()==BOUND_VARIABLE ){\r
+ if( funcs[pat]>1 ){\r
+ //duplicate variable\r
+ d_pattern_var_duplicate[opat]++;\r
+ }else{\r
+ //check for max/min\r
+ TypeNode tn = pat.getType();\r
+ unsigned vn = d_free_var_num[pat];\r
+ std::map< TypeNode, unsigned >::iterator it = mnvn.find( tn );\r
+ if( it!=mnvn.end() ){\r
+ if( vn<it->second ){\r
+ d_pattern_is_normal[opat] = false;\r
+ mnvn[tn] = vn;\r
+ }else if( vn>mxvn[tn] ){\r
+ if( vn!=mxvn[tn]+1 ){\r
+ d_pattern_is_normal[opat] = false;\r
+ }\r
+ mxvn[tn] = vn;\r
+ }\r
+ }else{\r
+ //first variable of this type\r
+ mnvn[tn] = vn;\r
+ mxvn[tn] = vn;\r
+ }\r
+ }\r
+ }\r
+ return 1;\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::registerPattern( Node pat, TypeNode tpat ) {\r
+ if( std::find( d_patterns[tpat].begin(), d_patterns[tpat].end(), pat )==d_patterns[tpat].end() ){\r
+ d_patterns[TypeNode::null()].push_back( pat );\r
+ d_patterns[tpat].push_back( pat );\r
+\r
+ Assert( d_pattern_fun_id.find( pat )==d_pattern_fun_id.end() );\r
+ Assert( d_pattern_var_id.find( pat )==d_pattern_var_id.end() );\r
+\r
+ //collect functions\r
+ std::map< TypeNode, unsigned > mnvn;\r
+ d_pattern_fun_sum[pat] = collectFunctions( pat, pat, d_pattern_fun_id[pat], mnvn, d_pattern_var_id[pat] );\r
+ if( d_pattern_is_normal.find( pat )==d_pattern_is_normal.end() ){\r
+ d_pattern_is_normal[pat] = true;\r
+ }\r
+ }\r
+}\r
+\r
+bool ConjectureGenerator::isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs ) {\r
+ if( patg.getKind()==BOUND_VARIABLE ){\r
+ std::map< TNode, TNode >::iterator it = subs.find( patg );\r
+ if( it!=subs.end() ){\r
+ return it->second==pat;\r
+ }else{\r
+ subs[patg] = pat;\r
+ return true;\r
+ }\r
+ }else{\r
+ Assert( patg.hasOperator() );\r
+ if( !pat.hasOperator() || patg.getOperator()!=pat.getOperator() ){\r
+ return false;\r
+ }else{\r
+ Assert( patg.getNumChildren()==pat.getNumChildren() );\r
+ for( unsigned i=0; i<patg.getNumChildren(); i++ ){\r
+ if( !isGeneralization( patg[i], pat[i], subs ) ){\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::addGeneralizationsOf( TNode pat, std::map< TNode, bool >& patProc ) {\r
+ patProc[pat] = true;\r
+ for( unsigned k=0; k<d_gen_lat_parent[pat].size(); k++ ){\r
+ addGeneralizationsOf( d_gen_lat_parent[pat][k], patProc );\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::addCandidateConjecture( TNode lhs, TNode rhs, unsigned depth ) {\r
+ if( std::find( d_cconj_rhs_paired[rhs].begin(), d_cconj_rhs_paired[rhs].end(), lhs )==d_cconj_rhs_paired[rhs].end() ){\r
+ //add conjecture to list to process\r
+ d_cconj_at_depth[depth].push_back( d_cconj[0].size() );\r
+ //define conjecture\r
+ d_cconj[0].push_back( lhs );\r
+ d_cconj[1].push_back( rhs );\r
+ d_cconj_rhs_paired[rhs].push_back( lhs );\r
+ }\r
+}\r
+\r
+void ConjectureGenerator::processCandidateConjecture( unsigned cid, unsigned depth ) {\r
+ if( d_waiting_conjectures.size()>=optFullCheckConjectures() ){\r
+ return;\r
+ }\r
+ TNode lhs = d_cconj[0][cid];\r
+ TNode rhs = d_cconj[1][cid];\r
+ if( !considerCandidateConjecture( lhs, rhs ) ){\r
+ //push to children of generalization lattice\r
+ for( unsigned i=0; i<d_gen_lat_child[lhs].size(); i++ ){\r
+ if( d_gen_depth[lhs]+1==d_gen_depth[d_gen_lat_child[lhs][i]] ){\r
+ addCandidateConjecture( d_gen_lat_child[lhs][i], rhs, depth+1 );\r
+ }\r
+ }\r
+ }else{\r
+ Trace("sg-conjecture") << "* Candidate conjecture : " << lhs << " == " << rhs << std::endl;\r
+ Trace("sg-conjecture-debug") << " LHS generalization depth : " << d_gen_depth[lhs] << std::endl;\r
+ if( optFilterConfirmation() || optFilterFalsification() ){\r
+ Trace("sg-conjecture-debug") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;\r
+ Trace("sg-conjecture-debug") << " #witnesses for ";\r
+ bool firstTime = true;\r
+ for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){\r
+ if( !firstTime ){\r
+ Trace("sg-conjecture-debug") << ", ";\r
+ }\r
+ Trace("sg-conjecture-debug") << it->first << " : " << it->second.size() << "/" << d_pattern_fun_id[lhs][it->first];\r
+ firstTime = false;\r
+ }\r
+ Trace("sg-conjecture-debug") << std::endl;\r
+ }\r
+ /*\r
+ if( getUniversalRepresentative( lhs )!=lhs ){\r
+ std::cout << "bad universal representative LHS : " << lhs << " " << getUniversalRepresentative( lhs ) << std::endl;\r
+ exit(0);\r
+ }\r
+ if( getUniversalRepresentative( rhs )!=rhs ){\r
+ std::cout << "bad universal representative RHS : " << rhs << " " << getUniversalRepresentative( rhs ) << std::endl;\r
+ exit(0);\r
+ }\r
+ */\r
+ Assert( getUniversalRepresentative( rhs )==rhs );\r
+ Assert( getUniversalRepresentative( lhs )==lhs );\r
+ //make universal quantified formula\r
+ Assert( std::find( d_eq_conjectures[lhs].begin(), d_eq_conjectures[lhs].end(), rhs )==d_eq_conjectures[lhs].end() );\r
+ d_eq_conjectures[lhs].push_back( rhs );\r
+ d_eq_conjectures[rhs].push_back( lhs );\r
+ std::vector< Node > bvs;\r
+ for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[lhs].begin(); it != d_pattern_var_id[lhs].end(); ++it ){\r
+ for( unsigned i=0; i<=it->second; i++ ){\r
+ bvs.push_back( getFreeVar( it->first, i ) );\r
+ }\r
+ }\r
+ Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs );\r
+ Node conj = NodeManager::currentNM()->mkNode( FORALL, bvl, lhs.eqNode( rhs ) );\r
+ conj = Rewriter::rewrite( conj );\r
+ Trace("sg-conjecture-debug") << " formula is : " << conj << std::endl;\r
+ d_waiting_conjectures.push_back( conj );\r
+ }\r
+}\r
+\r
+bool ConjectureGenerator::considerCandidateConjecture( TNode lhs, TNode rhs ) {\r
+ Trace("sg-cconj-debug") << "Consider candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;\r
+ if( lhs==rhs ){\r
+ Trace("sg-cconj-debug") << " -> trivial." << std::endl;\r
+ return false;\r
+ }else{\r
+ if( lhs.getKind()==APPLY_CONSTRUCTOR && rhs.getKind()==APPLY_CONSTRUCTOR ){\r
+ Trace("sg-cconj-debug") << " -> irrelevant by syntactic analysis." << std::endl;\r
+ return false;\r
+ }\r
+ //variables of LHS must subsume variables of RHS\r
+ for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[rhs].begin(); it != d_pattern_var_id[rhs].end(); ++it ){\r
+ std::map< TypeNode, unsigned >::iterator itl = d_pattern_var_id[lhs].find( it->first );\r
+ if( itl!=d_pattern_var_id[lhs].end() ){\r
+ if( itl->second<it->second ){\r
+ Trace("sg-cconj-debug") << " -> variables of sort " << it->first << " are not subsumed." << std::endl;\r
+ return false;\r
+ }else{\r
+ Trace("sg-cconj-debug2") << " variables of sort " << it->first << " are : " << itl->second << " vs " << it->second << std::endl;\r
+ }\r
+ }else{\r
+ Trace("sg-cconj-debug") << " -> has no variables of sort " << it->first << "." << std::endl;\r
+ return false;\r
+ }\r
+ }\r
+ //currently active conjecture?\r
+ std::map< Node, std::vector< Node > >::iterator iteq = d_eq_conjectures.find( lhs );\r
+ if( iteq!=d_eq_conjectures.end() ){\r
+ if( std::find( iteq->second.begin(), iteq->second.end(), rhs )!=iteq->second.end() ){\r
+ Trace("sg-cconj-debug") << " -> already are considering this conjecture." << std::endl;\r
+ return false;\r
+ }\r
+ }\r
+ Trace("sg-cconj") << "Consider possible candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl;\r
+ //find witness for counterexample, if possible\r
+ if( optFilterConfirmation() || optFilterFalsification() ){\r
+ Assert( d_rel_pattern_var_sum.find( lhs )!=d_rel_pattern_var_sum.end() );\r
+ Trace("sg-cconj-debug") << "Notify substitutions over " << d_rel_pattern_var_sum[lhs] << " variables." << std::endl;\r
+ std::map< TNode, TNode > subs;\r
+ d_subs_confirmCount = 0;\r
+ d_subs_confirmWitnessRange.clear();\r
+ d_subs_confirmWitnessDomain.clear();\r
+ if( !d_rel_pattern_subs_index[lhs].notifySubstitutions( this, subs, rhs, d_rel_pattern_var_sum[lhs] ) ){\r
+ Trace("sg-cconj") << " -> found witness that falsifies the conjecture." << std::endl;\r
+ return false;\r
+ }\r
+ if( optFilterConfirmation() ){\r
+ if( d_subs_confirmCount==0 ){\r
+ Trace("sg-cconj") << " -> not confirmed by a ground substitutions." << std::endl;\r
+ return false;\r
+ }\r
+ }\r
+ if( optFilterConfirmationDomain() ){\r
+ for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){\r
+ Assert( d_pattern_fun_id[lhs].find( it->first )!=d_pattern_fun_id[lhs].end() );\r
+ unsigned req = d_pattern_fun_id[lhs][it->first];\r
+ std::map< TNode, unsigned >::iterator itrf = d_pattern_fun_id[rhs].find( it->first );\r
+ if( itrf!=d_pattern_fun_id[rhs].end() ){\r
+ req = itrf->second>req ? itrf->second : req;\r
+ }\r
+ if( it->second.size()<req ){\r
+ Trace("sg-cconj") << " -> did not find at least " << d_pattern_fun_id[lhs][it->first] << " different values in ground substitutions for variable " << it->first << "." << std::endl;\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ Trace("sg-cconj") << " -> SUCCESS." << std::endl;\r
+ if( optFilterConfirmation() || optFilterFalsification() ){\r
+ Trace("sg-cconj") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;\r
+ for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){\r
+ Trace("sg-cconj") << " #witnesses for " << it->first << " : " << it->second.size() << std::endl;\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+}\r
+\r
+\r
+\r
+bool ConjectureGenerator::processCandidateConjecture2( TNode rhs, TypeNode tn, unsigned depth ) {\r
+ for( unsigned j=0; j<d_rel_patterns_at_depth[tn][depth].size(); j++ ){\r
+ if( processCandidateConjecture2( d_rel_patterns_at_depth[tn][depth][j], rhs ) ){\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+}\r
+\r
+bool ConjectureGenerator::processCandidateConjecture2( TNode lhs, TNode rhs ) {\r
+ if( !considerCandidateConjecture( lhs, rhs ) ){\r
+ return false;\r
+ }else{\r
+ Trace("sg-conjecture") << "* Candidate conjecture : " << lhs << " == " << rhs << std::endl;\r
+ Trace("sg-conjecture-debug") << " LHS generalization depth : " << d_gen_depth[lhs] << std::endl;\r
+ if( optFilterConfirmation() || optFilterFalsification() ){\r
+ Trace("sg-conjecture-debug") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl;\r
+ Trace("sg-conjecture-debug") << " #witnesses for ";\r
+ bool firstTime = true;\r
+ for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){\r
+ if( !firstTime ){\r
+ Trace("sg-conjecture-debug") << ", ";\r
+ }\r
+ Trace("sg-conjecture-debug") << it->first << " : " << it->second.size() << "/" << d_pattern_fun_id[lhs][it->first];\r
+ firstTime = false;\r
+ }\r
+ Trace("sg-conjecture-debug") << std::endl;\r
+ }\r
+ if( getUniversalRepresentative( lhs )!=lhs ){\r
+ Trace("ajr-temp") << "bad universal representative : " << lhs << " " << getUniversalRepresentative( lhs ) << std::endl;\r
+ }\r
+ Assert( getUniversalRepresentative( rhs )==rhs );\r
+ Assert( getUniversalRepresentative( lhs )==lhs );\r
+ //make universal quantified formula\r
+ Assert( std::find( d_eq_conjectures[lhs].begin(), d_eq_conjectures[lhs].end(), rhs )==d_eq_conjectures[lhs].end() );\r
+ d_eq_conjectures[lhs].push_back( rhs );\r
+ d_eq_conjectures[rhs].push_back( lhs );\r
+ std::vector< Node > bvs;\r
+ for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[lhs].begin(); it != d_pattern_var_id[lhs].end(); ++it ){\r
+ for( unsigned i=0; i<=it->second; i++ ){\r
+ bvs.push_back( getFreeVar( it->first, i ) );\r
+ }\r
+ }\r
+ Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs );\r
+ Node conj = NodeManager::currentNM()->mkNode( FORALL, bvl, lhs.eqNode( rhs ) );\r
+ conj = Rewriter::rewrite( conj );\r
+ Trace("sg-conjecture-debug") << " formula is : " << conj << std::endl;\r
+ d_waiting_conjectures.push_back( conj );\r
+ return true;\r
+ }\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+bool ConjectureGenerator::notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs ) {\r
+ if( Trace.isOn("sg-cconj-debug") ){\r
+ Trace("sg-cconj-debug") << "Ground eqc for LHS : " << glhs << ", based on substituion: " << std::endl;\r
+ for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+ Assert( getRepresentative( it->second )==it->second );\r
+ Trace("sg-cconj-debug") << " " << it->first << " -> " << it->second << std::endl;\r
+ }\r
+ }\r
+ Trace("sg-cconj-debug") << "Evaluate RHS : : " << rhs << std::endl;\r
+ //get the representative of rhs with substitution subs\r
+ TNode grhs = getTermDatabase()->evaluateTerm( rhs, subs, true );\r
+ Trace("sg-cconj-debug") << "...done evaluating term, got : " << grhs << std::endl;\r
+ if( !grhs.isNull() ){\r
+ if( glhs!=grhs ){\r
+ if( optFilterFalsification() ){\r
+ Trace("sg-cconj-debug") << "Ground eqc for RHS : " << grhs << std::endl;\r
+ //check based on ground terms\r
+ std::map< TNode, Node >::iterator itl = d_ground_eqc_map.find( glhs );\r
+ if( itl!=d_ground_eqc_map.end() ){\r
+ std::map< TNode, Node >::iterator itr = d_ground_eqc_map.find( grhs );\r
+ if( itr!=d_ground_eqc_map.end() ){\r
+ Trace("sg-cconj-debug") << "We have ground terms " << itl->second << " and " << itr->second << "." << std::endl;\r
+ if( itl->second.isConst() && itr->second.isConst() ){\r
+ Trace("sg-cconj-debug") << "...disequal constants." << std::endl;\r
+ Trace("sg-cconj-witness") << " Witness of falsification : " << itl->second << " != " << itr->second << ", substutition is : " << std::endl;\r
+ for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+ Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl;\r
+ }\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ /*\r
+ if( getEqualityEngine()->areDisequal( glhs, grhs, false ) ){\r
+ Trace("sg-cconj-debug") << "..." << glhs << " and " << grhs << " are disequal." << std::endl;\r
+ return false;\r
+ }else{\r
+ Trace("sg-cconj-debug") << "..." << glhs << " and " << grhs << " are not disequal." << std::endl;\r
+ }\r
+ */\r
+ }else{\r
+ Trace("sg-cconj-witness") << " Witnessed " << glhs << " == " << grhs << ", substutition is : " << std::endl;\r
+ for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){\r
+ Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl;\r
+ if( std::find( d_subs_confirmWitnessDomain[it->first].begin(), d_subs_confirmWitnessDomain[it->first].end(), it->second )==d_subs_confirmWitnessDomain[it->first].end() ){\r
+ d_subs_confirmWitnessDomain[it->first].push_back( it->second );\r
+ }\r
+ }\r
+ d_subs_confirmCount++;\r
+ if( std::find( d_subs_confirmWitnessRange.begin(), d_subs_confirmWitnessRange.end(), glhs )==d_subs_confirmWitnessRange.end() ){\r
+ d_subs_confirmWitnessRange.push_back( glhs );\r
+ }\r
+ Trace("sg-cconj-debug") << "RHS is identical." << std::endl;\r
+ }\r
+ }else{\r
+ Trace("sg-cconj-debug") << "(could not ground eqc for RHS)." << std::endl;\r
+ }\r
+ return true;\r
+}\r
+\r
+\r
+void TermGenerator::reset( ConjectureGenerator * s, TypeNode tn ) {\r
+ Assert( d_children.empty() );\r
+ d_typ = tn;\r
+ d_status = 0;\r
+ d_status_num = 0;\r
+ d_children.clear();\r
+ Trace("sg-gen-tg-debug2") << "...add to context " << this << std::endl;\r
+ d_id = s->d_tg_id;\r
+ s->changeContext( true );\r
+}\r
+\r
+bool TermGenerator::getNextTerm( ConjectureGenerator * s, unsigned depth ) {\r
+ if( Trace.isOn("sg-gen-tg-debug2") ){\r
+ Trace("sg-gen-tg-debug2") << this << " getNextTerm depth " << depth << " : status = " << d_status << ", num = " << d_status_num;\r
+ if( d_status==5 ){\r
+ TNode f = s->getTgFunc( d_typ, d_status_num );\r
+ Trace("sg-gen-tg-debug2") << ", f = " << f;\r
+ Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();\r
+ Trace("sg-gen-tg-debug2") << ", childNum = " << d_status_child_num;\r
+ Trace("sg-gen-tg-debug2") << ", #children = " << d_children.size();\r
+ }\r
+ Trace("sg-gen-tg-debug2") << std::endl;\r
+ }\r
+\r
+ if( d_status==0 ){\r
+ d_status++;\r
+ if( !d_typ.isNull() ){\r
+ if( s->allowVar( d_typ ) ){\r
+ //allocate variable\r
+ d_status_num = s->d_var_id[d_typ];\r
+ s->addVar( d_typ );\r
+ Trace("sg-gen-tg-debug2") << this << " ...return unique var #" << d_status_num << std::endl;\r
+ return s->considerCurrentTerm() ? true : getNextTerm( s, depth );\r
+ }else{\r
+ //check allocating new variable\r
+ d_status++;\r
+ d_status_num = -1;\r
+ s->d_tg_gdepth++;\r
+ return getNextTerm( s, depth );\r
+ }\r
+ }else{\r
+ d_status = 4;\r
+ d_status_num = -1;\r
+ return getNextTerm( s, depth );\r
+ }\r
+ }else if( d_status==2 ){\r
+ //cleanup previous information\r
+ //if( d_status_num>=0 ){\r
+ // s->d_var_eq_tg[d_status_num].pop_back();\r
+ //}\r
+ //check if there is another variable\r
+ if( (d_status_num+1)<(int)s->getNumTgVars( d_typ ) ){\r
+ d_status_num++;\r
+ //we have equated two variables\r
+ //s->d_var_eq_tg[d_status_num].push_back( d_id );\r
+ Trace("sg-gen-tg-debug2") << this << "...consider other var #" << d_status_num << std::endl;\r
+ return s->considerCurrentTerm() ? true : getNextTerm( s, depth );\r
+ }else{\r
+ s->d_tg_gdepth--;\r
+ d_status++;\r
+ return getNextTerm( s, depth );\r
+ }\r
+ }else if( d_status==4 ){\r
+ d_status++;\r
+ if( depth>0 && (d_status_num+1)<(int)s->getNumTgFuncs( d_typ ) ){\r
+ d_status_num++;\r
+ d_status_child_num = 0;\r
+ Trace("sg-gen-tg-debug2") << this << "...consider function " << s->getTgFunc( d_typ, d_status_num ) << std::endl;\r
+ s->d_tg_gdepth++;\r
+ if( !s->considerCurrentTerm() ){\r
+ s->d_tg_gdepth--;\r
+ //don't consider this function\r
+ d_status--;\r
+ }else{\r
+ //we have decided on a function application\r
+ }\r
+ return getNextTerm( s, depth );\r
+ }else{\r
+ //do not choose function applications at depth 0\r
+ d_status++;\r
+ return getNextTerm( s, depth );\r
+ }\r
+ }else if( d_status==5 ){\r
+ //iterating over arguments\r
+ TNode f = s->getTgFunc( d_typ, d_status_num );\r
+ if( d_status_child_num<0 ){\r
+ //no more arguments\r
+ s->d_tg_gdepth--;\r
+ d_status--;\r
+ return getNextTerm( s, depth );\r
+ }else if( d_status_child_num==(int)s->d_func_args[f].size() ){\r
+ d_status_child_num--;\r
+ return s->considerTermCanon( d_id ) ? true : getNextTerm( s, depth );\r
+ //return true;\r
+ }else{\r
+ Assert( d_status_child_num<(int)s->d_func_args[f].size() );\r
+ if( d_status_child_num==(int)d_children.size() ){\r
+ d_children.push_back( s->d_tg_id );\r
+ Assert( s->d_tg_alloc.find( s->d_tg_id )==s->d_tg_alloc.end() );\r
+ s->d_tg_alloc[d_children[d_status_child_num]].reset( s, s->d_func_args[f][d_status_child_num] );\r
+ return getNextTerm( s, depth );\r
+ }else{\r
+ Assert( d_status_child_num+1==(int)d_children.size() );\r
+ if( s->d_tg_alloc[d_children[d_status_child_num]].getNextTerm( s, depth-1 ) ){\r
+ d_status_child_num++;\r
+ return getNextTerm( s, depth );\r
+ }else{\r
+ d_children.pop_back();\r
+ d_status_child_num--;\r
+ return getNextTerm( s, depth );\r
+ }\r
+ }\r
+ }\r
+ }else if( d_status==1 || d_status==3 ){\r
+ if( d_status==1 ){\r
+ s->removeVar( d_typ );\r
+ Assert( d_status_num==(int)s->d_var_id[d_typ] );\r
+ //check if there is only one feasible equivalence class. if so, don't make pattern any more specific.\r
+ //unsigned i = s->d_ccand_eqc[0].size()-1;\r
+ //if( s->d_ccand_eqc[0][i].size()==1 && s->d_ccand_eqc[1][i].empty() ){\r
+ // Trace("ajr-temp") << "Apply this!" << std::endl;\r
+ // d_status = 6;\r
+ // return getNextTerm( s, depth );\r
+ //}\r
+ s->d_tg_gdepth++;\r
+ }\r
+ d_status++;\r
+ d_status_num = -1;\r
+ return getNextTerm( s, depth );\r
+ }else{\r
+ //clean up\r
+ Assert( d_children.empty() );\r
+ Trace("sg-gen-tg-debug2") << "...remove from context " << this << std::endl;\r
+ s->changeContext( false );\r
+ Assert( d_id==s->d_tg_id );\r
+ return false;\r
+ }\r
+}\r
+\r
+void TermGenerator::resetMatching( ConjectureGenerator * s, TNode eqc, unsigned mode ) {\r
+ d_match_status = 0;\r
+ d_match_status_child_num = 0;\r
+ d_match_children.clear();\r
+ d_match_children_end.clear();\r
+ d_match_mode = mode;\r
+}\r
+\r
+bool TermGenerator::getNextMatch( ConjectureGenerator * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) {\r
+ if( Trace.isOn("sg-gen-tg-match") ){\r
+ Trace("sg-gen-tg-match") << "Matching ";\r
+ debugPrint( s, "sg-gen-tg-match", "sg-gen-tg-match" );\r
+ Trace("sg-gen-tg-match") << " with eqc e" << s->d_em[eqc] << "..." << std::endl;\r
+ Trace("sg-gen-tg-match") << " mstatus = " << d_match_status;\r
+ if( d_status==5 ){\r
+ TNode f = s->getTgFunc( d_typ, d_status_num );\r
+ Trace("sg-gen-tg-debug2") << ", f = " << f;\r
+ Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size();\r
+ Trace("sg-gen-tg-debug2") << ", mchildNum = " << d_match_status_child_num;\r
+ Trace("sg-gen-tg-debug2") << ", #mchildren = " << d_match_children.size();\r
+ }\r
+ Trace("sg-gen-tg-debug2") << ", current substitution : {";\r
+ for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator itt = subs.begin(); itt != subs.end(); ++itt ){\r
+ for( std::map< unsigned, TNode >::iterator it = itt->second.begin(); it != itt->second.end(); ++it ){\r
+ Trace("sg-gen-tg-debug2") << " " << it->first << " -> e" << s->d_em[it->second];\r
+ }\r
+ }\r
+ Trace("sg-gen-tg-debug2") << " } " << std::endl;\r
+ }\r
+ if( d_status==1 ){\r
+ //a variable\r
+ if( d_match_status==0 ){\r
+ d_match_status++;\r
+ if( d_match_mode>=2 ){\r
+ //only ground terms\r
+ if( !s->isGroundEqc( eqc ) ){\r
+ return false;\r
+ }\r
+ }\r
+ if( d_match_mode%2==1 ){\r
+ std::map< TNode, bool >::iterator it = rev_subs.find( eqc );\r
+ if( it==rev_subs.end() ){\r
+ rev_subs[eqc] = true;\r
+ }else{\r
+ return false;\r
+ }\r
+ }\r
+ Assert( subs[d_typ].find( d_status_num )==subs[d_typ].end() );\r
+ subs[d_typ][d_status_num] = eqc;\r
+ return true;\r
+ }else{\r
+ //clean up\r
+ subs[d_typ].erase( d_status_num );\r
+ if( d_match_mode%2==1 ){\r
+ rev_subs.erase( eqc );\r
+ }\r
+ return false;\r
+ }\r
+ }else if( d_status==2 ){\r
+ if( d_match_status==0 ){\r
+ d_match_status++;\r
+ Assert( d_status_num<(int)s->getNumTgVars( d_typ ) );\r
+ std::map< unsigned, TNode >::iterator it = subs[d_typ].find( d_status_num );\r
+ Assert( it!=subs[d_typ].end() );\r
+ return it->second==eqc;\r
+ }else{\r
+ return false;\r
+ }\r
+ }else if( d_status==5 ){\r
+ //Assert( d_match_children.size()<=d_children.size() );\r
+ //enumerating over f-applications in eqc\r
+ if( d_match_status_child_num<0 ){\r
+ return false;\r
+ }else if( d_match_status==0 ){\r
+ //set up next binding\r
+ if( d_match_status_child_num==(int)d_match_children.size() ){\r
+ if( d_match_status_child_num==0 ){\r
+ //initial binding\r
+ TNode f = s->getTgFunc( d_typ, d_status_num );\r
+ std::map< TNode, TermArgTrie >::iterator it = s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.find( eqc );\r
+ if( it!=s->getTermDatabase()->d_func_map_eqc_trie[f].d_data.end() ){\r
+ d_match_children.push_back( it->second.d_data.begin() );\r
+ d_match_children_end.push_back( it->second.d_data.end() );\r
+ }else{\r
+ d_match_status++;\r
+ d_match_status_child_num--;\r
+ return getNextMatch( s, eqc, subs, rev_subs );\r
+ }\r
+ }else{\r
+ d_match_children.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.begin() );\r
+ d_match_children_end.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.end() );\r
+ }\r
+ }\r
+ d_match_status++;\r
+ Assert( d_match_status_child_num+1==(int)d_match_children.size() );\r
+ if( d_match_children[d_match_status_child_num]==d_match_children_end[d_match_status_child_num] ){\r
+ //no more arguments to bind\r
+ d_match_children.pop_back();\r
+ d_match_children_end.pop_back();\r
+ d_match_status_child_num--;\r
+ return getNextMatch( s, eqc, subs, rev_subs );\r
+ }else{\r
+ if( d_match_status_child_num==(int)d_children.size() ){\r
+ //successfully matched all children\r
+ d_match_children.pop_back();\r
+ d_match_children_end.pop_back();\r
+ d_match_status_child_num--;\r
+ return true;//return d_match_children[d_match_status]!=d_match_children_end[d_match_status];\r
+ }else{\r
+ //do next binding\r
+ s->d_tg_alloc[d_children[d_match_status_child_num]].resetMatching( s, d_match_children[d_match_status_child_num]->first, d_match_mode );\r
+ return getNextMatch( s, eqc, subs, rev_subs );\r
+ }\r
+ }\r
+ }else{\r
+ Assert( d_match_status==1 );\r
+ Assert( d_match_status_child_num+1==(int)d_match_children.size() );\r
+ Assert( d_match_children[d_match_status_child_num]!=d_match_children_end[d_match_status_child_num] );\r
+ d_match_status--;\r
+ if( s->d_tg_alloc[d_children[d_match_status_child_num]].getNextMatch( s, d_match_children[d_match_status_child_num]->first, subs, rev_subs ) ){\r
+ d_match_status_child_num++;\r
+ return getNextMatch( s, eqc, subs, rev_subs );\r
+ }else{\r
+ //iterate\r
+ d_match_children[d_match_status_child_num]++;\r
+ return getNextMatch( s, eqc, subs, rev_subs );\r
+ }\r
+ }\r
+ }\r
+ Assert( false );\r
+ return false;\r
+}\r
+\r
+unsigned TermGenerator::getDepth( ConjectureGenerator * s ) {\r
+ if( d_status==5 ){\r
+ unsigned maxd = 0;\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ unsigned d = s->d_tg_alloc[d_children[i]].getDepth( s );\r
+ if( d>maxd ){\r
+ maxd = d;\r
+ }\r
+ }\r
+ return 1+maxd;\r
+ }else{\r
+ return 0;\r
+ }\r
+}\r
+\r
+unsigned TermGenerator::getGeneralizationDepth( ConjectureGenerator * s ) {\r
+ if( d_status==5 ){\r
+ unsigned sum = 1;\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ sum += s->d_tg_alloc[d_children[i]].getGeneralizationDepth( s );\r
+ }\r
+ return sum;\r
+ }else if( d_status==2 ){\r
+ return 1;\r
+ }else{\r
+ Assert( d_status==1 );\r
+ return 0;\r
+ }\r
+}\r
+\r
+Node TermGenerator::getTerm( ConjectureGenerator * s ) {\r
+ if( d_status==1 || d_status==2 ){\r
+ Assert( !d_typ.isNull() );\r
+ return s->getFreeVar( d_typ, d_status_num );\r
+ }else if( d_status==5 ){\r
+ Node f = s->getTgFunc( d_typ, d_status_num );\r
+ if( d_children.size()==s->d_func_args[f].size() ){\r
+ std::vector< Node > children;\r
+ children.push_back( f );\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ Node nc = s->d_tg_alloc[d_children[i]].getTerm( s );\r
+ if( nc.isNull() ){\r
+ return Node::null();\r
+ }else{\r
+ //Assert( nc.getType()==s->d_func_args[f][i] );\r
+ children.push_back( nc );\r
+ }\r
+ }\r
+ return NodeManager::currentNM()->mkNode( s->d_func_kind[f], children );\r
+ }\r
+ }else{\r
+ Assert( false );\r
+ }\r
+ return Node::null();\r
+}\r
+\r
+/*\r
+int TermGenerator::getActiveChild( ConjectureGenerator * s ) {\r
+ if( d_status==1 || d_status==2 ){\r
+ return d_id;\r
+ }else if( d_status==5 ){\r
+ Node f = s->getTgFunc( d_typ, d_status_num );\r
+ int i = d_children.size()-1;\r
+ if( d_children.size()==s->d_func_args[f].size() ){\r
+ if( d_children.empty() ){\r
+ return d_id;\r
+ }else{\r
+ int cac = s->d_tg_alloc[d_children[i]].getActiveChild( s );\r
+ return cac==(int)d_children[i] ? d_id : cac;\r
+ }\r
+ }else if( !d_children.empty() ){\r
+ return s->d_tg_alloc[d_children[i]].getActiveChild( s );\r
+ }\r
+ }else{\r
+ Assert( false );\r
+ }\r
+ return -1;\r
+}\r
+*/\r
+\r
+void TermGenerator::debugPrint( ConjectureGenerator * s, const char * c, const char * cd ) {\r
+ Trace(cd) << "[*" << d_id << "," << d_status << "]:";\r
+ if( d_status==1 || d_status==2 ){\r
+ Trace(c) << s->getFreeVar( d_typ, d_status_num );\r
+ }else if( d_status==5 ){\r
+ TNode f = s->getTgFunc( d_typ, d_status_num );\r
+ Trace(c) << "(" << f;\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ Trace(c) << " ";\r
+ s->d_tg_alloc[d_children[i]].debugPrint( s, c, cd );\r
+ }\r
+ if( d_children.size()<s->d_func_args[f].size() ){\r
+ Trace(c) << " ...";\r
+ }\r
+ Trace(c) << ")";\r
+ }else{\r
+ Trace(c) << "???";\r
+ }\r
+}\r
+\r
+\r
+void SubstitutionIndex::addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i ) {\r
+ if( i==vars.size() ){\r
+ d_var = eqc;\r
+ }else{\r
+ Assert( d_var.isNull() || d_var==vars[i] );\r
+ d_var = vars[i];\r
+ d_children[terms[i]].addSubstitution( eqc, vars, terms, i+1 );\r
+ }\r
+}\r
+\r
+bool SubstitutionIndex::notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i ) {\r
+ if( i==numVars ){\r
+ Assert( d_children.empty() );\r
+ return s->notifySubstitution( d_var, subs, rhs );\r
+ }else{\r
+ Assert( i==0 || !d_children.empty() );\r
+ for( std::map< TNode, SubstitutionIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){\r
+ Trace("sg-cconj-debug2") << "Try " << d_var << " -> " << it->first << " (" << i << "/" << numVars << ")" << std::endl;\r
+ subs[d_var] = it->first;\r
+ if( !it->second.notifySubstitutions( s, subs, rhs, numVars, i+1 ) ){\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+}\r
+\r
+\r
+void TheoremIndex::addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){\r
+ if( lhs_v.empty() ){\r
+ if( std::find( d_terms.begin(), d_terms.end(), rhs )==d_terms.end() ){\r
+ d_terms.push_back( rhs );\r
+ }\r
+ }else{\r
+ unsigned index = lhs_v.size()-1;\r
+ if( lhs_arg[index]==lhs_v[index].getNumChildren() ){\r
+ lhs_v.pop_back();\r
+ lhs_arg.pop_back();\r
+ addTheorem( lhs_v, lhs_arg, rhs );\r
+ }else{\r
+ lhs_arg[index]++;\r
+ addTheoremNode( lhs_v[index][lhs_arg[index]-1], lhs_v, lhs_arg, rhs );\r
+ }\r
+ }\r
+}\r
+\r
+void TheoremIndex::addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){\r
+ Trace("thm-db-debug") << "Adding conjecture for subterm " << curr << "..." << std::endl;\r
+ if( curr.hasOperator() ){\r
+ lhs_v.push_back( curr );\r
+ lhs_arg.push_back( 0 );\r
+ d_children[curr.getOperator()].addTheorem( lhs_v, lhs_arg, rhs );\r
+ }else{\r
+ Assert( curr.getKind()==kind::BOUND_VARIABLE );\r
+ Assert( d_var.isNull() || d_var==curr );\r
+ d_var = curr;\r
+ d_children[curr].addTheorem( lhs_v, lhs_arg, rhs );\r
+ }\r
+}\r
+\r
+void TheoremIndex::getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,\r
+ std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,\r
+ std::vector< Node >& terms ) {\r
+ Trace("thm-db-debug") << "Get equivalent terms " << n_v.size() << " " << n_arg.size() << std::endl;\r
+ if( n_v.empty() ){\r
+ Trace("thm-db-debug") << "Number of terms : " << d_terms.size() << std::endl;\r
+ //apply substutitions to RHS's\r
+ for( unsigned i=0; i<d_terms.size(); i++ ){\r
+ Node n = d_terms[i].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );\r
+ terms.push_back( n );\r
+ }\r
+ }else{\r
+ unsigned index = n_v.size()-1;\r
+ if( n_arg[index]==n_v[index].getNumChildren() ){\r
+ n_v.pop_back();\r
+ n_arg.pop_back();\r
+ getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );\r
+ }else{\r
+ n_arg[index]++;\r
+ getEquivalentTermsNode( n_v[index][n_arg[index]-1], n_v, n_arg, smap, vars, subs, terms );\r
+ }\r
+ }\r
+}\r
+\r
+void TheoremIndex::getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg,\r
+ std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs,\r
+ std::vector< Node >& terms ) {\r
+ Trace("thm-db-debug") << "Get equivalent based on subterm " << curr << "..." << std::endl;\r
+ if( curr.hasOperator() ){\r
+ Trace("thm-db-debug") << "Check based on operator..." << std::endl;\r
+ std::map< TNode, TheoremIndex >::iterator it = d_children.find( curr.getOperator() );\r
+ if( it!=d_children.end() ){\r
+ n_v.push_back( curr );\r
+ n_arg.push_back( 0 );\r
+ it->second.getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );\r
+ }\r
+ Trace("thm-db-debug") << "...done check based on operator" << std::endl;\r
+ }\r
+ if( !d_var.isNull() ){\r
+ Trace("thm-db-debug") << "Check for substitution with " << d_var << "..." << std::endl;\r
+ if( curr.getType()==d_var.getType() ){\r
+ //add to substitution if possible\r
+ bool success = false;\r
+ std::map< TNode, TNode >::iterator it = smap.find( d_var );\r
+ if( it==smap.end() ){\r
+ smap[d_var] = curr;\r
+ vars.push_back( d_var );\r
+ subs.push_back( curr );\r
+ success = true;\r
+ }else if( it->second==curr ){\r
+ success = true;\r
+ }else{\r
+ //also check modulo equality (in universal equality engine)\r
+ }\r
+ Trace("thm-db-debug") << "...check for substitution with " << d_var << ", success = " << success << "." << std::endl;\r
+ if( success ){\r
+ d_children[d_var].getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms );\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void TheoremIndex::debugPrint( const char * c, unsigned ind ) {\r
+ for( std::map< TNode, TheoremIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){\r
+ for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }\r
+ Trace(c) << it->first << std::endl;\r
+ it->second.debugPrint( c, ind+1 );\r
+ }\r
+ if( !d_terms.empty() ){\r
+ for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }\r
+ Trace(c) << "{";\r
+ for( unsigned i=0; i<d_terms.size(); i++ ){\r
+ Trace(c) << " " << d_terms[i];\r
+ }\r
+ Trace(c) << " }" << std::endl;\r
+ }\r
+ //if( !d_var.isNull() ){\r
+ // for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; }\r
+ // Trace(c) << "var:" << d_var << std::endl;\r
+ //}\r
+}\r
+\r
+bool ConjectureGenerator::optReqDistinctVarPatterns() { return false; }\r
+bool ConjectureGenerator::optFilterFalsification() { return true; }\r
+bool ConjectureGenerator::optFilterConfirmation() { return true; }\r
+bool ConjectureGenerator::optFilterConfirmationDomain() { return true; }\r
+bool ConjectureGenerator::optFilterConfirmationOnlyGround() { return true; }//false; }\r
+bool ConjectureGenerator::optWaitForFullCheck() { return true; }\r
+unsigned ConjectureGenerator::optFullCheckFrequency() { return 1; }\r
+unsigned ConjectureGenerator::optFullCheckConjectures() { return 1; }\r
+\r
+\r
+}\r
+\r
+\r
-/********************* */
-/*! \file quant_conflict_find.cpp
- ** \verbatim
- ** Original author: Andrew Reynolds
- ** Major contributors: Morgan Deters
- ** Minor contributors (to current version): none
- ** This file is part of the CVC4 project.
- ** Copyright (c) 2009-2014 New York University and The University of Iowa
- ** See the file COPYING in the top-level source directory for licensing
- ** information.\endverbatim
- **
- ** \brief quant conflict find class
- **
- **/
-
-#include <vector>
-
-#include "theory/quantifiers/quant_conflict_find.h"
-#include "theory/quantifiers/quant_util.h"
-#include "theory/theory_engine.h"
-#include "theory/quantifiers/options.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/quantifiers/trigger.h"
-
-using namespace CVC4;
-using namespace CVC4::kind;
-using namespace CVC4::theory;
-using namespace CVC4::theory::quantifiers;
-using namespace std;
-
-namespace CVC4 {
-
-Node QcfNodeIndex::existsTerm( TNode n, std::vector< TNode >& reps, int index ) {
- if( index==(int)reps.size() ){
- if( d_children.empty() ){
- return Node::null();
- }else{
- return d_children.begin()->first;
- }
- }else{
- std::map< TNode, QcfNodeIndex >::iterator it = d_children.find( reps[index] );
- if( it==d_children.end() ){
- return Node::null();
- }else{
- return it->second.existsTerm( n, reps, index+1 );
- }
- }
-}
-
-Node QcfNodeIndex::addTerm( TNode n, std::vector< TNode >& reps, int index ) {
- if( index==(int)reps.size() ){
- if( d_children.empty() ){
- d_children[ n ].clear();
- return n;
- }else{
- return d_children.begin()->first;
- }
- }else{
- return d_children[reps[index]].addTerm( n, reps, index+1 );
- }
-}
-
-
-void QcfNodeIndex::debugPrint( const char * c, int t ) {
- for( std::map< TNode, QcfNodeIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){
- if( !it->first.isNull() ){
- for( int j=0; j<t; j++ ){ Trace(c) << " "; }
- Trace(c) << it->first << " : " << std::endl;
- it->second.debugPrint( c, t+1 );
- }
- }
-}
-
-
-void QuantInfo::initialize( Node q, Node qn ) {
- d_q = q;
- for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
- d_match.push_back( TNode::null() );
- d_match_term.push_back( TNode::null() );
- }
-
- //register the variables
- for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
- d_var_num[q[0][i]] = i;
- d_vars.push_back( q[0][i] );
- }
-
- registerNode( qn, true, true );
-
-
- Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;
- d_mg = new MatchGen( this, qn );
-
- if( d_mg->isValid() ){
- /*
- for( unsigned j=0; j<q[0].getNumChildren(); j++ ){
- if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){
- Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;
- d_mg->setInvalid();
- break;
- }
- }
- */
- if( d_mg->isValid() ){
- for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){
- if( d_vars[j].getKind()!=BOUND_VARIABLE ){
- d_var_mg[j] = NULL;
- bool is_tsym = false;
- if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){
- is_tsym = true;
- d_tsym_vars.push_back( j );
- }
- if( !is_tsym || options::qcfTConstraint() ){
- d_var_mg[j] = new MatchGen( this, d_vars[j], true );
- }
- if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){
- Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;
- d_mg->setInvalid();
- break;
- }else{
- std::vector< int > bvars;
- d_var_mg[j]->determineVariableOrder( this, bvars );
- }
- }
- }
- if( d_mg->isValid() ){
- std::vector< int > bvars;
- d_mg->determineVariableOrder( this, bvars );
- }
- }
- }else{
- Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;
- }
- Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;
-}
-
-void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {
- Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;
- if( n.getKind()==FORALL ){
- registerNode( n[1], hasPol, pol, true );
- }else{
- if( !MatchGen::isHandledBoolConnective( n ) ){
- if( n.hasBoundVar() ){
- //literals
- if( n.getKind()==EQUAL ){
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- flatten( n[i], beneathQuant );
- }
- }else if( MatchGen::isHandledUfTerm( n ) ){
- flatten( n, beneathQuant );
- }else if( n.getKind()==ITE ){
- for( unsigned i=1; i<=2; i++ ){
- flatten( n[i], beneathQuant );
- }
- registerNode( n[0], false, pol, beneathQuant );
- }else if( options::qcfTConstraint() ){
- //a theory-specific predicate
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- flatten( n[i], beneathQuant );
- }
- }
- }
- }else{
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- bool newHasPol;
- bool newPol;
- QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );
- //QcfNode * qcfc = new QcfNode( d_c );
- //qcfc->d_parent = qcf;
- //qcf->d_child[i] = qcfc;
- registerNode( n[i], newHasPol, newPol, beneathQuant );
- }
- }
- }
-}
-
-void QuantInfo::flatten( Node n, bool beneathQuant ) {
- Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;
- if( n.hasBoundVar() ){
- if( n.getKind()==BOUND_VARIABLE ){
- d_inMatchConstraint[n] = true;
- }
- //if( MatchGen::isHandledUfTerm( n ) || n.getKind()==ITE ){
- if( d_var_num.find( n )==d_var_num.end() ){
- Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;
- d_var_num[n] = d_vars.size();
- d_vars.push_back( n );
- d_match.push_back( TNode::null() );
- d_match_term.push_back( TNode::null() );
- if( n.getKind()==ITE ){
- registerNode( n, false, false );
- }else{
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- flatten( n[i], beneathQuant );
- }
- }
- }else{
- Trace("qcf-qregister-debug2") << "...already processed" << std::endl;
- }
- }else{
- Trace("qcf-qregister-debug2") << "...is ground." << std::endl;
- }
-}
-
-
-void QuantInfo::reset_round( QuantConflictFind * p ) {
- for( unsigned i=0; i<d_match.size(); i++ ){
- d_match[i] = TNode::null();
- d_match_term[i] = TNode::null();
- }
- d_curr_var_deq.clear();
- d_tconstraints.clear();
- //add built-in variable constraints
- for( unsigned r=0; r<2; r++ ){
- for( std::map< int, std::vector< Node > >::iterator it = d_var_constraint[r].begin();
- it != d_var_constraint[r].end(); ++it ){
- for( unsigned j=0; j<it->second.size(); j++ ){
- Node rr = it->second[j];
- if( !isVar( rr ) ){
- rr = p->getRepresentative( rr );
- }
- if( addConstraint( p, it->first, rr, r==0 )==-1 ){
- d_var_constraint[0].clear();
- d_var_constraint[1].clear();
- //quantified formula is actually equivalent to true
- Trace("qcf-qregister") << "Quantifier is equivalent to true!!!" << std::endl;
- d_mg->d_children.clear();
- d_mg->d_n = NodeManager::currentNM()->mkConst( true );
- d_mg->d_type = MatchGen::typ_ground;
- return;
- }
- }
- }
- }
- d_mg->reset_round( p );
- for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){
- it->second->reset_round( p );
- }
- //now, reset for matching
- d_mg->reset( p, false, this );
-}
-
-int QuantInfo::getCurrentRepVar( int v ) {
- if( v!=-1 && !d_match[v].isNull() ){
- int vn = getVarNum( d_match[v] );
- if( vn!=-1 ){
- //int vr = getCurrentRepVar( vn );
- //d_match[v] = d_vars[vr];
- //return vr;
- return getCurrentRepVar( vn );
- }
- }
- return v;
-}
-
-TNode QuantInfo::getCurrentValue( TNode n ) {
- int v = getVarNum( n );
- if( v==-1 ){
- return n;
- }else{
- if( d_match[v].isNull() ){
- return n;
- }else{
- Assert( getVarNum( d_match[v] )!=v );
- return getCurrentValue( d_match[v] );
- }
- }
-}
-
-TNode QuantInfo::getCurrentExpValue( TNode n ) {
- int v = getVarNum( n );
- if( v==-1 ){
- return n;
- }else{
- if( d_match[v].isNull() ){
- return n;
- }else{
- Assert( getVarNum( d_match[v] )!=v );
- if( d_match_term[v].isNull() ){
- return getCurrentValue( d_match[v] );
- }else{
- return d_match_term[v];
- }
- }
- }
-}
-
-bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {
- //check disequalities
- std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
- if( itd!=d_curr_var_deq.end() ){
- for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
- Node cv = getCurrentValue( it->first );
- Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;
- if( cv==n ){
- return false;
- }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){
- //they must actually be disequal if we are looking for conflicts
- if( !p->areDisequal( n, cv ) ){
- //TODO : check for entailed disequal
-
- return false;
- }
- }
- }
- }
- return true;
-}
-
-int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {
- v = getCurrentRepVar( v );
- int vn = getVarNum( n );
- vn = vn==-1 ? -1 : getCurrentRepVar( vn );
- n = getCurrentValue( n );
- return addConstraint( p, v, n, vn, polarity, false );
-}
-
-int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {
- //for handling equalities between variables, and disequalities involving variables
- Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";
- Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;
- Assert( doRemove || n==getCurrentValue( n ) );
- Assert( doRemove || v==getCurrentRepVar( v ) );
- Assert( doRemove || vn==getCurrentRepVar( getVarNum( n ) ) );
- if( polarity ){
- if( vn!=v ){
- if( doRemove ){
- if( vn!=-1 ){
- //if set to this in the opposite direction, clean up opposite instead
- // std::map< int, TNode >::iterator itmn = d_match.find( vn );
- if( d_match[vn]==d_vars[v] ){
- return addConstraint( p, vn, d_vars[v], v, true, true );
- }else{
- //unsetting variables equal
- std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );
- if( itd!=d_curr_var_deq.end() ){
- //remove disequalities owned by this
- std::vector< TNode > remDeq;
- for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
- if( it->second==v ){
- remDeq.push_back( it->first );
- }
- }
- for( unsigned i=0; i<remDeq.size(); i++ ){
- d_curr_var_deq[vn].erase( remDeq[i] );
- }
- }
- }
- }
- d_match[v] = TNode::null();
- return 1;
- }else{
- //std::map< int, TNode >::iterator itm = d_match.find( v );
-
- if( vn!=-1 ){
- Debug("qcf-match-debug") << " ...Variable bound to variable" << std::endl;
- //std::map< int, TNode >::iterator itmn = d_match.find( vn );
- if( d_match[v].isNull() ){
- //setting variables equal
- bool alreadySet = false;
- if( !d_match[vn].isNull() ){
- alreadySet = true;
- Assert( !isVar( d_match[vn] ) );
- }
-
- //copy or check disequalities
- std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );
- if( itd!=d_curr_var_deq.end() ){
- for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){
- Node dv = getCurrentValue( it->first );
- if( !alreadySet ){
- if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){
- d_curr_var_deq[vn][dv] = v;
- }
- }else{
- if( !p->areMatchDisequal( d_match[vn], dv ) ){
- Debug("qcf-match-debug") << " -> fail, conflicting disequality" << std::endl;
- return -1;
- }
- }
- }
- }
- if( alreadySet ){
- n = getCurrentValue( n );
- }
- }else{
- if( d_match[vn].isNull() ){
- Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;
- //set the opposite direction
- return addConstraint( p, vn, d_vars[v], v, true, false );
- }else{
- Debug("qcf-match-debug") << " -> Both variables bound, compare" << std::endl;
- //are they currently equal
- return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;
- }
- }
- }else{
- Debug("qcf-match-debug") << " ...Variable bound to ground" << std::endl;
- if( d_match[v].isNull() ){
- }else{
- //compare ground values
- Debug("qcf-match-debug") << " -> Ground value, compare " << d_match[v] << " "<< n << std::endl;
- return p->areMatchEqual( d_match[v], n ) ? 0 : -1;
- }
- }
- if( setMatch( p, v, n ) ){
- Debug("qcf-match-debug") << " -> success" << std::endl;
- return 1;
- }else{
- Debug("qcf-match-debug") << " -> fail, conflicting disequality" << std::endl;
- return -1;
- }
- }
- }else{
- Debug("qcf-match-debug") << " -> redundant, variable identity" << std::endl;
- return 0;
- }
- }else{
- if( vn==v ){
- Debug("qcf-match-debug") << " -> fail, variable identity" << std::endl;
- return -1;
- }else{
- if( doRemove ){
- Assert( d_curr_var_deq[v].find( n )!=d_curr_var_deq[v].end() );
- d_curr_var_deq[v].erase( n );
- return 1;
- }else{
- if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){
- //check if it respects equality
- //std::map< int, TNode >::iterator itm = d_match.find( v );
- if( !d_match[v].isNull() ){
- TNode nv = getCurrentValue( n );
- if( !p->areMatchDisequal( nv, d_match[v] ) ){
- Debug("qcf-match-debug") << " -> fail, conflicting disequality" << std::endl;
- return -1;
- }
- }
- d_curr_var_deq[v][n] = v;
- Debug("qcf-match-debug") << " -> success" << std::endl;
- return 1;
- }else{
- Debug("qcf-match-debug") << " -> redundant disequality" << std::endl;
- return 0;
- }
- }
- }
- }
-}
-
-bool QuantInfo::isConstrainedVar( int v ) {
- if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){
- return true;
- }else{
- Node vv = getVar( v );
- //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){
- for( unsigned i=0; i<d_match.size(); i++ ){
- if( d_match[i]==vv ){
- return true;
- }
- }
- for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){
- for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- if( it2->first==vv ){
- return true;
- }
- }
- }
- return false;
- }
-}
-
-bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n ) {
- if( getCurrentCanBeEqual( p, v, n ) ){
- Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " << d_curr_var_deq[v].size() << " disequalities" << std::endl;
- d_match[v] = n;
- return true;
- }else{
- return false;
- }
-}
-
-bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {
- for( int i=0; i<getNumVars(); i++ ){
- //std::map< int, TNode >::iterator it = d_match.find( i );
- if( !d_match[i].isNull() ){
- if( !getCurrentCanBeEqual( p, i, d_match[i], p->d_effort==QuantConflictFind::effort_conflict ) ){
- return true;
- }
- }
- }
- return false;
-}
-
-bool QuantInfo::isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms ) {
- if( !d_tconstraints.empty() ){
- //check constraints
- for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
- //apply substitution to the tconstraint
- Node cons = it->first.substitute( p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].begin(),
- p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].end(),
- terms.begin(), terms.end() );
- cons = it->second ? cons : cons.negate();
- if( !entailmentTest( p, cons, p->d_effort==QuantConflictFind::effort_conflict ) ){
- return true;
- }
- }
- }
- return false;
-}
-
-bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {
- Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;
- Node rew = Rewriter::rewrite( lit );
- if( rew==p->d_false ){
- Trace("qcf-tconstraint-debug") << "...constraint " << lit << " is disentailed (rewrites to false)." << std::endl;
- return false;
- }else if( rew!=p->d_true ){
- //if checking for conflicts, we must be sure that the constraint is entailed
- if( chEnt ){
- //check if it is entailed
- Trace("qcf-tconstraint-debug") << "Check entailment of " << rew << "..." << std::endl;
- std::pair<bool, Node> et = p->getQuantifiersEngine()->getTheoryEngine()->entailmentCheck(THEORY_OF_TYPE_BASED, rew );
- ++(p->d_statistics.d_entailment_checks);
- Trace("qcf-tconstraint-debug") << "ET result : " << et.first << " " << et.second << std::endl;
- if( !et.first ){
- Trace("qcf-tconstraint-debug") << "...cannot show entailment of " << rew << "." << std::endl;
- return false;
- }else{
- return true;
- }
- }else{
- Trace("qcf-tconstraint-debug") << "...does not need to be entailed." << std::endl;
- return true;
- }
- }else{
- Trace("qcf-tconstraint-debug") << "...rewrites to true." << std::endl;
- return true;
- }
-}
-
-bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {
- //assign values for variables that were unassigned (usually not necessary, but handles corner cases)
- bool doFail = false;
- bool success = true;
- if( doContinue ){
- doFail = true;
- success = false;
- }else{
- //solve for interpreted symbol matches
- // this breaks the invariant that all introduced constraints are over existing terms
- for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){
- int index = d_tsym_vars[i];
- TNode v = getCurrentValue( d_vars[index] );
- int slv_v = -1;
- if( v==d_vars[index] ){
- slv_v = index;
- }
- Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;
- if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){
- Kind k = d_vars[index].getKind();
- std::vector< TNode > children;
- for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){
- int vn = getVarNum( d_vars[index][j] );
- if( vn!=-1 ){
- TNode vv = getCurrentValue( d_vars[index][j] );
- if( vv==d_vars[index][j] ){
- //we will assign this
- if( slv_v==-1 ){
- Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;
- slv_v = vn;
- if( p->d_effort!=QuantConflictFind::effort_conflict ){
- break;
- }
- }else{
- Node z = p->getZero( k );
- if( !z.isNull() ){
- Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;
- assigned.push_back( vn );
- if( !setMatch( p, vn, z ) ){
- success = false;
- break;
- }
- }
- }
- }else{
- Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;
- children.push_back( vv );
- }
- }else{
- Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;
- children.push_back( d_vars[index][j] );
- }
- }
- if( success ){
- if( slv_v!=-1 ){
- Node lhs;
- if( children.empty() ){
- lhs = p->getZero( k );
- }else if( children.size()==1 ){
- lhs = children[0];
- }else{
- lhs = NodeManager::currentNM()->mkNode( k, children );
- }
- Node sum;
- if( v==d_vars[index] ){
- sum = lhs;
- }else{
- if( p->d_effort==QuantConflictFind::effort_conflict ){
- Kind kn = k;
- if( d_vars[index].getKind()==PLUS ){
- kn = MINUS;
- }
- if( kn!=k ){
- sum = NodeManager::currentNM()->mkNode( kn, v, lhs );
- }
- }
- }
- if( !sum.isNull() ){
- assigned.push_back( slv_v );
- Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;
- if( !setMatch( p, slv_v, sum ) ){
- success = false;
- }
- p->d_tempCache.push_back( sum );
- }
- }else{
- //must show that constraint is met
- Node sum = NodeManager::currentNM()->mkNode( k, children );
- Node eq = sum.eqNode( v );
- if( !entailmentTest( p, eq ) ){
- success = false;
- }
- p->d_tempCache.push_back( sum );
- }
- }
- }
-
- if( !success ){
- break;
- }
- }
- if( success ){
- //check what is left to assign
- d_unassigned.clear();
- d_unassigned_tn.clear();
- std::vector< int > unassigned[2];
- std::vector< TypeNode > unassigned_tn[2];
- for( int i=0; i<getNumVars(); i++ ){
- if( d_match[i].isNull() ){
- int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;
- unassigned[rindex].push_back( i );
- unassigned_tn[rindex].push_back( getVar( i ).getType() );
- assigned.push_back( i );
- }
- }
- d_unassigned_nvar = unassigned[0].size();
- for( unsigned i=0; i<2; i++ ){
- d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );
- d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );
- }
- d_una_eqc_count.clear();
- d_una_index = 0;
- }
- }
-
- if( !d_unassigned.empty() && ( success || doContinue ) ){
- Trace("qcf-check") << "Assign to unassigned..." << std::endl;
- do {
- if( doFail ){
- Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;
- }
- bool invalidMatch = false;
- while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){
- invalidMatch = false;
- if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){
- //check if it has now been assigned
- if( d_una_index<d_unassigned_nvar ){
- if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
- d_una_eqc_count.push_back( -1 );
- }else{
- d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );
- d_una_eqc_count.push_back( 0 );
- }
- }else{
- d_una_eqc_count.push_back( 0 );
- }
- }else{
- bool failed = false;
- if( !doFail ){
- if( d_una_index<d_unassigned_nvar ){
- if( !isConstrainedVar( d_unassigned[d_una_index] ) ){
- Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;
- d_una_index++;
- }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){
- Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;
- d_una_index++;
- }else{
- failed = true;
- Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;
- }
- }else{
- Assert( doFail || d_una_index==(int)d_una_eqc_count.size()-1 );
- if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){
- int currIndex = d_una_eqc_count[d_una_index];
- d_una_eqc_count[d_una_index]++;
- Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;
- if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] ) ){
- d_match_term[d_unassigned[d_una_index]] = TNode::null();
- Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;
- d_una_index++;
- }else{
- Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;
- invalidMatch = true;
- }
- }else{
- failed = true;
- Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;
- }
- }
- }
- if( doFail || failed ){
- do{
- if( !doFail ){
- d_una_eqc_count.pop_back();
- }else{
- doFail = false;
- }
- d_una_index--;
- }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );
- }
- }
- }
- success = d_una_index>=0;
- if( success ){
- doFail = true;
- Trace("qcf-check-unassign") << " Try: " << std::endl;
- for( unsigned i=0; i<d_unassigned.size(); i++ ){
- int ui = d_unassigned[i];
- if( !d_match[ui].isNull() ){
- Trace("qcf-check-unassign") << " Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
- }
- }
- }
- }while( success && isMatchSpurious( p ) );
- }
- if( success ){
- for( unsigned i=0; i<d_unassigned.size(); i++ ){
- int ui = d_unassigned[i];
- if( !d_match[ui].isNull() ){
- Trace("qcf-check") << " Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;
- }
- }
- return true;
- }else{
- for( unsigned i=0; i<assigned.size(); i++ ){
- d_match[ assigned[i] ] = TNode::null();
- }
- assigned.clear();
- return false;
- }
-}
-
-void QuantInfo::getMatch( std::vector< Node >& terms ){
- for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){
- //Node cv = qi->getCurrentValue( qi->d_match[i] );
- int repVar = getCurrentRepVar( i );
- Node cv;
- //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );
- if( !d_match_term[repVar].isNull() ){
- cv = d_match_term[repVar];
- }else{
- cv = d_match[repVar];
- }
- Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;
- terms.push_back( cv );
- }
-}
-
-void QuantInfo::revertMatch( std::vector< int >& assigned ) {
- for( unsigned i=0; i<assigned.size(); i++ ){
- d_match[ assigned[i] ] = TNode::null();
- }
-}
-
-void QuantInfo::debugPrintMatch( const char * c ) {
- for( int i=0; i<getNumVars(); i++ ){
- Trace(c) << " " << d_vars[i] << " -> ";
- if( !d_match[i].isNull() ){
- Trace(c) << d_match[i];
- }else{
- Trace(c) << "(unassigned) ";
- }
- if( !d_curr_var_deq[i].empty() ){
- Trace(c) << ", DEQ{ ";
- for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){
- Trace(c) << it->first << " ";
- }
- Trace(c) << "}";
- }
- if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){
- Trace(c) << ", EXP : " << d_match_term[i];
- }
- Trace(c) << std::endl;
- }
- if( !d_tconstraints.empty() ){
- Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;
- for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){
- Trace(c) << " " << it->first << " -> " << it->second << std::endl;
- }
- }
-}
-
-MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar ){
- Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;
- std::vector< Node > qni_apps;
- d_qni_size = 0;
- if( isVar ){
- Assert( qi->d_var_num.find( n )!=qi->d_var_num.end() );
- if( n.getKind()==ITE ){
- d_type = typ_ite_var;
- d_type_not = false;
- d_n = n;
- d_children.push_back( MatchGen( qi, d_n[0] ) );
- if( d_children[0].isValid() ){
- d_type = typ_ite_var;
- for( unsigned i=1; i<=2; i++ ){
- Node nn = n.eqNode( n[i] );
- d_children.push_back( MatchGen( qi, nn ) );
- d_children[d_children.size()-1].d_qni_bound_except.push_back( 0 );
- if( !d_children[d_children.size()-1].isValid() ){
- setInvalid();
- break;
- }
- }
- }else{
- d_type = typ_invalid;
- }
- }else{
- d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;
- d_qni_var_num[0] = qi->getVarNum( n );
- d_qni_size++;
- d_type_not = false;
- d_n = n;
- //Node f = getOperator( n );
- for( unsigned j=0; j<d_n.getNumChildren(); j++ ){
- Node nn = d_n[j];
- Trace("qcf-qregister-debug") << " " << d_qni_size;
- if( qi->isVar( nn ) ){
- int v = qi->d_var_num[nn];
- Trace("qcf-qregister-debug") << " is var #" << v << std::endl;
- d_qni_var_num[d_qni_size] = v;
- //qi->addFuncParent( v, f, j );
- }else{
- Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;
- d_qni_gterm[d_qni_size] = nn;
- }
- d_qni_size++;
- }
- }
- }else{
- if( n.hasBoundVar() ){
- d_type_not = false;
- d_n = n;
- if( d_n.getKind()==NOT ){
- d_n = d_n[0];
- d_type_not = !d_type_not;
- }
-
- if( isHandledBoolConnective( d_n ) ){
- //non-literals
- d_type = typ_formula;
- for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
- if( d_n.getKind()!=FORALL || i==1 ){
- d_children.push_back( MatchGen( qi, d_n[i], false ) );
- if( !d_children[d_children.size()-1].isValid() ){
- setInvalid();
- break;
- }
- }
- /*
- else if( isTop && n.getKind()==OR && d_children[d_children.size()-1].d_type==typ_var_eq ){
- Trace("qcf-qregister-debug") << "Remove child, make built-in constraint" << std::endl;
- //if variable equality/disequality at top level, remove immediately
- bool cIsNot = d_children[d_children.size()-1].d_type_not;
- Node cn = d_children[d_children.size()-1].d_n;
- Assert( cn.getKind()==EQUAL );
- Assert( p->d_qinfo[q].isVar( cn[0] ) || p->d_qinfo[q].isVar( cn[1] ) );
- //make it a built-in constraint instead
- for( unsigned i=0; i<2; i++ ){
- if( p->d_qinfo[q].isVar( cn[i] ) ){
- int v = p->d_qinfo[q].getVarNum( cn[i] );
- Node cno = cn[i==0 ? 1 : 0];
- p->d_qinfo[q].d_var_constraint[ cIsNot ? 0 : 1 ][v].push_back( cno );
- break;
- }
- }
- d_children.pop_back();
- }
- */
- }
- }else{
- d_type = typ_invalid;
- //literals
- if( isHandledUfTerm( d_n ) ){
- Assert( qi->isVar( d_n ) );
- d_type = typ_pred;
- }else if( d_n.getKind()==BOUND_VARIABLE ){
- Assert( d_n.getType().isBoolean() );
- d_type = typ_bool_var;
- }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){
- for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
- if( d_n[i].hasBoundVar() ){
- if( !qi->isVar( d_n[i] ) ){
- Trace("qcf-qregister-debug") << "ERROR : not var " << d_n[i] << std::endl;
- }
- Assert( qi->isVar( d_n[i] ) );
- if( d_n.getKind()!=EQUAL && qi->isVar( d_n[i] ) ){
- d_qni_var_num[i+1] = qi->d_var_num[d_n[i]];
- }
- }else{
- d_qni_gterm[i] = d_n[i];
- }
- }
- d_type = d_n.getKind()==EQUAL ? typ_eq : typ_tconstraint;
- Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;
- }
- }
- }else{
- //we will just evaluate
- d_n = n;
- d_type = typ_ground;
- }
- //if( d_type!=typ_invalid ){
- //determine an efficient children ordering
- //if( !d_children.empty() ){
- //for( unsigned i=0; i<d_children.size(); i++ ){
- // d_children_order.push_back( i );
- //}
- //if( !d_n.isNull() && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF ) ){
- //sort based on the type of the constraint : ground comes first, then literals, then others
- //MatchGenSort mgs;
- //mgs.d_mg = this;
- //std::sort( d_children_order.begin(), d_children_order.end(), mgs );
- //}
- //}
- //}
- }
- Trace("qcf-qregister-debug") << "Done make match gen " << n << ", type = ";
- debugPrintType( "qcf-qregister-debug", d_type, true );
- Trace("qcf-qregister-debug") << std::endl;
- //Assert( d_children.size()==d_children_order.size() );
-
-}
-
-void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars ) {
- int v = qi->getVarNum( n );
- if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){
- cbvars.push_back( v );
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- collectBoundVar( qi, n[i], cbvars );
- }
-}
-
-void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {
- Trace("qcf-qregister-debug") << "Determine variable order " << d_n << std::endl;
- bool isCom = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF );
- std::map< int, std::vector< int > > c_to_vars;
- std::map< int, std::vector< int > > vars_to_c;
- std::map< int, int > vb_count;
- std::map< int, int > vu_count;
- std::vector< bool > assigned;
- Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;
- for( unsigned i=0; i<d_children.size(); i++ ){
- collectBoundVar( qi, d_children[i].d_n, c_to_vars[i] );
- assigned.push_back( false );
- vb_count[i] = 0;
- vu_count[i] = 0;
- for( unsigned j=0; j<c_to_vars[i].size(); j++ ){
- int v = c_to_vars[i][j];
- vars_to_c[v].push_back( i );
- if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
- vu_count[i]++;
- if( !isCom ){
- bvars.push_back( v );
- }
- }else{
- vb_count[i]++;
- }
- }
- }
- if( isCom ){
- //children that bind the least number of unbound variables go first
- do {
- int min_score = -1;
- int min_score_index = -1;
- for( unsigned i=0; i<d_children.size(); i++ ){
- if( !assigned[i] ){
- int score = vu_count[i];
- if( min_score==-1 || score<min_score ){
- min_score = score;
- min_score_index = i;
- }
- }
- }
- Trace("qcf-qregister-debug") << "...assign child " << min_score_index << "/" << d_children.size() << std::endl;
- Assert( min_score_index!=-1 );
- //add to children order
- d_children_order.push_back( min_score_index );
- assigned[min_score_index] = true;
- //if( vb_count[min_score_index]==0 ){
- // d_independent.push_back( min_score_index );
- //}
- //determine order internal to children
- d_children[min_score_index].determineVariableOrder( qi, bvars );
- Trace("qcf-qregister-debug") << "...bind variables" << std::endl;
- //now, make it a bound variable
- for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){
- int v = c_to_vars[min_score_index][i];
- if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){
- for( unsigned j=0; j<vars_to_c[v].size(); j++ ){
- int vc = vars_to_c[v][j];
- vu_count[vc]--;
- vb_count[vc]++;
- }
- bvars.push_back( v );
- }
- }
- Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;
- }while( d_children_order.size()!=d_children.size() );
- Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;
- }else{
- for( unsigned i=0; i<d_children.size(); i++ ){
- d_children_order.push_back( i );
- d_children[i].determineVariableOrder( qi, bvars );
- }
- }
-}
-
-
-void MatchGen::reset_round( QuantConflictFind * p ) {
- d_wasSet = false;
- for( unsigned i=0; i<d_children.size(); i++ ){
- d_children[i].reset_round( p );
- }
- for( std::map< int, TNode >::iterator it = d_qni_gterm.begin(); it != d_qni_gterm.end(); ++it ){
- d_qni_gterm_rep[it->first] = p->getRepresentative( it->second );
- }
- if( d_type==typ_ground ){
- int e = p->evaluate( d_n );
- if( e==1 ){
- d_ground_eval[0] = p->d_true;
- }else if( e==-1 ){
- d_ground_eval[0] = p->d_false;
- }
- }else if( d_type==typ_eq ){
- for( unsigned i=0; i<d_n.getNumChildren(); i++ ){
- if( !d_n[i].hasBoundVar() ){
- d_ground_eval[i] = p->evaluateTerm( d_n[i] );
- }
- }
- }
- d_qni_bound_cons.clear();
- d_qni_bound_cons_var.clear();
- d_qni_bound.clear();
-}
-
-void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {
- d_tgt = d_type_not ? !tgt : tgt;
- Debug("qcf-match") << " Reset for : " << d_n << ", type : ";
- debugPrintType( "qcf-match", d_type );
- Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;
- d_qn.clear();
- d_qni.clear();
- d_qni_bound.clear();
- d_child_counter = -1;
- d_tgt_orig = d_tgt;
-
- //set up processing matches
- if( d_type==typ_invalid ){
- //do nothing
- }else if( d_type==typ_ground ){
- if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){
- d_child_counter = 0;
- }
- }else if( d_type==typ_bool_var ){
- //get current value of the variable
- TNode n = qi->getCurrentValue( d_n );
- int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );
- if( vn==-1 ){
- //evaluate the value, see if it is compatible
- int e = p->evaluate( n );
- if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){
- d_child_counter = 0;
- }
- }else{
- //unassigned, set match to true/false
- d_qni_bound[0] = vn;
- qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false );
- d_child_counter = 0;
- }
- if( d_child_counter==0 ){
- d_qn.push_back( NULL );
- }
- }else if( d_type==typ_var ){
- Assert( isHandledUfTerm( d_n ) );
- Node f = getOperator( p, d_n );
- Debug("qcf-match-debug") << " reset: Var will match operators of " << f << std::endl;
- QcfNodeIndex * qni = p->getQcfNodeIndex( Node::null(), f );
- if( qni!=NULL ){
- d_qn.push_back( qni );
- }
- d_matched_basis = false;
- }else if( d_type==typ_tsym || d_type==typ_tconstraint ){
- for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){
- int repVar = qi->getCurrentRepVar( it->second );
- if( qi->d_match[repVar].isNull() ){
- Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;
- d_qni_bound[it->first] = repVar;
- }
- }
- d_qn.push_back( NULL );
- }else if( d_type==typ_pred || d_type==typ_eq ){
- //add initial constraint
- Node nn[2];
- int vn[2];
- if( d_type==typ_pred ){
- nn[0] = qi->getCurrentValue( d_n );
- vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );
- nn[1] = p->getRepresentative( d_tgt ? p->d_true : p->d_false );
- vn[1] = -1;
- d_tgt = true;
- }else{
- for( unsigned i=0; i<2; i++ ){
- TNode nc;
- std::map< int, TNode >::iterator it = d_qni_gterm_rep.find( i );
- if( it!=d_qni_gterm_rep.end() ){
- nc = it->second;
- }else{
- nc = d_n[i];
- }
- nn[i] = qi->getCurrentValue( nc );
- vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );
- }
- }
- bool success;
- if( vn[0]==-1 && vn[1]==-1 ){
- //Trace("qcf-explain") << " reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;
- Debug("qcf-match-debug") << " reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;
- //just compare values
- if( d_tgt ){
- success = p->areMatchEqual( nn[0], nn[1] );
- }else{
- if( p->d_effort==QuantConflictFind::effort_conflict ){
- success = p->areDisequal( nn[0], nn[1] );
- }else{
- success = p->areMatchDisequal( nn[0], nn[1] );
- }
- }
- }else{
- //otherwise, add a constraint to a variable
- if( vn[1]!=-1 && vn[0]==-1 ){
- //swap
- Node t = nn[1];
- nn[1] = nn[0];
- nn[0] = t;
- vn[0] = vn[1];
- vn[1] = -1;
- }
- Debug("qcf-match-debug") << " reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;
- //add some constraint
- int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );
- success = addc!=-1;
- //if successful and non-redundant, store that we need to cleanup this
- if( addc==1 ){
- //Trace("qcf-explain") << " reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;
- for( unsigned i=0; i<2; i++ ){
- if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){
- d_qni_bound[vn[i]] = vn[i];
- }
- }
- d_qni_bound_cons[vn[0]] = nn[1];
- d_qni_bound_cons_var[vn[0]] = vn[1];
- }
- }
- //if successful, we will bind values to variables
- if( success ){
- d_qn.push_back( NULL );
- }
- }else{
- if( d_children.empty() ){
- //add dummy
- d_qn.push_back( NULL );
- }else{
- if( d_tgt && d_n.getKind()==FORALL ){
- //do nothing
- }else{
- //reset the first child to d_tgt
- d_child_counter = 0;
- getChild( d_child_counter )->reset( p, d_tgt, qi );
- }
- }
- }
- d_binding = false;
- d_wasSet = true;
- Debug("qcf-match") << " reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;
-}
-
-bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {
- Debug("qcf-match") << " Get next match for : " << d_n << ", type = ";
- debugPrintType( "qcf-match", d_type );
- Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;
- if( d_type==typ_invalid || d_type==typ_ground ){
- if( d_child_counter==0 ){
- d_child_counter = -1;
- return true;
- }else{
- d_wasSet = false;
- return false;
- }
- }else if( d_type==typ_var || d_type==typ_eq || d_type==typ_pred || d_type==typ_bool_var || d_type==typ_tconstraint || d_type==typ_tsym ){
- bool success = false;
- bool terminate = false;
- do {
- bool doReset = false;
- bool doFail = false;
- if( !d_binding ){
- if( doMatching( p, qi ) ){
- Debug("qcf-match-debug") << " - Matching succeeded" << std::endl;
- d_binding = true;
- d_binding_it = d_qni_bound.begin();
- doReset = true;
- //for tconstraint, add constraint
- if( d_type==typ_tconstraint ){
- std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );
- if( it==qi->d_tconstraints.end() ){
- qi->d_tconstraints[d_n] = d_tgt;
- //store that we added this constraint
- d_qni_bound_cons[0] = d_n;
- }else if( d_tgt!=it->second ){
- success = false;
- terminate = true;
- }
- }
- }else{
- Debug("qcf-match-debug") << " - Matching failed" << std::endl;
- success = false;
- terminate = true;
- }
- }else{
- doFail = true;
- }
- if( d_binding ){
- //also need to create match for each variable we bound
- success = true;
- Debug("qcf-match-debug") << " Produce matches for bound variables by " << d_n << ", type = ";
- debugPrintType( "qcf-match-debug", d_type );
- Debug("qcf-match-debug") << "..." << std::endl;
-
- while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){
- std::map< int, MatchGen * >::iterator itm;
- if( !doFail ){
- Debug("qcf-match-debug") << " check variable " << d_binding_it->second << std::endl;
- itm = qi->d_var_mg.find( d_binding_it->second );
- }
- if( doFail || ( d_binding_it->first!=0 && itm!=qi->d_var_mg.end() ) ){
- Debug("qcf-match-debug") << " we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;
- if( doReset ){
- itm->second->reset( p, true, qi );
- }
- if( doFail || !itm->second->getNextMatch( p, qi ) ){
- do {
- if( d_binding_it==d_qni_bound.begin() ){
- Debug("qcf-match-debug") << " failed." << std::endl;
- success = false;
- }else{
- --d_binding_it;
- Debug("qcf-match-debug") << " decrement..." << std::endl;
- }
- }while( success && ( d_binding_it->first==0 || qi->d_var_mg.find( d_binding_it->second )==qi->d_var_mg.end() ) );
- doReset = false;
- doFail = false;
- }else{
- Debug("qcf-match-debug") << " increment..." << std::endl;
- ++d_binding_it;
- doReset = true;
- }
- }else{
- Debug("qcf-match-debug") << " skip..." << d_binding_it->second << std::endl;
- ++d_binding_it;
- doReset = true;
- }
- }
- if( !success ){
- d_binding = false;
- }else{
- terminate = true;
- if( d_binding_it==d_qni_bound.begin() ){
- d_binding = false;
- }
- }
- }
- }while( !terminate );
- //if not successful, clean up the variables you bound
- if( !success ){
- if( d_type==typ_eq || d_type==typ_pred ){
- //clean up the constraints you added
- for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){
- if( !it->second.isNull() ){
- Debug("qcf-match") << " Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;
- std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );
- int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;
- //Trace("qcf-explain") << " cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;
- qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );
- }
- }
- d_qni_bound_cons.clear();
- d_qni_bound_cons_var.clear();
- d_qni_bound.clear();
- }else{
- //clean up the matches you set
- for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
- Debug("qcf-match") << " Clean up bound var " << it->second << std::endl;
- Assert( it->second<qi->getNumVars() );
- qi->d_match[ it->second ] = TNode::null();
- qi->d_match_term[ it->second ] = TNode::null();
- }
- d_qni_bound.clear();
- }
- if( d_type==typ_tconstraint ){
- //remove constraint if applicable
- if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){
- qi->d_tconstraints.erase( d_n );
- d_qni_bound_cons.clear();
- }
- }
- /*
- if( d_type==typ_var && p->d_effort==QuantConflictFind::effort_mc && !d_matched_basis ){
- d_matched_basis = true;
- Node f = getOperator( d_n );
- TNode mbo = p->getQuantifiersEngine()->getTermDatabase()->getModelBasisOpTerm( f );
- if( qi->setMatch( p, d_qni_var_num[0], mbo ) ){
- success = true;
- d_qni_bound[0] = d_qni_var_num[0];
- }
- }
- */
- }
- Debug("qcf-match") << " ...finished matching for " << d_n << ", success = " << success << std::endl;
- d_wasSet = success;
- return success;
- }else if( d_type==typ_formula || d_type==typ_ite_var ){
- bool success = false;
- if( d_child_counter<0 ){
- if( d_child_counter<-1 ){
- success = true;
- d_child_counter = -1;
- }
- }else{
- while( !success && d_child_counter>=0 ){
- //transition system based on d_child_counter
- if( d_n.getKind()==OR || d_n.getKind()==AND ){
- if( (d_n.getKind()==AND)==d_tgt ){
- //all children must match simultaneously
- if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
- if( d_child_counter<(int)(getNumChildren()-1) ){
- d_child_counter++;
- Debug("qcf-match-debug") << " Reset child " << d_child_counter << " of " << d_n << std::endl;
- getChild( d_child_counter )->reset( p, d_tgt, qi );
- }else{
- success = true;
- }
- }else{
- //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){
- // d_child_counter--;
- //}else{
- d_child_counter--;
- //}
- }
- }else{
- //one child must match
- if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){
- if( d_child_counter<(int)(getNumChildren()-1) ){
- d_child_counter++;
- Debug("qcf-match-debug") << " Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;
- getChild( d_child_counter )->reset( p, d_tgt, qi );
- }else{
- d_child_counter = -1;
- }
- }else{
- success = true;
- }
- }
- }else if( d_n.getKind()==IFF ){
- //construct match based on both children
- if( d_child_counter%2==0 ){
- if( getChild( 0 )->getNextMatch( p, qi ) ){
- d_child_counter++;
- getChild( 1 )->reset( p, d_child_counter==1, qi );
- }else{
- if( d_child_counter==0 ){
- d_child_counter = 2;
- getChild( 0 )->reset( p, !d_tgt, qi );
- }else{
- d_child_counter = -1;
- }
- }
- }
- if( d_child_counter>=0 && d_child_counter%2==1 ){
- if( getChild( 1 )->getNextMatch( p, qi ) ){
- success = true;
- }else{
- d_child_counter--;
- }
- }
- }else if( d_n.getKind()==ITE ){
- if( d_child_counter%2==0 ){
- int index1 = d_child_counter==4 ? 1 : 0;
- if( getChild( index1 )->getNextMatch( p, qi ) ){
- d_child_counter++;
- getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );
- }else{
- if( d_child_counter==4 || ( d_type==typ_ite_var && d_child_counter==2 ) ){
- d_child_counter = -1;
- }else{
- d_child_counter +=2;
- getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );
- }
- }
- }
- if( d_child_counter>=0 && d_child_counter%2==1 ){
- int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);
- if( getChild( index2 )->getNextMatch( p, qi ) ){
- success = true;
- }else{
- d_child_counter--;
- }
- }
- }else if( d_n.getKind()==FORALL ){
- if( getChild( d_child_counter )->getNextMatch( p, qi ) ){
- success = true;
- }else{
- d_child_counter = -1;
- }
- }
- }
- d_wasSet = success;
- Debug("qcf-match") << " ...finished construct match for " << d_n << ", success = " << success << std::endl;
- return success;
- }
- }
- Debug("qcf-match") << " ...already finished for " << d_n << std::endl;
- return false;
-}
-
-bool MatchGen::getExplanation( QuantConflictFind * p, QuantInfo * qi, std::vector< Node >& exp ) {
- if( d_type==typ_eq ){
- Node n[2];
- for( unsigned i=0; i<2; i++ ){
- Trace("qcf-explain") << "Explain term " << d_n[i] << "..." << std::endl;
- n[i] = getExplanationTerm( p, qi, d_n[i], exp );
- }
- Node eq = n[0].eqNode( n[1] );
- if( !d_tgt_orig ){
- eq = eq.negate();
- }
- exp.push_back( eq );
- Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << eq << ", set = " << d_wasSet << std::endl;
- return true;
- }else if( d_type==typ_pred ){
- Trace("qcf-explain") << "Explain term " << d_n << "..." << std::endl;
- Node n = getExplanationTerm( p, qi, d_n, exp );
- if( !d_tgt_orig ){
- n = n.negate();
- }
- exp.push_back( n );
- Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << n << ", set = " << d_wasSet << std::endl;
- return true;
- }else if( d_type==typ_formula ){
- Trace("qcf-explain") << "Explanation get for " << d_n << ", counter = " << d_child_counter << ", tgt = " << d_tgt_orig << ", set = " << d_wasSet << std::endl;
- if( d_n.getKind()==OR || d_n.getKind()==AND ){
- if( (d_n.getKind()==AND)==d_tgt ){
- for( unsigned i=0; i<getNumChildren(); i++ ){
- if( !getChild( i )->getExplanation( p, qi, exp ) ){
- return false;
- }
- }
- }else{
- return getChild( d_child_counter )->getExplanation( p, qi, exp );
- }
- }else if( d_n.getKind()==IFF ){
- for( unsigned i=0; i<2; i++ ){
- if( !getChild( i )->getExplanation( p, qi, exp ) ){
- return false;
- }
- }
- }else if( d_n.getKind()==ITE ){
- for( unsigned i=0; i<3; i++ ){
- bool isActive = ( ( i==0 && d_child_counter!=5 ) ||
- ( i==1 && d_child_counter!=( d_tgt ? 3 : 1 ) ) ||
- ( i==2 && d_child_counter!=( d_tgt ? 1 : 3 ) ) );
- if( isActive ){
- if( !getChild( i )->getExplanation( p, qi, exp ) ){
- return false;
- }
- }
- }
- }else{
- return false;
- }
- return true;
- }else{
- return false;
- }
-}
-
-Node MatchGen::getExplanationTerm( QuantConflictFind * p, QuantInfo * qi, Node t, std::vector< Node >& exp ) {
- Node v = qi->getCurrentExpValue( t );
- if( isHandledUfTerm( t ) ){
- for( unsigned i=0; i<t.getNumChildren(); i++ ){
- Node vi = getExplanationTerm( p, qi, t[i], exp );
- if( vi!=v[i] ){
- Node eq = vi.eqNode( v[i] );
- if( std::find( exp.begin(), exp.end(), eq )==exp.end() ){
- Trace("qcf-explain") << " add : " << eq << "." << std::endl;
- exp.push_back( eq );
- }
- }
- }
- }
- return v;
-}
-
-bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {
- if( !d_qn.empty() ){
- if( d_qn[0]==NULL ){
- d_qn.clear();
- return true;
- }else{
- Assert( d_type==typ_var );
- Assert( d_qni_size>0 );
- bool invalidMatch;
- do {
- invalidMatch = false;
- Debug("qcf-match-debug") << " Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;
- if( d_qn.size()==d_qni.size()+1 ) {
- int index = (int)d_qni.size();
- //initialize
- TNode val;
- std::map< int, int >::iterator itv = d_qni_var_num.find( index );
- if( itv!=d_qni_var_num.end() ){
- //get the representative variable this variable is equal to
- int repVar = qi->getCurrentRepVar( itv->second );
- Debug("qcf-match-debug") << " Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;
- //get the value the rep variable
- //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );
- if( !qi->d_match[repVar].isNull() ){
- val = qi->d_match[repVar];
- Debug("qcf-match-debug") << " Variable is already bound to " << val << std::endl;
- }else{
- //binding a variable
- d_qni_bound[index] = repVar;
- std::map< TNode, QcfNodeIndex >::iterator it = d_qn[index]->d_children.begin();
- if( it != d_qn[index]->d_children.end() ) {
- d_qni.push_back( it );
- //set the match
- if( qi->setMatch( p, d_qni_bound[index], it->first ) ){
- Debug("qcf-match-debug") << " Binding variable" << std::endl;
- if( d_qn.size()<d_qni_size ){
- d_qn.push_back( &it->second );
- }
- }else{
- Debug("qcf-match") << " Binding variable, currently fail." << std::endl;
- invalidMatch = true;
- }
- }else{
- Debug("qcf-match-debug") << " Binding variable, fail, no more variables to bind" << std::endl;
- d_qn.pop_back();
- }
- }
- }else{
- Debug("qcf-match-debug") << " Match " << index << " is ground term" << std::endl;
- Assert( d_qni_gterm.find( index )!=d_qni_gterm.end() );
- Assert( d_qni_gterm_rep.find( index )!=d_qni_gterm_rep.end() );
- val = d_qni_gterm_rep[index];
- Assert( !val.isNull() );
- }
- if( !val.isNull() ){
- //constrained by val
- std::map< TNode, QcfNodeIndex >::iterator it = d_qn[index]->d_children.find( val );
- if( it!=d_qn[index]->d_children.end() ){
- Debug("qcf-match-debug") << " Match" << std::endl;
- d_qni.push_back( it );
- if( d_qn.size()<d_qni_size ){
- d_qn.push_back( &it->second );
- }
- }else{
- Debug("qcf-match-debug") << " Failed to match" << std::endl;
- d_qn.pop_back();
- }
- }
- }else{
- Assert( d_qn.size()==d_qni.size() );
- int index = d_qni.size()-1;
- //increment if binding this variable
- bool success = false;
- std::map< int, int >::iterator itb = d_qni_bound.find( index );
- if( itb!=d_qni_bound.end() ){
- d_qni[index]++;
- if( d_qni[index]!=d_qn[index]->d_children.end() ){
- success = true;
- if( qi->setMatch( p, itb->second, d_qni[index]->first ) ){
- Debug("qcf-match-debug") << " Bind next variable" << std::endl;
- if( d_qn.size()<d_qni_size ){
- d_qn.push_back( &d_qni[index]->second );
- }
- }else{
- Debug("qcf-match-debug") << " Bind next variable, currently fail" << std::endl;
- invalidMatch = true;
- }
- }else{
- qi->d_match[ itb->second ] = TNode::null();
- qi->d_match_term[ itb->second ] = TNode::null();
- Debug("qcf-match-debug") << " Bind next variable, no more variables to bind" << std::endl;
- }
- }else{
- //TODO : if it equal to something else, also try that
- }
- //if not incrementing, move to next
- if( !success ){
- d_qn.pop_back();
- d_qni.pop_back();
- }
- }
- }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );
- if( d_qni.size()==d_qni_size ){
- //Assert( !d_qni[d_qni.size()-1]->second.d_children.empty() );
- //Debug("qcf-match-debug") << " We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;
- Assert( !d_qni[d_qni.size()-1]->second.d_children.empty() );
- TNode t = d_qni[d_qni.size()-1]->second.d_children.begin()->first;
- Debug("qcf-match-debug") << " " << d_n << " matched " << t << std::endl;
- qi->d_match_term[d_qni_var_num[0]] = t;
- //set the match terms
- for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){
- Debug("qcf-match-debug") << " position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;
- //if( it->second<(int)qi->d_q[0].getNumChildren() ){ //if it is an actual variable, we are interested in knowing the actual term
- if( it->first>0 ){
- Assert( !qi->d_match[ it->second ].isNull() );
- Assert( p->areEqual( t[it->first-1], qi->d_match[ it->second ] ) );
- qi->d_match_term[it->second] = t[it->first-1];
- }
- //}
- }
- }
- }
- }
- return !d_qn.empty();
-}
-
-void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {
- if( isTrace ){
- switch( typ ){
- case typ_invalid: Trace(c) << "invalid";break;
- case typ_ground: Trace(c) << "ground";break;
- case typ_eq: Trace(c) << "eq";break;
- case typ_pred: Trace(c) << "pred";break;
- case typ_formula: Trace(c) << "formula";break;
- case typ_var: Trace(c) << "var";break;
- case typ_ite_var: Trace(c) << "ite_var";break;
- case typ_bool_var: Trace(c) << "bool_var";break;
- }
- }else{
- switch( typ ){
- case typ_invalid: Debug(c) << "invalid";break;
- case typ_ground: Debug(c) << "ground";break;
- case typ_eq: Debug(c) << "eq";break;
- case typ_pred: Debug(c) << "pred";break;
- case typ_formula: Debug(c) << "formula";break;
- case typ_var: Debug(c) << "var";break;
- case typ_ite_var: Debug(c) << "ite_var";break;
- case typ_bool_var: Debug(c) << "bool_var";break;
- }
- }
-}
-
-void MatchGen::setInvalid() {
- d_type = typ_invalid;
- d_children.clear();
-}
-
-bool MatchGen::isHandledBoolConnective( TNode n ) {
- return n.getType().isBoolean() && ( n.getKind()==OR || n.getKind()==AND || n.getKind()==IFF || n.getKind()==ITE || n.getKind()==FORALL || n.getKind()==NOT );
-}
-
-bool MatchGen::isHandledUfTerm( TNode n ) {
- //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||
- // n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;
- return inst::Trigger::isAtomicTriggerKind( n.getKind() );
-}
-
-Node MatchGen::getOperator( QuantConflictFind * p, Node n ) {
- if( isHandledUfTerm( n ) ){
- return p->getQuantifiersEngine()->getTermDatabase()->getOperator( n );
- }else{
- return Node::null();
- }
-}
-
-bool MatchGen::isHandled( TNode n ) {
- if( n.getKind()!=BOUND_VARIABLE && n.hasBoundVar() ){
- if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){
- return false;
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- if( !isHandled( n[i] ) ){
- return false;
- }
- }
- }
- return true;
-}
-
-
-QuantConflictFind::QuantConflictFind( QuantifiersEngine * qe, context::Context* c ) :
-QuantifiersModule( qe ),
-d_c( c ),
-d_conflict( c, false ),
-d_qassert( c ) {
- d_fid_count = 0;
- d_true = NodeManager::currentNM()->mkConst<bool>(true);
- d_false = NodeManager::currentNM()->mkConst<bool>(false);
-}
-
-Node QuantConflictFind::mkEqNode( Node a, Node b ) {
- if( a.getType().isBoolean() ){
- return a.iffNode( b );
- }else{
- return a.eqNode( b );
- }
-}
-
-//-------------------------------------------------- registration
-
-void QuantConflictFind::registerQuantifier( Node q ) {
- if( !TermDb::isRewriteRule( q ) ){
- d_quants.push_back( q );
- d_quant_id[q] = d_quants.size();
- Trace("qcf-qregister") << "Register ";
- debugPrintQuant( "qcf-qregister", q );
- Trace("qcf-qregister") << " : " << q << std::endl;
- //make QcfNode structure
- Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;
- d_qinfo[q].initialize( q, q[1] );
-
- //debug print
- Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;
- Trace("qcf-qregister") << " ";
- debugPrintQuantBody( "qcf-qregister", q, q[1] );
- Trace("qcf-qregister") << std::endl;
- if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){
- Trace("qcf-qregister") << " with additional constraints : " << std::endl;
- for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){
- Trace("qcf-qregister") << " ?x" << j << " = ";
- debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );
- Trace("qcf-qregister") << std::endl;
- }
- }
-
- Trace("qcf-qregister") << "Done registering quantifier." << std::endl;
- }
-}
-
-int QuantConflictFind::evaluate( Node n, bool pref, bool hasPref ) {
- int ret = 0;
- if( n.getKind()==EQUAL ){
- Node n1 = evaluateTerm( n[0] );
- Node n2 = evaluateTerm( n[1] );
- Debug("qcf-eval") << "Evaluate : Normalize " << n << " to " << n1 << " = " << n2 << std::endl;
- if( areEqual( n1, n2 ) ){
- ret = 1;
- }else if( areDisequal( n1, n2 ) ){
- ret = -1;
- }
- //else if( d_effort>QuantConflictFind::effort_conflict ){
- // ret = -1;
- //}
- }else if( MatchGen::isHandledUfTerm( n ) ){ //predicate
- Node nn = evaluateTerm( n );
- Debug("qcf-eval") << "Evaluate : Normalize " << nn << " to " << n << std::endl;
- if( areEqual( nn, d_true ) ){
- ret = 1;
- }else if( areEqual( nn, d_false ) ){
- ret = -1;
- }
- //else if( d_effort>QuantConflictFind::effort_conflict ){
- // ret = -1;
- //}
- }else if( n.getKind()==NOT ){
- return -evaluate( n[0] );
- }else if( n.getKind()==ITE ){
- int cev1 = evaluate( n[0] );
- int cevc[2] = { 0, 0 };
- for( unsigned i=0; i<2; i++ ){
- if( ( i==0 && cev1!=-1 ) || ( i==1 && cev1!=1 ) ){
- cevc[i] = evaluate( n[i+1] );
- if( cev1!=0 ){
- ret = cevc[i];
- break;
- }else if( cevc[i]==0 ){
- break;
- }
- }
- }
- if( ret==0 && cevc[0]!=0 && cevc[0]==cevc[1] ){
- ret = cevc[0];
- }
- }else if( n.getKind()==IFF ){
- int cev1 = evaluate( n[0] );
- if( cev1!=0 ){
- int cev2 = evaluate( n[1] );
- if( cev2!=0 ){
- ret = cev1==cev2 ? 1 : -1;
- }
- }
-
- }else{
- int ssval = 0;
- if( n.getKind()==OR ){
- ssval = 1;
- }else if( n.getKind()==AND ){
- ssval = -1;
- }
- bool isUnk = false;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- int cev = evaluate( n[i] );
- if( cev==ssval ){
- ret = ssval;
- break;
- }else if( cev==0 ){
- isUnk = true;
- }
- }
- if( ret==0 && !isUnk ){
- ret = -ssval;
- }
- }
- Debug("qcf-eval") << "Evaluate " << n << " to " << ret << std::endl;
- return ret;
-}
-
-short QuantConflictFind::getMaxQcfEffort() {
- if( options::qcfMode()==QCF_CONFLICT_ONLY ){
- return effort_conflict;
- }else if( options::qcfMode()==QCF_PROP_EQ ){
- return effort_prop_eq;
- }else if( options::qcfMode()==QCF_MC ){
- return effort_mc;
- }else{
- return 0;
- }
-}
-
-bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {
- //if( d_effort==QuantConflictFind::effort_mc ){
- // return n1==n2 || !areDisequal( n1, n2 );
- //}else{
- return n1==n2;
- //}
-}
-
-bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {
- //if( d_effort==QuantConflictFind::effort_conflict ){
- // return areDisequal( n1, n2 );
- //}else{
- return n1!=n2;
- //}
-}
-
-//-------------------------------------------------- handling assertions / eqc
-
-void QuantConflictFind::assertNode( Node q ) {
- if( !TermDb::isRewriteRule( q ) ){
- Trace("qcf-proc") << "QCF : assertQuantifier : ";
- debugPrintQuant("qcf-proc", q);
- Trace("qcf-proc") << std::endl;
- d_qassert.push_back( q );
- //set the eqRegistries that this depends on to true
- //for( std::map< EqRegistry *, bool >::iterator it = d_qinfo[q].d_rel_eqr.begin(); it != d_qinfo[q].d_rel_eqr.end(); ++it ){
- // it->first->d_active.set( true );
- //}
- }
-}
-
-eq::EqualityEngine * QuantConflictFind::getEqualityEngine() {
- //return ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( theory::THEORY_UF ))->getEqualityEngine();
- return d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();
-}
-bool QuantConflictFind::areEqual( Node n1, Node n2 ) {
- return getEqualityEngine()->hasTerm( n1 ) && getEqualityEngine()->hasTerm( n2 ) && getEqualityEngine()->areEqual( n1,n2 );
-}
-bool QuantConflictFind::areDisequal( Node n1, Node n2 ) {
- return n1!=n2 && getEqualityEngine()->hasTerm( n1 ) && getEqualityEngine()->hasTerm( n2 ) && getEqualityEngine()->areDisequal( n1,n2, false );
-}
-Node QuantConflictFind::getRepresentative( Node n ) {
- if( getEqualityEngine()->hasTerm( n ) ){
- return getEqualityEngine()->getRepresentative( n );
- }else{
- return n;
- }
-}
-Node QuantConflictFind::evaluateTerm( Node n ) {
- if( MatchGen::isHandledUfTerm( n ) ){
- Node f = MatchGen::getOperator( this, n );
- Node nn;
- computeUfTerms( f );
- if( getEqualityEngine()->hasTerm( n ) ){
- computeArgReps( n );
- nn = d_uf_terms[f].existsTerm( n, d_arg_reps[n] );
- }else{
- std::vector< TNode > args;
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- Node c = evaluateTerm( n[i] );
- args.push_back( c );
- }
- nn = d_uf_terms[f].existsTerm( n, args );
- }
- if( !nn.isNull() ){
- Debug("qcf-eval") << "GT: Term " << nn << " for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n ) << std::endl;
- return getRepresentative( nn );
- }else{
- Debug("qcf-eval") << "GT: No term for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n ) << std::endl;
- return n;
- }
- }else if( n.getKind()==ITE ){
- int v = evaluate( n[0], false, false );
- if( v==1 ){
- return evaluateTerm( n[1] );
- }else if( v==-1 ){
- return evaluateTerm( n[2] );
- }
- }
- return getRepresentative( n );
-}
-
-/*
-QuantConflictFind::EqcInfo * QuantConflictFind::getEqcInfo( Node n, bool doCreate ) {
- std::map< Node, EqcInfo * >::iterator it2 = d_eqc_info.find( n );
- if( it2==d_eqc_info.end() ){
- if( doCreate ){
- EqcInfo * eqci = new EqcInfo( d_c );
- d_eqc_info[n] = eqci;
- return eqci;
- }else{
- return NULL;
- }
- }
- return it2->second;
-}
-*/
-
-QcfNodeIndex * QuantConflictFind::getQcfNodeIndex( Node eqc, Node f ) {
- computeUfTerms( f );
- std::map< TNode, QcfNodeIndex >::iterator itut = d_eqc_uf_terms.find( f );
- if( itut==d_eqc_uf_terms.end() ){
- return NULL;
- }else{
- if( eqc.isNull() ){
- return &itut->second;
- }else{
- std::map< TNode, QcfNodeIndex >::iterator itute = itut->second.d_children.find( eqc );
- if( itute!=itut->second.d_children.end() ){
- return &itute->second;
- }else{
- return NULL;
- }
- }
- }
-}
-
-QcfNodeIndex * QuantConflictFind::getQcfNodeIndex( Node f ) {
- computeUfTerms( f );
- std::map< TNode, QcfNodeIndex >::iterator itut = d_uf_terms.find( f );
- if( itut!=d_uf_terms.end() ){
- return &itut->second;
- }else{
- return NULL;
- }
-}
-
-/** new node */
-void QuantConflictFind::newEqClass( Node n ) {
- //Trace("qcf-proc-debug") << "QCF : newEqClass : " << n << std::endl;
- //Trace("qcf-proc2-debug") << "QCF : finished newEqClass : " << n << std::endl;
-}
-
-/** merge */
-void QuantConflictFind::merge( Node a, Node b ) {
- /*
- if( b.getKind()==EQUAL ){
- if( a==d_true ){
- //will merge anyways
- //merge( b[0], b[1] );
- }else if( a==d_false ){
- assertDisequal( b[0], b[1] );
- }
- }else{
- Trace("qcf-proc") << "QCF : merge : " << a << " " << b << std::endl;
- EqcInfo * eqc_b = getEqcInfo( b, false );
- EqcInfo * eqc_a = NULL;
- if( eqc_b ){
- eqc_a = getEqcInfo( a );
- //move disequalities of b into a
- for( NodeBoolMap::iterator it = eqc_b->d_diseq.begin(); it != eqc_b->d_diseq.end(); ++it ){
- if( (*it).second ){
- Node n = (*it).first;
- EqcInfo * eqc_n = getEqcInfo( n, false );
- Assert( eqc_n );
- if( !eqc_n->isDisequal( a ) ){
- Assert( !eqc_a->isDisequal( n ) );
- eqc_n->setDisequal( a );
- eqc_a->setDisequal( n );
- //setEqual( eqc_a, eqc_b, a, n, false );
- }
- eqc_n->setDisequal( b, false );
- }
- }
- ////move all previous EqcRegistry's regarding equalities within b
- //for( NodeBoolMap::iterator it = eqc_b->d_rel_eqr_e.begin(); it != eqc_b->d_rel_eqr_e.end(); ++it ){
- // if( (*it).second ){
- // eqc_a->d_rel_eqr_e[(*it).first] = true;
- // }
- //}
- }
- //process new equalities
- //setEqual( eqc_a, eqc_b, a, b, true );
- Trace("qcf-proc2") << "QCF : finished merge : " << a << " " << b << std::endl;
- }
- */
-}
-
-/** assert disequal */
-void QuantConflictFind::assertDisequal( Node a, Node b ) {
- /*
- a = getRepresentative( a );
- b = getRepresentative( b );
- Trace("qcf-proc") << "QCF : assert disequal : " << a << " " << b << std::endl;
- EqcInfo * eqc_a = getEqcInfo( a );
- EqcInfo * eqc_b = getEqcInfo( b );
- if( !eqc_a->isDisequal( b ) ){
- Assert( !eqc_b->isDisequal( a ) );
- eqc_b->setDisequal( a );
- eqc_a->setDisequal( b );
- //setEqual( eqc_a, eqc_b, a, b, false );
- }
- Trace("qcf-proc2") << "QCF : finished assert disequal : " << a << " " << b << std::endl;
- */
-}
-
-//-------------------------------------------------- check function
-
-void QuantConflictFind::reset_round( Theory::Effort level ) {
- d_needs_computeRelEqr = true;
-}
-
-/** check */
-void QuantConflictFind::check( Theory::Effort level ) {
- Trace("qcf-check") << "QCF : check : " << level << std::endl;
- if( d_conflict ){
- Trace("qcf-check2") << "QCF : finished check : already in conflict." << std::endl;
- if( level>=Theory::EFFORT_FULL ){
- Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;
- //Assert( false );
- }
- }else{
- int addedLemmas = 0;
- if( d_performCheck ){
- ++(d_statistics.d_inst_rounds);
- double clSet = 0;
- int prevEt = 0;
- if( Trace.isOn("qcf-engine") ){
- prevEt = d_statistics.d_entailment_checks.getData();
- clSet = double(clock())/double(CLOCKS_PER_SEC);
- Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level << "---" << std::endl;
- }
- computeRelevantEqr();
-
- //determine order for quantified formulas
- std::vector< Node > qorder;
- std::map< Node, bool > qassert;
- //mark which are asserted
- for( unsigned i=0; i<d_qassert.size(); i++ ){
- qassert[d_qassert[i]] = true;
- }
- //add which ones are specified in the order
- for( unsigned i=0; i<d_quant_order.size(); i++ ){
- Node n = d_quant_order[i];
- if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() && qassert.find( n )!=qassert.end() ){
- qorder.push_back( n );
- }
- }
- d_quant_order.clear();
- d_quant_order.insert( d_quant_order.begin(), qorder.begin(), qorder.end() );
- //add remaining
- for( unsigned i=0; i<d_qassert.size(); i++ ){
- Node n = d_qassert[i];
- if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() ){
- qorder.push_back( n );
- }
- }
-
- if( Trace.isOn("qcf-debug") ){
- Trace("qcf-debug") << std::endl;
- debugPrint("qcf-debug");
- Trace("qcf-debug") << std::endl;
- }
- short end_e = getMaxQcfEffort();
- for( short e = effort_conflict; e<=end_e; e++ ){
- d_effort = e;
- Trace("qcf-check") << "Checking quantified formulas at effort " << e << "..." << std::endl;
- for( unsigned j=0; j<qorder.size(); j++ ){
- Node q = qorder[j];
- QuantInfo * qi = &d_qinfo[q];
-
- Assert( d_qinfo.find( q )!=d_qinfo.end() );
- if( qi->d_mg->isValid() ){
- Trace("qcf-check") << "Check quantified formula ";
- debugPrintQuant("qcf-check", q);
- Trace("qcf-check") << " : " << q << "..." << std::endl;
-
- Trace("qcf-check-debug") << "Reset round..." << std::endl;
- qi->reset_round( this );
- //try to make a matches making the body false
- Trace("qcf-check-debug") << "Get next match..." << std::endl;
- while( qi->d_mg->getNextMatch( this, qi ) ){
- Trace("qcf-check") << "*** Produced match at effort " << e << " : " << std::endl;
- qi->debugPrintMatch("qcf-check");
- Trace("qcf-check") << std::endl;
- std::vector< int > assigned;
- if( !qi->isMatchSpurious( this ) ){
- if( qi->completeMatch( this, assigned ) ){
- /*
- if( options::qcfExp() && d_effort==effort_conflict ){
- std::vector< Node > exp;
- if( qi->d_mg->getExplanation( this, qi, exp ) ){
- Trace("qcf-check-exp") << "Base explanation is : " << std::endl;
- for( unsigned c=0; c<exp.size(); c++ ){
- Trace("qcf-check-exp") << " " << exp[c] << std::endl;
- }
- std::vector< TNode > c_exp;
- eq::EqualityEngine* ee = ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getEqualityEngine() ;
- for( unsigned c=0; c<exp.size(); c++ ){
- bool pol = exp[c].getKind()!=NOT;
- TNode lit = pol ? exp[c] : exp[c][0];
- Trace("qcf-check-exp") << "Explain " << lit << ", polarity " << pol << std::endl;
- if( lit.getKind()==EQUAL ){
- if( !pol && !ee->areDisequal( lit[0], lit[1], true ) ){
- exit( 98 );
- }else if( pol && !ee->areEqual( lit[0], lit[1] ) ){
- exit( 99 );
- }
- ee->explainEquality( lit[0], lit[1], pol, c_exp );
- }else{
- if( !ee->areEqual( lit, pol ? d_true : d_false ) ){
- exit( pol ? 96 : 97 );
- }
- ee->explainPredicate( lit, pol, c_exp );
- }
- }
- std::vector< Node > c_lem;
- Trace("qcf-check-exp") << "Actual explanation is : " << std::endl;
- for( unsigned c=0; c<c_exp.size(); c++ ){
- Trace("qcf-check-exp") << " " << c_exp[c] << std::endl;
- Node ccc = c_exp[c].negate();
- if( std::find( c_lem.begin(), c_lem.end(), ccc )==c_lem.end() ){
- c_lem.push_back( ccc );
- }
- }
-
- c_lem.push_back( q.negate() );
- Node conf = NodeManager::currentNM()->mkNode( OR, c_lem );
- Trace("qcf-conflict") << "QCF conflict : " << conf << std::endl;
- d_quantEngine->addLemma( conf, false );
- d_conflict.set( true );
- ++(d_statistics.d_conflict_inst);
- ++addedLemmas;
- break;
- }
- }
- */
- std::vector< Node > terms;
- qi->getMatch( terms );
- if( !qi->isTConstraintSpurious( this, terms ) ){
- if( Debug.isOn("qcf-check-inst") ){
- //if( e==effort_conflict ){
- Node inst = d_quantEngine->getInstantiation( q, terms );
- Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;
- Assert( evaluate( inst )!=1 );
- Assert( evaluate( inst )==-1 || e>effort_conflict );
- //}
- }
- if( d_quantEngine->addInstantiation( q, terms, false ) ){
- Trace("qcf-check") << " ... Added instantiation" << std::endl;
- Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;
- qi->debugPrintMatch("qcf-inst");
- Trace("qcf-inst") << std::endl;
- ++addedLemmas;
- if( e==effort_conflict ){
- d_quant_order.insert( d_quant_order.begin(), q );
- d_conflict.set( true );
- ++(d_statistics.d_conflict_inst);
- break;
- }else if( e==effort_prop_eq ){
- ++(d_statistics.d_prop_inst);
- }
- }else{
- Trace("qcf-check") << " ... Failed to add instantiation" << std::endl;
- //Assert( false );
- }
- }
- //clean up assigned
- qi->revertMatch( assigned );
- d_tempCache.clear();
- }else{
- Trace("qcf-check") << " ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;
- }
- }else{
- Trace("qcf-check") << " ... Spurious instantiation (match is inconsistent)" << std::endl;
- }
- }
- if( d_conflict ){
- break;
- }
- }
- }
- if( addedLemmas>0 ){
- d_quantEngine->flushLemmas();
- break;
- }
- }
- if( Trace.isOn("qcf-engine") ){
- double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
- Trace("qcf-engine") << "Finished conflict find engine, time = " << (clSet2-clSet);
- if( addedLemmas>0 ){
- Trace("qcf-engine") << ", effort = " << ( d_effort==effort_conflict ? "conflict" : ( d_effort==effort_prop_eq ? "prop_eq" : "mc" ) );
- Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;
- }
- Trace("qcf-engine") << std::endl;
- int currEt = d_statistics.d_entailment_checks.getData();
- if( currEt!=prevEt ){
- Trace("qcf-engine") << " Entailment checks = " << ( currEt - prevEt ) << std::endl;
- }
- }
- }
- Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;
- }
-}
-
-bool QuantConflictFind::needsCheck( Theory::Effort level ) {
- d_performCheck = false;
- if( options::quantConflictFind() && !d_conflict ){
- if( level==Theory::EFFORT_LAST_CALL ){
- d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_LAST_CALL;
- }else if( level==Theory::EFFORT_FULL ){
- d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_DEFAULT;
- }else if( level==Theory::EFFORT_STANDARD ){
- d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_STD;
- }
- }
- return d_performCheck;
-}
-
-void QuantConflictFind::computeRelevantEqr() {
- if( d_needs_computeRelEqr ){
- d_needs_computeRelEqr = false;
- Trace("qcf-check") << "Compute relevant equalities..." << std::endl;
- d_uf_terms.clear();
- d_eqc_uf_terms.clear();
- d_eqcs.clear();
- d_model_basis.clear();
- d_arg_reps.clear();
- //double clSet = 0;
- //if( Trace.isOn("qcf-opt") ){
- // clSet = double(clock())/double(CLOCKS_PER_SEC);
- //}
-
- //long nTermst = 0;
- //long nTerms = 0;
- //long nEqc = 0;
-
- //which nodes are irrelevant for disequality matches
- std::map< TNode, bool > irrelevant_dnode;
- //now, store matches
- eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
- while( !eqcs_i.isFinished() ){
- //nEqc++;
- Node r = (*eqcs_i);
- TypeNode rtn = r.getType();
- if( options::qcfMode()==QCF_MC ){
- std::map< TypeNode, std::vector< TNode > >::iterator itt = d_eqcs.find( rtn );
- if( itt==d_eqcs.end() ){
- Node mb = getQuantifiersEngine()->getTermDatabase()->getModelBasisTerm( rtn );
- if( !getEqualityEngine()->hasTerm( mb ) ){
- Trace("qcf-warn") << "WARNING: Model basis term does not exist!" << std::endl;
- Assert( false );
- }
- Node mbr = getRepresentative( mb );
- if( mbr!=r ){
- d_eqcs[rtn].push_back( mbr );
- }
- d_eqcs[rtn].push_back( r );
- d_model_basis[rtn] = mb;
- }else{
- itt->second.push_back( r );
- }
- }else{
- d_eqcs[rtn].push_back( r );
- }
- /*
- eq::EqClassIterator eqc_i = eq::EqClassIterator( r, getEqualityEngine() );
- while( !eqc_i.isFinished() ){
- TNode n = (*eqc_i);
- if( n.hasBoundVar() ){
- std::cout << "BAD TERM IN DB : " << n << std::endl;
- exit( 199 );
- }
- ++eqc_i;
- }
-
- */
-
- //if( r.getType().isInteger() ){
- // Trace("qcf-mv") << "Model value for eqc(" << r << ") : " << d_quantEngine->getValuation().getModelValue( r ) << std::endl;
- //}
- //EqcInfo * eqcir = getEqcInfo( r, false );
- //get relevant nodes that we are disequal from
- /*
- std::vector< Node > deqc;
- if( eqcir ){
- for( NodeBoolMap::iterator it = eqcir->d_diseq.begin(); it != eqcir->d_diseq.end(); ++it ){
- if( (*it).second ){
- //Node rd = (*it).first;
- //if( rd!=getRepresentative( rd ) ){
- // std::cout << "Bad rep!" << std::endl;
- // exit( 0 );
- //}
- deqc.push_back( (*it).first );
- }
- }
- }
- */
- //process disequalities
- /*
- eq::EqClassIterator eqc_i = eq::EqClassIterator( r, getEqualityEngine() );
- while( !eqc_i.isFinished() ){
- TNode n = (*eqc_i);
- if( n.getKind()!=EQUAL ){
- nTermst++;
- //node_to_rep[n] = r;
- //if( n.getNumChildren()>0 ){
- // if( n.getKind()!=APPLY_UF ){
- // std::cout << n.getKind() << " " << n.getOperator() << " " << n << std::endl;
- // }
- //}
- if( !quantifiers::TermDb::hasBoundVarAttr( n ) ){ //temporary
-
- bool isRedundant;
- std::map< TNode, std::vector< TNode > >::iterator it_na;
- TNode fn;
- if( MatchGen::isHandledUfTerm( n ) ){
- Node f = MatchGen::getOperator( this, n );
- computeArgReps( n );
- it_na = d_arg_reps.find( n );
- Assert( it_na!=d_arg_reps.end() );
- Node nadd = d_eqc_uf_terms[f].d_children[r].addTerm( n, d_arg_reps[n] );
- isRedundant = (nadd!=n);
- d_uf_terms[f].addTerm( n, d_arg_reps[n] );
- }else{
- isRedundant = false;
- }
- nTerms += isRedundant ? 0 : 1;
- }else{
- if( Debug.isOn("qcf-nground") ){
- Debug("qcf-nground") << "Non-ground term in eqc : " << n << std::endl;
- Assert( false );
- }
- }
- }
- ++eqc_i;
- }
- */
- ++eqcs_i;
- }
- /*
- if( Trace.isOn("qcf-opt") ){
- double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
- Trace("qcf-opt") << "Compute rel eqc : " << std::endl;
- Trace("qcf-opt") << " " << nEqc << " equivalence classes. " << std::endl;
- Trace("qcf-opt") << " " << nTerms << " / " << nTermst << " terms." << std::endl;
- Trace("qcf-opt") << " Time : " << (clSet2-clSet) << std::endl;
- }
- */
- }
-}
-
-void QuantConflictFind::computeArgReps( TNode n ) {
- if( d_arg_reps.find( n )==d_arg_reps.end() ){
- Assert( MatchGen::isHandledUfTerm( n ) );
- for( unsigned j=0; j<n.getNumChildren(); j++ ){
- d_arg_reps[n].push_back( getRepresentative( n[j] ) );
- }
- }
-}
-
-void QuantConflictFind::computeUfTerms( TNode f ) {
- if( d_uf_terms.find( f )==d_uf_terms.end() ){
- d_uf_terms[f].clear();
- unsigned nt = d_quantEngine->getTermDatabase()->getNumGroundTerms( f );
- for( unsigned i=0; i<nt; i++ ){
- Node n = d_quantEngine->getTermDatabase()->d_op_map[f][i];
- if( getEqualityEngine()->hasTerm( n ) && !n.getAttribute(NoMatchAttribute()) ){
- Node r = getRepresentative( n );
- computeArgReps( n );
- d_eqc_uf_terms[f].d_children[r].addTerm( n, d_arg_reps[n] );
- d_uf_terms[f].addTerm( n, d_arg_reps[n] );
- }
- }
- }
-}
-
-//-------------------------------------------------- debugging
-
-
-void QuantConflictFind::debugPrint( const char * c ) {
- //print the equivalance classes
- Trace(c) << "----------EQ classes" << std::endl;
- eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );
- while( !eqcs_i.isFinished() ){
- Node n = (*eqcs_i);
- //if( !n.getType().isInteger() ){
- Trace(c) << " - " << n << " : {";
- eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );
- bool pr = false;
- while( !eqc_i.isFinished() ){
- Node nn = (*eqc_i);
- if( nn.getKind()!=EQUAL && nn!=n ){
- Trace(c) << (pr ? "," : "" ) << " " << nn;
- pr = true;
- }
- ++eqc_i;
- }
- Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
- /*
- EqcInfo * eqcn = getEqcInfo( n, false );
- if( eqcn ){
- Trace(c) << " DEQ : {";
- pr = false;
- for( NodeBoolMap::iterator it = eqcn->d_diseq.begin(); it != eqcn->d_diseq.end(); ++it ){
- if( (*it).second ){
- Trace(c) << (pr ? "," : "" ) << " " << (*it).first;
- pr = true;
- }
- }
- Trace(c) << (pr ? " " : "" ) << "}" << std::endl;
- }
- //}
- */
- ++eqcs_i;
- }
-}
-
-void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {
- Trace(c) << "Q" << d_quant_id[q];
-}
-
-void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {
- if( n.getNumChildren()==0 ){
- Trace(c) << n;
- }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){
- Trace(c) << "?x" << d_qinfo[q].d_var_num[n];
- }else{
- Trace(c) << "(";
- if( n.getKind()==APPLY_UF ){
- Trace(c) << n.getOperator();
- }else{
- Trace(c) << n.getKind();
- }
- for( unsigned i=0; i<n.getNumChildren(); i++ ){
- Trace(c) << " ";
- debugPrintQuantBody( c, q, n[i] );
- }
- Trace(c) << ")";
- }
-}
-
-QuantConflictFind::Statistics::Statistics():
- d_inst_rounds("QuantConflictFind::Inst_Rounds", 0),
- d_conflict_inst("QuantConflictFind::Instantiations_Conflict_Find", 0 ),
- d_prop_inst("QuantConflictFind::Instantiations_Prop", 0 ),
- d_entailment_checks("QuantConflictFind::Entailment_Checks",0)
-{
- StatisticsRegistry::registerStat(&d_inst_rounds);
- StatisticsRegistry::registerStat(&d_conflict_inst);
- StatisticsRegistry::registerStat(&d_prop_inst);
- StatisticsRegistry::registerStat(&d_entailment_checks);
-}
-
-QuantConflictFind::Statistics::~Statistics(){
- StatisticsRegistry::unregisterStat(&d_inst_rounds);
- StatisticsRegistry::unregisterStat(&d_conflict_inst);
- StatisticsRegistry::unregisterStat(&d_prop_inst);
- StatisticsRegistry::unregisterStat(&d_entailment_checks);
-}
-
-TNode QuantConflictFind::getZero( Kind k ) {
- std::map< Kind, Node >::iterator it = d_zero.find( k );
- if( it==d_zero.end() ){
- Node nn;
- if( k==PLUS ){
- nn = NodeManager::currentNM()->mkConst( Rational(0) );
- }
- d_zero[k] = nn;
- return nn;
- }else{
- return it->second;
- }
-}
-
-
-}
+/********************* */\r
+/*! \file quant_conflict_find.cpp\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2014 New York University and The University of Iowa\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief quant conflict find class\r
+ **\r
+ **/\r
+\r
+#include <vector>\r
+\r
+#include "theory/quantifiers/quant_conflict_find.h"\r
+#include "theory/quantifiers/quant_util.h"\r
+#include "theory/theory_engine.h"\r
+#include "theory/quantifiers/options.h"\r
+#include "theory/quantifiers/term_database.h"\r
+#include "theory/quantifiers/trigger.h"\r
+\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+using namespace std;\r
+\r
+namespace CVC4 {\r
+\r
+\r
+\r
+void QuantInfo::initialize( Node q, Node qn ) {\r
+ d_q = q;\r
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){\r
+ d_match.push_back( TNode::null() );\r
+ d_match_term.push_back( TNode::null() );\r
+ }\r
+\r
+ //register the variables\r
+ for( unsigned i=0; i<q[0].getNumChildren(); i++ ){\r
+ d_var_num[q[0][i]] = i;\r
+ d_vars.push_back( q[0][i] );\r
+ }\r
+\r
+ registerNode( qn, true, true );\r
+\r
+\r
+ Trace("qcf-qregister") << "- Make match gen structure..." << std::endl;\r
+ d_mg = new MatchGen( this, qn );\r
+\r
+ if( d_mg->isValid() ){\r
+ /*\r
+ for( unsigned j=0; j<q[0].getNumChildren(); j++ ){\r
+ if( d_inMatchConstraint.find( q[0][j] )==d_inMatchConstraint.end() ){\r
+ Trace("qcf-invalid") << "QCF invalid : variable " << q[0][j] << " does not exist in a matching constraint." << std::endl;\r
+ d_mg->setInvalid();\r
+ break;\r
+ }\r
+ }\r
+ */\r
+ if( d_mg->isValid() ){\r
+ for( unsigned j=q[0].getNumChildren(); j<d_vars.size(); j++ ){\r
+ if( d_vars[j].getKind()!=BOUND_VARIABLE ){\r
+ d_var_mg[j] = NULL;\r
+ bool is_tsym = false;\r
+ if( !MatchGen::isHandledUfTerm( d_vars[j] ) && d_vars[j].getKind()!=ITE ){\r
+ is_tsym = true;\r
+ d_tsym_vars.push_back( j );\r
+ }\r
+ if( !is_tsym || options::qcfTConstraint() ){\r
+ d_var_mg[j] = new MatchGen( this, d_vars[j], true );\r
+ }\r
+ if( !d_var_mg[j] || !d_var_mg[j]->isValid() ){\r
+ Trace("qcf-invalid") << "QCF invalid : cannot match for " << d_vars[j] << std::endl;\r
+ d_mg->setInvalid();\r
+ break;\r
+ }else{\r
+ std::vector< int > bvars;\r
+ d_var_mg[j]->determineVariableOrder( this, bvars );\r
+ }\r
+ }\r
+ }\r
+ if( d_mg->isValid() ){\r
+ std::vector< int > bvars;\r
+ d_mg->determineVariableOrder( this, bvars );\r
+ }\r
+ }\r
+ }else{\r
+ Trace("qcf-invalid") << "QCF invalid : body of formula cannot be processed." << std::endl;\r
+ }\r
+ Trace("qcf-qregister-summary") << "QCF register : " << ( d_mg->isValid() ? "VALID " : "INVALID" ) << " : " << q << std::endl;\r
+}\r
+\r
+void QuantInfo::registerNode( Node n, bool hasPol, bool pol, bool beneathQuant ) {\r
+ Trace("qcf-qregister-debug2") << "Register : " << n << std::endl;\r
+ if( n.getKind()==FORALL ){\r
+ registerNode( n[1], hasPol, pol, true );\r
+ }else{\r
+ if( !MatchGen::isHandledBoolConnective( n ) ){\r
+ if( n.hasBoundVar() ){\r
+ //literals\r
+ if( n.getKind()==EQUAL ){\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ flatten( n[i], beneathQuant );\r
+ }\r
+ }else if( MatchGen::isHandledUfTerm( n ) ){\r
+ flatten( n, beneathQuant );\r
+ }else if( n.getKind()==ITE ){\r
+ for( unsigned i=1; i<=2; i++ ){\r
+ flatten( n[i], beneathQuant );\r
+ }\r
+ registerNode( n[0], false, pol, beneathQuant );\r
+ }else if( options::qcfTConstraint() ){\r
+ //a theory-specific predicate\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ flatten( n[i], beneathQuant );\r
+ }\r
+ }\r
+ }\r
+ }else{\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ bool newHasPol;\r
+ bool newPol;\r
+ QuantPhaseReq::getPolarity( n, i, hasPol, pol, newHasPol, newPol );\r
+ //QcfNode * qcfc = new QcfNode( d_c );\r
+ //qcfc->d_parent = qcf;\r
+ //qcf->d_child[i] = qcfc;\r
+ registerNode( n[i], newHasPol, newPol, beneathQuant );\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void QuantInfo::flatten( Node n, bool beneathQuant ) {\r
+ Trace("qcf-qregister-debug2") << "Flatten : " << n << std::endl;\r
+ if( n.hasBoundVar() ){\r
+ if( n.getKind()==BOUND_VARIABLE ){\r
+ d_inMatchConstraint[n] = true;\r
+ }\r
+ //if( MatchGen::isHandledUfTerm( n ) || n.getKind()==ITE ){\r
+ if( d_var_num.find( n )==d_var_num.end() ){\r
+ Trace("qcf-qregister-debug2") << "Add FLATTEN VAR : " << n << std::endl;\r
+ d_var_num[n] = d_vars.size();\r
+ d_vars.push_back( n );\r
+ d_match.push_back( TNode::null() );\r
+ d_match_term.push_back( TNode::null() );\r
+ if( n.getKind()==ITE ){\r
+ registerNode( n, false, false );\r
+ }else{\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ flatten( n[i], beneathQuant );\r
+ }\r
+ }\r
+ }else{\r
+ Trace("qcf-qregister-debug2") << "...already processed" << std::endl;\r
+ }\r
+ }else{\r
+ Trace("qcf-qregister-debug2") << "...is ground." << std::endl;\r
+ }\r
+}\r
+\r
+\r
+void QuantInfo::reset_round( QuantConflictFind * p ) {\r
+ for( unsigned i=0; i<d_match.size(); i++ ){\r
+ d_match[i] = TNode::null();\r
+ d_match_term[i] = TNode::null();\r
+ }\r
+ d_curr_var_deq.clear();\r
+ d_tconstraints.clear();\r
+ //add built-in variable constraints\r
+ for( unsigned r=0; r<2; r++ ){\r
+ for( std::map< int, std::vector< Node > >::iterator it = d_var_constraint[r].begin();\r
+ it != d_var_constraint[r].end(); ++it ){\r
+ for( unsigned j=0; j<it->second.size(); j++ ){\r
+ Node rr = it->second[j];\r
+ if( !isVar( rr ) ){\r
+ rr = p->getRepresentative( rr );\r
+ }\r
+ if( addConstraint( p, it->first, rr, r==0 )==-1 ){\r
+ d_var_constraint[0].clear();\r
+ d_var_constraint[1].clear();\r
+ //quantified formula is actually equivalent to true\r
+ Trace("qcf-qregister") << "Quantifier is equivalent to true!!!" << std::endl;\r
+ d_mg->d_children.clear();\r
+ d_mg->d_n = NodeManager::currentNM()->mkConst( true );\r
+ d_mg->d_type = MatchGen::typ_ground;\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ d_mg->reset_round( p );\r
+ for( std::map< int, MatchGen * >::iterator it = d_var_mg.begin(); it != d_var_mg.end(); ++it ){\r
+ it->second->reset_round( p );\r
+ }\r
+ //now, reset for matching\r
+ d_mg->reset( p, false, this );\r
+}\r
+\r
+int QuantInfo::getCurrentRepVar( int v ) {\r
+ if( v!=-1 && !d_match[v].isNull() ){\r
+ int vn = getVarNum( d_match[v] );\r
+ if( vn!=-1 ){\r
+ //int vr = getCurrentRepVar( vn );\r
+ //d_match[v] = d_vars[vr];\r
+ //return vr;\r
+ return getCurrentRepVar( vn );\r
+ }\r
+ }\r
+ return v;\r
+}\r
+\r
+TNode QuantInfo::getCurrentValue( TNode n ) {\r
+ int v = getVarNum( n );\r
+ if( v==-1 ){\r
+ return n;\r
+ }else{\r
+ if( d_match[v].isNull() ){\r
+ return n;\r
+ }else{\r
+ Assert( getVarNum( d_match[v] )!=v );\r
+ return getCurrentValue( d_match[v] );\r
+ }\r
+ }\r
+}\r
+\r
+TNode QuantInfo::getCurrentExpValue( TNode n ) {\r
+ int v = getVarNum( n );\r
+ if( v==-1 ){\r
+ return n;\r
+ }else{\r
+ if( d_match[v].isNull() ){\r
+ return n;\r
+ }else{\r
+ Assert( getVarNum( d_match[v] )!=v );\r
+ if( d_match_term[v].isNull() ){\r
+ return getCurrentValue( d_match[v] );\r
+ }else{\r
+ return d_match_term[v];\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+bool QuantInfo::getCurrentCanBeEqual( QuantConflictFind * p, int v, TNode n, bool chDiseq ) {\r
+ //check disequalities\r
+ std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );\r
+ if( itd!=d_curr_var_deq.end() ){\r
+ for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){\r
+ Node cv = getCurrentValue( it->first );\r
+ Debug("qcf-ccbe") << "compare " << cv << " " << n << std::endl;\r
+ if( cv==n ){\r
+ return false;\r
+ }else if( chDiseq && !isVar( n ) && !isVar( cv ) ){\r
+ //they must actually be disequal if we are looking for conflicts\r
+ if( !p->areDisequal( n, cv ) ){\r
+ //TODO : check for entailed disequal\r
+\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return true;\r
+}\r
+\r
+int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, bool polarity ) {\r
+ v = getCurrentRepVar( v );\r
+ int vn = getVarNum( n );\r
+ vn = vn==-1 ? -1 : getCurrentRepVar( vn );\r
+ n = getCurrentValue( n );\r
+ return addConstraint( p, v, n, vn, polarity, false );\r
+}\r
+\r
+int QuantInfo::addConstraint( QuantConflictFind * p, int v, TNode n, int vn, bool polarity, bool doRemove ) {\r
+ //for handling equalities between variables, and disequalities involving variables\r
+ Debug("qcf-match-debug") << "- " << (doRemove ? "un" : "" ) << "constrain : " << v << " -> " << n << " (cv=" << getCurrentValue( n ) << ")";\r
+ Debug("qcf-match-debug") << ", (vn=" << vn << "), polarity = " << polarity << std::endl;\r
+ Assert( doRemove || n==getCurrentValue( n ) );\r
+ Assert( doRemove || v==getCurrentRepVar( v ) );\r
+ Assert( doRemove || vn==getCurrentRepVar( getVarNum( n ) ) );\r
+ if( polarity ){\r
+ if( vn!=v ){\r
+ if( doRemove ){\r
+ if( vn!=-1 ){\r
+ //if set to this in the opposite direction, clean up opposite instead\r
+ // std::map< int, TNode >::iterator itmn = d_match.find( vn );\r
+ if( d_match[vn]==d_vars[v] ){\r
+ return addConstraint( p, vn, d_vars[v], v, true, true );\r
+ }else{\r
+ //unsetting variables equal\r
+ std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( vn );\r
+ if( itd!=d_curr_var_deq.end() ){\r
+ //remove disequalities owned by this\r
+ std::vector< TNode > remDeq;\r
+ for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){\r
+ if( it->second==v ){\r
+ remDeq.push_back( it->first );\r
+ }\r
+ }\r
+ for( unsigned i=0; i<remDeq.size(); i++ ){\r
+ d_curr_var_deq[vn].erase( remDeq[i] );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ d_match[v] = TNode::null();\r
+ return 1;\r
+ }else{\r
+ //std::map< int, TNode >::iterator itm = d_match.find( v );\r
+\r
+ if( vn!=-1 ){\r
+ Debug("qcf-match-debug") << " ...Variable bound to variable" << std::endl;\r
+ //std::map< int, TNode >::iterator itmn = d_match.find( vn );\r
+ if( d_match[v].isNull() ){\r
+ //setting variables equal\r
+ bool alreadySet = false;\r
+ if( !d_match[vn].isNull() ){\r
+ alreadySet = true;\r
+ Assert( !isVar( d_match[vn] ) );\r
+ }\r
+\r
+ //copy or check disequalities\r
+ std::map< int, std::map< TNode, int > >::iterator itd = d_curr_var_deq.find( v );\r
+ if( itd!=d_curr_var_deq.end() ){\r
+ for( std::map< TNode, int >::iterator it = itd->second.begin(); it != itd->second.end(); ++it ){\r
+ Node dv = getCurrentValue( it->first );\r
+ if( !alreadySet ){\r
+ if( d_curr_var_deq[vn].find( dv )==d_curr_var_deq[vn].end() ){\r
+ d_curr_var_deq[vn][dv] = v;\r
+ }\r
+ }else{\r
+ if( !p->areMatchDisequal( d_match[vn], dv ) ){\r
+ Debug("qcf-match-debug") << " -> fail, conflicting disequality" << std::endl;\r
+ return -1;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if( alreadySet ){\r
+ n = getCurrentValue( n );\r
+ }\r
+ }else{\r
+ if( d_match[vn].isNull() ){\r
+ Debug("qcf-match-debug") << " ...Reverse direction" << std::endl;\r
+ //set the opposite direction\r
+ return addConstraint( p, vn, d_vars[v], v, true, false );\r
+ }else{\r
+ Debug("qcf-match-debug") << " -> Both variables bound, compare" << std::endl;\r
+ //are they currently equal\r
+ return p->areMatchEqual( d_match[v], d_match[vn] ) ? 0 : -1;\r
+ }\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " ...Variable bound to ground" << std::endl;\r
+ if( d_match[v].isNull() ){\r
+ }else{\r
+ //compare ground values\r
+ Debug("qcf-match-debug") << " -> Ground value, compare " << d_match[v] << " "<< n << std::endl;\r
+ return p->areMatchEqual( d_match[v], n ) ? 0 : -1;\r
+ }\r
+ }\r
+ if( setMatch( p, v, n ) ){\r
+ Debug("qcf-match-debug") << " -> success" << std::endl;\r
+ return 1;\r
+ }else{\r
+ Debug("qcf-match-debug") << " -> fail, conflicting disequality" << std::endl;\r
+ return -1;\r
+ }\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " -> redundant, variable identity" << std::endl;\r
+ return 0;\r
+ }\r
+ }else{\r
+ if( vn==v ){\r
+ Debug("qcf-match-debug") << " -> fail, variable identity" << std::endl;\r
+ return -1;\r
+ }else{\r
+ if( doRemove ){\r
+ Assert( d_curr_var_deq[v].find( n )!=d_curr_var_deq[v].end() );\r
+ d_curr_var_deq[v].erase( n );\r
+ return 1;\r
+ }else{\r
+ if( d_curr_var_deq[v].find( n )==d_curr_var_deq[v].end() ){\r
+ //check if it respects equality\r
+ //std::map< int, TNode >::iterator itm = d_match.find( v );\r
+ if( !d_match[v].isNull() ){\r
+ TNode nv = getCurrentValue( n );\r
+ if( !p->areMatchDisequal( nv, d_match[v] ) ){\r
+ Debug("qcf-match-debug") << " -> fail, conflicting disequality" << std::endl;\r
+ return -1;\r
+ }\r
+ }\r
+ d_curr_var_deq[v][n] = v;\r
+ Debug("qcf-match-debug") << " -> success" << std::endl;\r
+ return 1;\r
+ }else{\r
+ Debug("qcf-match-debug") << " -> redundant disequality" << std::endl;\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+bool QuantInfo::isConstrainedVar( int v ) {\r
+ if( d_curr_var_deq.find( v )!=d_curr_var_deq.end() && !d_curr_var_deq[v].empty() ){\r
+ return true;\r
+ }else{\r
+ Node vv = getVar( v );\r
+ //for( std::map< int, TNode >::iterator it = d_match.begin(); it != d_match.end(); ++it ){\r
+ for( unsigned i=0; i<d_match.size(); i++ ){\r
+ if( d_match[i]==vv ){\r
+ return true;\r
+ }\r
+ }\r
+ for( std::map< int, std::map< TNode, int > >::iterator it = d_curr_var_deq.begin(); it != d_curr_var_deq.end(); ++it ){\r
+ for( std::map< TNode, int >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
+ if( it2->first==vv ){\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+}\r
+\r
+bool QuantInfo::setMatch( QuantConflictFind * p, int v, TNode n ) {\r
+ if( getCurrentCanBeEqual( p, v, n ) ){\r
+ Debug("qcf-match-debug") << "-- bind : " << v << " -> " << n << ", checked " << d_curr_var_deq[v].size() << " disequalities" << std::endl;\r
+ d_match[v] = n;\r
+ return true;\r
+ }else{\r
+ return false;\r
+ }\r
+}\r
+\r
+bool QuantInfo::isMatchSpurious( QuantConflictFind * p ) {\r
+ for( int i=0; i<getNumVars(); i++ ){\r
+ //std::map< int, TNode >::iterator it = d_match.find( i );\r
+ if( !d_match[i].isNull() ){\r
+ if( !getCurrentCanBeEqual( p, i, d_match[i], p->d_effort==QuantConflictFind::effort_conflict ) ){\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+ return false;\r
+}\r
+\r
+bool QuantInfo::isTConstraintSpurious( QuantConflictFind * p, std::vector< Node >& terms ) {\r
+ if( !d_tconstraints.empty() ){\r
+ //check constraints\r
+ for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){\r
+ //apply substitution to the tconstraint\r
+ Node cons = it->first.substitute( p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].begin(),\r
+ p->getQuantifiersEngine()->getTermDatabase()->d_vars[d_q].end(),\r
+ terms.begin(), terms.end() );\r
+ cons = it->second ? cons : cons.negate();\r
+ if( !entailmentTest( p, cons, p->d_effort==QuantConflictFind::effort_conflict ) ){\r
+ return true;\r
+ }\r
+ }\r
+ }\r
+ return false;\r
+}\r
+\r
+bool QuantInfo::entailmentTest( QuantConflictFind * p, Node lit, bool chEnt ) {\r
+ Trace("qcf-tconstraint-debug") << "Check : " << lit << std::endl;\r
+ Node rew = Rewriter::rewrite( lit );\r
+ if( rew==p->d_false ){\r
+ Trace("qcf-tconstraint-debug") << "...constraint " << lit << " is disentailed (rewrites to false)." << std::endl;\r
+ return false;\r
+ }else if( rew!=p->d_true ){\r
+ //if checking for conflicts, we must be sure that the constraint is entailed\r
+ if( chEnt ){\r
+ //check if it is entailed\r
+ Trace("qcf-tconstraint-debug") << "Check entailment of " << rew << "..." << std::endl;\r
+ std::pair<bool, Node> et = p->getQuantifiersEngine()->getTheoryEngine()->entailmentCheck(THEORY_OF_TYPE_BASED, rew );\r
+ ++(p->d_statistics.d_entailment_checks);\r
+ Trace("qcf-tconstraint-debug") << "ET result : " << et.first << " " << et.second << std::endl;\r
+ if( !et.first ){\r
+ Trace("qcf-tconstraint-debug") << "...cannot show entailment of " << rew << "." << std::endl;\r
+ return false;\r
+ }else{\r
+ return true;\r
+ }\r
+ }else{\r
+ Trace("qcf-tconstraint-debug") << "...does not need to be entailed." << std::endl;\r
+ return true;\r
+ }\r
+ }else{\r
+ Trace("qcf-tconstraint-debug") << "...rewrites to true." << std::endl;\r
+ return true;\r
+ }\r
+}\r
+\r
+bool QuantInfo::completeMatch( QuantConflictFind * p, std::vector< int >& assigned, bool doContinue ) {\r
+ //assign values for variables that were unassigned (usually not necessary, but handles corner cases)\r
+ bool doFail = false;\r
+ bool success = true;\r
+ if( doContinue ){\r
+ doFail = true;\r
+ success = false;\r
+ }else{\r
+ //solve for interpreted symbol matches\r
+ // this breaks the invariant that all introduced constraints are over existing terms\r
+ for( int i=(int)(d_tsym_vars.size()-1); i>=0; i-- ){\r
+ int index = d_tsym_vars[i];\r
+ TNode v = getCurrentValue( d_vars[index] );\r
+ int slv_v = -1;\r
+ if( v==d_vars[index] ){\r
+ slv_v = index;\r
+ }\r
+ Trace("qcf-tconstraint-debug") << "Solve " << d_vars[index] << " = " << v << " " << d_vars[index].getKind() << std::endl;\r
+ if( d_vars[index].getKind()==PLUS || d_vars[index].getKind()==MULT ){\r
+ Kind k = d_vars[index].getKind();\r
+ std::vector< TNode > children;\r
+ for( unsigned j=0; j<d_vars[index].getNumChildren(); j++ ){\r
+ int vn = getVarNum( d_vars[index][j] );\r
+ if( vn!=-1 ){\r
+ TNode vv = getCurrentValue( d_vars[index][j] );\r
+ if( vv==d_vars[index][j] ){\r
+ //we will assign this\r
+ if( slv_v==-1 ){\r
+ Trace("qcf-tconstraint-debug") << "...will solve for var #" << vn << std::endl;\r
+ slv_v = vn;\r
+ if( p->d_effort!=QuantConflictFind::effort_conflict ){\r
+ break;\r
+ }\r
+ }else{\r
+ Node z = p->getZero( k );\r
+ if( !z.isNull() ){\r
+ Trace("qcf-tconstraint-debug") << "...set " << d_vars[vn] << " = " << z << std::endl;\r
+ assigned.push_back( vn );\r
+ if( !setMatch( p, vn, z ) ){\r
+ success = false;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }else{\r
+ Trace("qcf-tconstraint-debug") << "...sum value " << vv << std::endl;\r
+ children.push_back( vv );\r
+ }\r
+ }else{\r
+ Trace("qcf-tconstraint-debug") << "...sum " << d_vars[index][j] << std::endl;\r
+ children.push_back( d_vars[index][j] );\r
+ }\r
+ }\r
+ if( success ){\r
+ if( slv_v!=-1 ){\r
+ Node lhs;\r
+ if( children.empty() ){\r
+ lhs = p->getZero( k );\r
+ }else if( children.size()==1 ){\r
+ lhs = children[0];\r
+ }else{\r
+ lhs = NodeManager::currentNM()->mkNode( k, children );\r
+ }\r
+ Node sum;\r
+ if( v==d_vars[index] ){\r
+ sum = lhs;\r
+ }else{\r
+ if( p->d_effort==QuantConflictFind::effort_conflict ){\r
+ Kind kn = k;\r
+ if( d_vars[index].getKind()==PLUS ){\r
+ kn = MINUS;\r
+ }\r
+ if( kn!=k ){\r
+ sum = NodeManager::currentNM()->mkNode( kn, v, lhs );\r
+ }\r
+ }\r
+ }\r
+ if( !sum.isNull() ){\r
+ assigned.push_back( slv_v );\r
+ Trace("qcf-tconstraint-debug") << "...set " << d_vars[slv_v] << " = " << sum << std::endl;\r
+ if( !setMatch( p, slv_v, sum ) ){\r
+ success = false;\r
+ }\r
+ p->d_tempCache.push_back( sum );\r
+ }\r
+ }else{\r
+ //must show that constraint is met\r
+ Node sum = NodeManager::currentNM()->mkNode( k, children );\r
+ Node eq = sum.eqNode( v );\r
+ if( !entailmentTest( p, eq ) ){\r
+ success = false;\r
+ }\r
+ p->d_tempCache.push_back( sum );\r
+ }\r
+ }\r
+ }\r
+\r
+ if( !success ){\r
+ break;\r
+ }\r
+ }\r
+ if( success ){\r
+ //check what is left to assign\r
+ d_unassigned.clear();\r
+ d_unassigned_tn.clear();\r
+ std::vector< int > unassigned[2];\r
+ std::vector< TypeNode > unassigned_tn[2];\r
+ for( int i=0; i<getNumVars(); i++ ){\r
+ if( d_match[i].isNull() ){\r
+ int rindex = d_var_mg.find( i )==d_var_mg.end() ? 1 : 0;\r
+ unassigned[rindex].push_back( i );\r
+ unassigned_tn[rindex].push_back( getVar( i ).getType() );\r
+ assigned.push_back( i );\r
+ }\r
+ }\r
+ d_unassigned_nvar = unassigned[0].size();\r
+ for( unsigned i=0; i<2; i++ ){\r
+ d_unassigned.insert( d_unassigned.end(), unassigned[i].begin(), unassigned[i].end() );\r
+ d_unassigned_tn.insert( d_unassigned_tn.end(), unassigned_tn[i].begin(), unassigned_tn[i].end() );\r
+ }\r
+ d_una_eqc_count.clear();\r
+ d_una_index = 0;\r
+ }\r
+ }\r
+\r
+ if( !d_unassigned.empty() && ( success || doContinue ) ){\r
+ Trace("qcf-check") << "Assign to unassigned..." << std::endl;\r
+ do {\r
+ if( doFail ){\r
+ Trace("qcf-check-unassign") << "Failure, try again..." << std::endl;\r
+ }\r
+ bool invalidMatch = false;\r
+ while( ( d_una_index>=0 && (int)d_una_index<(int)d_unassigned.size() ) || invalidMatch || doFail ){\r
+ invalidMatch = false;\r
+ if( !doFail && d_una_index==(int)d_una_eqc_count.size() ){\r
+ //check if it has now been assigned\r
+ if( d_una_index<d_unassigned_nvar ){\r
+ if( !isConstrainedVar( d_unassigned[d_una_index] ) ){\r
+ d_una_eqc_count.push_back( -1 );\r
+ }else{\r
+ d_var_mg[ d_unassigned[d_una_index] ]->reset( p, true, this );\r
+ d_una_eqc_count.push_back( 0 );\r
+ }\r
+ }else{\r
+ d_una_eqc_count.push_back( 0 );\r
+ }\r
+ }else{\r
+ bool failed = false;\r
+ if( !doFail ){\r
+ if( d_una_index<d_unassigned_nvar ){\r
+ if( !isConstrainedVar( d_unassigned[d_una_index] ) ){\r
+ Trace("qcf-check-unassign") << "Succeeded, variable unconstrained at " << d_una_index << std::endl;\r
+ d_una_index++;\r
+ }else if( d_var_mg[d_unassigned[d_una_index]]->getNextMatch( p, this ) ){\r
+ Trace("qcf-check-unassign") << "Succeeded match with mg at " << d_una_index << std::endl;\r
+ d_una_index++;\r
+ }else{\r
+ failed = true;\r
+ Trace("qcf-check-unassign") << "Failed match with mg at " << d_una_index << std::endl;\r
+ }\r
+ }else{\r
+ Assert( doFail || d_una_index==(int)d_una_eqc_count.size()-1 );\r
+ if( d_una_eqc_count[d_una_index]<(int)p->d_eqcs[d_unassigned_tn[d_una_index]].size() ){\r
+ int currIndex = d_una_eqc_count[d_una_index];\r
+ d_una_eqc_count[d_una_index]++;\r
+ Trace("qcf-check-unassign") << d_unassigned[d_una_index] << "->" << p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] << std::endl;\r
+ if( setMatch( p, d_unassigned[d_una_index], p->d_eqcs[d_unassigned_tn[d_una_index]][currIndex] ) ){\r
+ d_match_term[d_unassigned[d_una_index]] = TNode::null();\r
+ Trace("qcf-check-unassign") << "Succeeded match " << d_una_index << std::endl;\r
+ d_una_index++;\r
+ }else{\r
+ Trace("qcf-check-unassign") << "Failed match " << d_una_index << std::endl;\r
+ invalidMatch = true;\r
+ }\r
+ }else{\r
+ failed = true;\r
+ Trace("qcf-check-unassign") << "No more matches " << d_una_index << std::endl;\r
+ }\r
+ }\r
+ }\r
+ if( doFail || failed ){\r
+ do{\r
+ if( !doFail ){\r
+ d_una_eqc_count.pop_back();\r
+ }else{\r
+ doFail = false;\r
+ }\r
+ d_una_index--;\r
+ }while( d_una_index>=0 && d_una_eqc_count[d_una_index]==-1 );\r
+ }\r
+ }\r
+ }\r
+ success = d_una_index>=0;\r
+ if( success ){\r
+ doFail = true;\r
+ Trace("qcf-check-unassign") << " Try: " << std::endl;\r
+ for( unsigned i=0; i<d_unassigned.size(); i++ ){\r
+ int ui = d_unassigned[i];\r
+ if( !d_match[ui].isNull() ){\r
+ Trace("qcf-check-unassign") << " Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;\r
+ }\r
+ }\r
+ }\r
+ }while( success && isMatchSpurious( p ) );\r
+ }\r
+ if( success ){\r
+ for( unsigned i=0; i<d_unassigned.size(); i++ ){\r
+ int ui = d_unassigned[i];\r
+ if( !d_match[ui].isNull() ){\r
+ Trace("qcf-check") << " Assigned #" << ui << " : " << d_vars[ui] << " -> " << d_match[ui] << std::endl;\r
+ }\r
+ }\r
+ return true;\r
+ }else{\r
+ for( unsigned i=0; i<assigned.size(); i++ ){\r
+ d_match[ assigned[i] ] = TNode::null();\r
+ }\r
+ assigned.clear();\r
+ return false;\r
+ }\r
+}\r
+\r
+void QuantInfo::getMatch( std::vector< Node >& terms ){\r
+ for( unsigned i=0; i<d_q[0].getNumChildren(); i++ ){\r
+ //Node cv = qi->getCurrentValue( qi->d_match[i] );\r
+ int repVar = getCurrentRepVar( i );\r
+ Node cv;\r
+ //std::map< int, TNode >::iterator itmt = qi->d_match_term.find( repVar );\r
+ if( !d_match_term[repVar].isNull() ){\r
+ cv = d_match_term[repVar];\r
+ }else{\r
+ cv = d_match[repVar];\r
+ }\r
+ Debug("qcf-check-inst") << "INST : " << i << " -> " << cv << ", from " << d_match[i] << std::endl;\r
+ terms.push_back( cv );\r
+ }\r
+}\r
+\r
+void QuantInfo::revertMatch( std::vector< int >& assigned ) {\r
+ for( unsigned i=0; i<assigned.size(); i++ ){\r
+ d_match[ assigned[i] ] = TNode::null();\r
+ }\r
+}\r
+\r
+void QuantInfo::debugPrintMatch( const char * c ) {\r
+ for( int i=0; i<getNumVars(); i++ ){\r
+ Trace(c) << " " << d_vars[i] << " -> ";\r
+ if( !d_match[i].isNull() ){\r
+ Trace(c) << d_match[i];\r
+ }else{\r
+ Trace(c) << "(unassigned) ";\r
+ }\r
+ if( !d_curr_var_deq[i].empty() ){\r
+ Trace(c) << ", DEQ{ ";\r
+ for( std::map< TNode, int >::iterator it = d_curr_var_deq[i].begin(); it != d_curr_var_deq[i].end(); ++it ){\r
+ Trace(c) << it->first << " ";\r
+ }\r
+ Trace(c) << "}";\r
+ }\r
+ if( !d_match_term[i].isNull() && d_match_term[i]!=d_match[i] ){\r
+ Trace(c) << ", EXP : " << d_match_term[i];\r
+ }\r
+ Trace(c) << std::endl;\r
+ }\r
+ if( !d_tconstraints.empty() ){\r
+ Trace(c) << "ADDITIONAL CONSTRAINTS : " << std::endl;\r
+ for( std::map< Node, bool >::iterator it = d_tconstraints.begin(); it != d_tconstraints.end(); ++it ){\r
+ Trace(c) << " " << it->first << " -> " << it->second << std::endl;\r
+ }\r
+ }\r
+}\r
+\r
+MatchGen::MatchGen( QuantInfo * qi, Node n, bool isVar ){\r
+ Trace("qcf-qregister-debug") << "Make match gen for " << n << ", isVar = " << isVar << std::endl;\r
+ std::vector< Node > qni_apps;\r
+ d_qni_size = 0;\r
+ if( isVar ){\r
+ Assert( qi->d_var_num.find( n )!=qi->d_var_num.end() );\r
+ if( n.getKind()==ITE ){\r
+ d_type = typ_ite_var;\r
+ d_type_not = false;\r
+ d_n = n;\r
+ d_children.push_back( MatchGen( qi, d_n[0] ) );\r
+ if( d_children[0].isValid() ){\r
+ d_type = typ_ite_var;\r
+ for( unsigned i=1; i<=2; i++ ){\r
+ Node nn = n.eqNode( n[i] );\r
+ d_children.push_back( MatchGen( qi, nn ) );\r
+ d_children[d_children.size()-1].d_qni_bound_except.push_back( 0 );\r
+ if( !d_children[d_children.size()-1].isValid() ){\r
+ setInvalid();\r
+ break;\r
+ }\r
+ }\r
+ }else{\r
+ d_type = typ_invalid;\r
+ }\r
+ }else{\r
+ d_type = isHandledUfTerm( n ) ? typ_var : typ_tsym;\r
+ d_qni_var_num[0] = qi->getVarNum( n );\r
+ d_qni_size++;\r
+ d_type_not = false;\r
+ d_n = n;\r
+ //Node f = getOperator( n );\r
+ for( unsigned j=0; j<d_n.getNumChildren(); j++ ){\r
+ Node nn = d_n[j];\r
+ Trace("qcf-qregister-debug") << " " << d_qni_size;\r
+ if( qi->isVar( nn ) ){\r
+ int v = qi->d_var_num[nn];\r
+ Trace("qcf-qregister-debug") << " is var #" << v << std::endl;\r
+ d_qni_var_num[d_qni_size] = v;\r
+ //qi->addFuncParent( v, f, j );\r
+ }else{\r
+ Trace("qcf-qregister-debug") << " is gterm " << nn << std::endl;\r
+ d_qni_gterm[d_qni_size] = nn;\r
+ }\r
+ d_qni_size++;\r
+ }\r
+ }\r
+ }else{\r
+ if( n.hasBoundVar() ){\r
+ d_type_not = false;\r
+ d_n = n;\r
+ if( d_n.getKind()==NOT ){\r
+ d_n = d_n[0];\r
+ d_type_not = !d_type_not;\r
+ }\r
+\r
+ if( isHandledBoolConnective( d_n ) ){\r
+ //non-literals\r
+ d_type = typ_formula;\r
+ for( unsigned i=0; i<d_n.getNumChildren(); i++ ){\r
+ if( d_n.getKind()!=FORALL || i==1 ){\r
+ d_children.push_back( MatchGen( qi, d_n[i], false ) );\r
+ if( !d_children[d_children.size()-1].isValid() ){\r
+ setInvalid();\r
+ break;\r
+ }\r
+ }\r
+ /*\r
+ else if( isTop && n.getKind()==OR && d_children[d_children.size()-1].d_type==typ_var_eq ){\r
+ Trace("qcf-qregister-debug") << "Remove child, make built-in constraint" << std::endl;\r
+ //if variable equality/disequality at top level, remove immediately\r
+ bool cIsNot = d_children[d_children.size()-1].d_type_not;\r
+ Node cn = d_children[d_children.size()-1].d_n;\r
+ Assert( cn.getKind()==EQUAL );\r
+ Assert( p->d_qinfo[q].isVar( cn[0] ) || p->d_qinfo[q].isVar( cn[1] ) );\r
+ //make it a built-in constraint instead\r
+ for( unsigned i=0; i<2; i++ ){\r
+ if( p->d_qinfo[q].isVar( cn[i] ) ){\r
+ int v = p->d_qinfo[q].getVarNum( cn[i] );\r
+ Node cno = cn[i==0 ? 1 : 0];\r
+ p->d_qinfo[q].d_var_constraint[ cIsNot ? 0 : 1 ][v].push_back( cno );\r
+ break;\r
+ }\r
+ }\r
+ d_children.pop_back();\r
+ }\r
+ */\r
+ }\r
+ }else{\r
+ d_type = typ_invalid;\r
+ //literals\r
+ if( isHandledUfTerm( d_n ) ){\r
+ Assert( qi->isVar( d_n ) );\r
+ d_type = typ_pred;\r
+ }else if( d_n.getKind()==BOUND_VARIABLE ){\r
+ Assert( d_n.getType().isBoolean() );\r
+ d_type = typ_bool_var;\r
+ }else if( d_n.getKind()==EQUAL || options::qcfTConstraint() ){\r
+ for( unsigned i=0; i<d_n.getNumChildren(); i++ ){\r
+ if( d_n[i].hasBoundVar() ){\r
+ if( !qi->isVar( d_n[i] ) ){\r
+ Trace("qcf-qregister-debug") << "ERROR : not var " << d_n[i] << std::endl;\r
+ }\r
+ Assert( qi->isVar( d_n[i] ) );\r
+ if( d_n.getKind()!=EQUAL && qi->isVar( d_n[i] ) ){\r
+ d_qni_var_num[i+1] = qi->d_var_num[d_n[i]];\r
+ }\r
+ }else{\r
+ d_qni_gterm[i] = d_n[i];\r
+ }\r
+ }\r
+ d_type = d_n.getKind()==EQUAL ? typ_eq : typ_tconstraint;\r
+ Trace("qcf-tconstraint") << "T-Constraint : " << d_n << std::endl;\r
+ }\r
+ }\r
+ }else{\r
+ //we will just evaluate\r
+ d_n = n;\r
+ d_type = typ_ground;\r
+ }\r
+ //if( d_type!=typ_invalid ){\r
+ //determine an efficient children ordering\r
+ //if( !d_children.empty() ){\r
+ //for( unsigned i=0; i<d_children.size(); i++ ){\r
+ // d_children_order.push_back( i );\r
+ //}\r
+ //if( !d_n.isNull() && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF ) ){\r
+ //sort based on the type of the constraint : ground comes first, then literals, then others\r
+ //MatchGenSort mgs;\r
+ //mgs.d_mg = this;\r
+ //std::sort( d_children_order.begin(), d_children_order.end(), mgs );\r
+ //}\r
+ //}\r
+ //}\r
+ }\r
+ Trace("qcf-qregister-debug") << "Done make match gen " << n << ", type = ";\r
+ debugPrintType( "qcf-qregister-debug", d_type, true );\r
+ Trace("qcf-qregister-debug") << std::endl;\r
+ //Assert( d_children.size()==d_children_order.size() );\r
+\r
+}\r
+\r
+void MatchGen::collectBoundVar( QuantInfo * qi, Node n, std::vector< int >& cbvars ) {\r
+ int v = qi->getVarNum( n );\r
+ if( v!=-1 && std::find( cbvars.begin(), cbvars.end(), v )==cbvars.end() ){\r
+ cbvars.push_back( v );\r
+ }\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ collectBoundVar( qi, n[i], cbvars );\r
+ }\r
+}\r
+\r
+void MatchGen::determineVariableOrder( QuantInfo * qi, std::vector< int >& bvars ) {\r
+ Trace("qcf-qregister-debug") << "Determine variable order " << d_n << std::endl;\r
+ bool isCom = d_type==typ_formula && ( d_n.getKind()==OR || d_n.getKind()==AND || d_n.getKind()==IFF );\r
+ std::map< int, std::vector< int > > c_to_vars;\r
+ std::map< int, std::vector< int > > vars_to_c;\r
+ std::map< int, int > vb_count;\r
+ std::map< int, int > vu_count;\r
+ std::vector< bool > assigned;\r
+ Trace("qcf-qregister-debug") << "Calculate bound variables..." << std::endl;\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ collectBoundVar( qi, d_children[i].d_n, c_to_vars[i] );\r
+ assigned.push_back( false );\r
+ vb_count[i] = 0;\r
+ vu_count[i] = 0;\r
+ for( unsigned j=0; j<c_to_vars[i].size(); j++ ){\r
+ int v = c_to_vars[i][j];\r
+ vars_to_c[v].push_back( i );\r
+ if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){\r
+ vu_count[i]++;\r
+ if( !isCom ){\r
+ bvars.push_back( v );\r
+ }\r
+ }else{\r
+ vb_count[i]++;\r
+ }\r
+ }\r
+ }\r
+ if( isCom ){\r
+ //children that bind the least number of unbound variables go first\r
+ do {\r
+ int min_score = -1;\r
+ int min_score_index = -1;\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ if( !assigned[i] ){\r
+ int score = vu_count[i];\r
+ if( min_score==-1 || score<min_score ){\r
+ min_score = score;\r
+ min_score_index = i;\r
+ }\r
+ }\r
+ }\r
+ Trace("qcf-qregister-debug") << "...assign child " << min_score_index << "/" << d_children.size() << std::endl;\r
+ Assert( min_score_index!=-1 );\r
+ //add to children order\r
+ d_children_order.push_back( min_score_index );\r
+ assigned[min_score_index] = true;\r
+ //if( vb_count[min_score_index]==0 ){\r
+ // d_independent.push_back( min_score_index );\r
+ //}\r
+ //determine order internal to children\r
+ d_children[min_score_index].determineVariableOrder( qi, bvars );\r
+ Trace("qcf-qregister-debug") << "...bind variables" << std::endl;\r
+ //now, make it a bound variable\r
+ for( unsigned i=0; i<c_to_vars[min_score_index].size(); i++ ){\r
+ int v = c_to_vars[min_score_index][i];\r
+ if( std::find( bvars.begin(), bvars.end(), v )==bvars.end() ){\r
+ for( unsigned j=0; j<vars_to_c[v].size(); j++ ){\r
+ int vc = vars_to_c[v][j];\r
+ vu_count[vc]--;\r
+ vb_count[vc]++;\r
+ }\r
+ bvars.push_back( v );\r
+ }\r
+ }\r
+ Trace("qcf-qregister-debug") << "...done assign child " << min_score_index << std::endl;\r
+ }while( d_children_order.size()!=d_children.size() );\r
+ Trace("qcf-qregister-debug") << "Done assign variable ordering for " << d_n << std::endl;\r
+ }else{\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ d_children_order.push_back( i );\r
+ d_children[i].determineVariableOrder( qi, bvars );\r
+ }\r
+ }\r
+}\r
+\r
+\r
+void MatchGen::reset_round( QuantConflictFind * p ) {\r
+ d_wasSet = false;\r
+ for( unsigned i=0; i<d_children.size(); i++ ){\r
+ d_children[i].reset_round( p );\r
+ }\r
+ for( std::map< int, TNode >::iterator it = d_qni_gterm.begin(); it != d_qni_gterm.end(); ++it ){\r
+ d_qni_gterm_rep[it->first] = p->getRepresentative( it->second );\r
+ }\r
+ if( d_type==typ_ground ){\r
+ int e = p->evaluate( d_n );\r
+ if( e==1 ){\r
+ d_ground_eval[0] = p->d_true;\r
+ }else if( e==-1 ){\r
+ d_ground_eval[0] = p->d_false;\r
+ }\r
+ }else if( d_type==typ_eq ){\r
+ for( unsigned i=0; i<d_n.getNumChildren(); i++ ){\r
+ if( !d_n[i].hasBoundVar() ){\r
+ d_ground_eval[i] = p->evaluateTerm( d_n[i] );\r
+ }\r
+ }\r
+ }\r
+ d_qni_bound_cons.clear();\r
+ d_qni_bound_cons_var.clear();\r
+ d_qni_bound.clear();\r
+}\r
+\r
+void MatchGen::reset( QuantConflictFind * p, bool tgt, QuantInfo * qi ) {\r
+ d_tgt = d_type_not ? !tgt : tgt;\r
+ Debug("qcf-match") << " Reset for : " << d_n << ", type : ";\r
+ debugPrintType( "qcf-match", d_type );\r
+ Debug("qcf-match") << ", tgt = " << d_tgt << ", children = " << d_children.size() << " " << d_children_order.size() << std::endl;\r
+ d_qn.clear();\r
+ d_qni.clear();\r
+ d_qni_bound.clear();\r
+ d_child_counter = -1;\r
+ d_tgt_orig = d_tgt;\r
+\r
+ //set up processing matches\r
+ if( d_type==typ_invalid ){\r
+ //do nothing\r
+ }else if( d_type==typ_ground ){\r
+ if( d_ground_eval[0]==( d_tgt ? p->d_true : p->d_false ) ){\r
+ d_child_counter = 0;\r
+ }\r
+ }else if( d_type==typ_bool_var ){\r
+ //get current value of the variable\r
+ TNode n = qi->getCurrentValue( d_n );\r
+ int vn = qi->getCurrentRepVar( qi->getVarNum( n ) );\r
+ if( vn==-1 ){\r
+ //evaluate the value, see if it is compatible\r
+ int e = p->evaluate( n );\r
+ if( ( e==1 && d_tgt ) || ( e==0 && !d_tgt ) ){\r
+ d_child_counter = 0;\r
+ }\r
+ }else{\r
+ //unassigned, set match to true/false\r
+ d_qni_bound[0] = vn;\r
+ qi->setMatch( p, vn, d_tgt ? p->d_true : p->d_false );\r
+ d_child_counter = 0;\r
+ }\r
+ if( d_child_counter==0 ){\r
+ d_qn.push_back( NULL );\r
+ }\r
+ }else if( d_type==typ_var ){\r
+ Assert( isHandledUfTerm( d_n ) );\r
+ Node f = getOperator( p, d_n );\r
+ Debug("qcf-match-debug") << " reset: Var will match operators of " << f << std::endl;\r
+ TermArgTrie * qni = p->getTermDatabase()->getTermArgTrie( Node::null(), f );\r
+ if( qni!=NULL ){\r
+ d_qn.push_back( qni );\r
+ }\r
+ d_matched_basis = false;\r
+ }else if( d_type==typ_tsym || d_type==typ_tconstraint ){\r
+ for( std::map< int, int >::iterator it = d_qni_var_num.begin(); it != d_qni_var_num.end(); ++it ){\r
+ int repVar = qi->getCurrentRepVar( it->second );\r
+ if( qi->d_match[repVar].isNull() ){\r
+ Debug("qcf-match-debug") << "Force matching on child #" << it->first << ", which is var #" << repVar << std::endl;\r
+ d_qni_bound[it->first] = repVar;\r
+ }\r
+ }\r
+ d_qn.push_back( NULL );\r
+ }else if( d_type==typ_pred || d_type==typ_eq ){\r
+ //add initial constraint\r
+ Node nn[2];\r
+ int vn[2];\r
+ if( d_type==typ_pred ){\r
+ nn[0] = qi->getCurrentValue( d_n );\r
+ vn[0] = qi->getCurrentRepVar( qi->getVarNum( nn[0] ) );\r
+ nn[1] = p->getRepresentative( d_tgt ? p->d_true : p->d_false );\r
+ vn[1] = -1;\r
+ d_tgt = true;\r
+ }else{\r
+ for( unsigned i=0; i<2; i++ ){\r
+ TNode nc;\r
+ std::map< int, TNode >::iterator it = d_qni_gterm_rep.find( i );\r
+ if( it!=d_qni_gterm_rep.end() ){\r
+ nc = it->second;\r
+ }else{\r
+ nc = d_n[i];\r
+ }\r
+ nn[i] = qi->getCurrentValue( nc );\r
+ vn[i] = qi->getCurrentRepVar( qi->getVarNum( nn[i] ) );\r
+ }\r
+ }\r
+ bool success;\r
+ if( vn[0]==-1 && vn[1]==-1 ){\r
+ //Trace("qcf-explain") << " reset : " << d_n << " check ground values " << nn[0] << " " << nn[1] << " (tgt=" << d_tgt << ")" << std::endl;\r
+ Debug("qcf-match-debug") << " reset: check ground values " << nn[0] << " " << nn[1] << " (" << d_tgt << ")" << std::endl;\r
+ //just compare values\r
+ if( d_tgt ){\r
+ success = p->areMatchEqual( nn[0], nn[1] );\r
+ }else{\r
+ if( p->d_effort==QuantConflictFind::effort_conflict ){\r
+ success = p->areDisequal( nn[0], nn[1] );\r
+ }else{\r
+ success = p->areMatchDisequal( nn[0], nn[1] );\r
+ }\r
+ }\r
+ }else{\r
+ //otherwise, add a constraint to a variable\r
+ if( vn[1]!=-1 && vn[0]==-1 ){\r
+ //swap\r
+ Node t = nn[1];\r
+ nn[1] = nn[0];\r
+ nn[0] = t;\r
+ vn[0] = vn[1];\r
+ vn[1] = -1;\r
+ }\r
+ Debug("qcf-match-debug") << " reset: add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << std::endl;\r
+ //add some constraint\r
+ int addc = qi->addConstraint( p, vn[0], nn[1], vn[1], d_tgt, false );\r
+ success = addc!=-1;\r
+ //if successful and non-redundant, store that we need to cleanup this\r
+ if( addc==1 ){\r
+ //Trace("qcf-explain") << " reset: " << d_n << " add constraint " << vn[0] << " -> " << nn[1] << " (vn=" << vn[1] << ")" << ", d_tgt = " << d_tgt << std::endl;\r
+ for( unsigned i=0; i<2; i++ ){\r
+ if( vn[i]!=-1 && std::find( d_qni_bound_except.begin(), d_qni_bound_except.end(), i )==d_qni_bound_except.end() ){\r
+ d_qni_bound[vn[i]] = vn[i];\r
+ }\r
+ }\r
+ d_qni_bound_cons[vn[0]] = nn[1];\r
+ d_qni_bound_cons_var[vn[0]] = vn[1];\r
+ }\r
+ }\r
+ //if successful, we will bind values to variables\r
+ if( success ){\r
+ d_qn.push_back( NULL );\r
+ }\r
+ }else{\r
+ if( d_children.empty() ){\r
+ //add dummy\r
+ d_qn.push_back( NULL );\r
+ }else{\r
+ if( d_tgt && d_n.getKind()==FORALL ){\r
+ //do nothing\r
+ }else{\r
+ //reset the first child to d_tgt\r
+ d_child_counter = 0;\r
+ getChild( d_child_counter )->reset( p, d_tgt, qi );\r
+ }\r
+ }\r
+ }\r
+ d_binding = false;\r
+ d_wasSet = true;\r
+ Debug("qcf-match") << " reset: Finished reset for " << d_n << ", success = " << ( !d_qn.empty() || d_child_counter!=-1 ) << std::endl;\r
+}\r
+\r
+bool MatchGen::getNextMatch( QuantConflictFind * p, QuantInfo * qi ) {\r
+ Debug("qcf-match") << " Get next match for : " << d_n << ", type = ";\r
+ debugPrintType( "qcf-match", d_type );\r
+ Debug("qcf-match") << ", children = " << d_children.size() << ", binding = " << d_binding << std::endl;\r
+ if( d_type==typ_invalid || d_type==typ_ground ){\r
+ if( d_child_counter==0 ){\r
+ d_child_counter = -1;\r
+ return true;\r
+ }else{\r
+ d_wasSet = false;\r
+ return false;\r
+ }\r
+ }else if( d_type==typ_var || d_type==typ_eq || d_type==typ_pred || d_type==typ_bool_var || d_type==typ_tconstraint || d_type==typ_tsym ){\r
+ bool success = false;\r
+ bool terminate = false;\r
+ do {\r
+ bool doReset = false;\r
+ bool doFail = false;\r
+ if( !d_binding ){\r
+ if( doMatching( p, qi ) ){\r
+ Debug("qcf-match-debug") << " - Matching succeeded" << std::endl;\r
+ d_binding = true;\r
+ d_binding_it = d_qni_bound.begin();\r
+ doReset = true;\r
+ //for tconstraint, add constraint\r
+ if( d_type==typ_tconstraint ){\r
+ std::map< Node, bool >::iterator it = qi->d_tconstraints.find( d_n );\r
+ if( it==qi->d_tconstraints.end() ){\r
+ qi->d_tconstraints[d_n] = d_tgt;\r
+ //store that we added this constraint\r
+ d_qni_bound_cons[0] = d_n;\r
+ }else if( d_tgt!=it->second ){\r
+ success = false;\r
+ terminate = true;\r
+ }\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " - Matching failed" << std::endl;\r
+ success = false;\r
+ terminate = true;\r
+ }\r
+ }else{\r
+ doFail = true;\r
+ }\r
+ if( d_binding ){\r
+ //also need to create match for each variable we bound\r
+ success = true;\r
+ Debug("qcf-match-debug") << " Produce matches for bound variables by " << d_n << ", type = ";\r
+ debugPrintType( "qcf-match-debug", d_type );\r
+ Debug("qcf-match-debug") << "..." << std::endl;\r
+\r
+ while( ( success && d_binding_it!=d_qni_bound.end() ) || doFail ){\r
+ std::map< int, MatchGen * >::iterator itm;\r
+ if( !doFail ){\r
+ Debug("qcf-match-debug") << " check variable " << d_binding_it->second << std::endl;\r
+ itm = qi->d_var_mg.find( d_binding_it->second );\r
+ }\r
+ if( doFail || ( d_binding_it->first!=0 && itm!=qi->d_var_mg.end() ) ){\r
+ Debug("qcf-match-debug") << " we had bound variable " << d_binding_it->second << ", reset = " << doReset << std::endl;\r
+ if( doReset ){\r
+ itm->second->reset( p, true, qi );\r
+ }\r
+ if( doFail || !itm->second->getNextMatch( p, qi ) ){\r
+ do {\r
+ if( d_binding_it==d_qni_bound.begin() ){\r
+ Debug("qcf-match-debug") << " failed." << std::endl;\r
+ success = false;\r
+ }else{\r
+ --d_binding_it;\r
+ Debug("qcf-match-debug") << " decrement..." << std::endl;\r
+ }\r
+ }while( success && ( d_binding_it->first==0 || qi->d_var_mg.find( d_binding_it->second )==qi->d_var_mg.end() ) );\r
+ doReset = false;\r
+ doFail = false;\r
+ }else{\r
+ Debug("qcf-match-debug") << " increment..." << std::endl;\r
+ ++d_binding_it;\r
+ doReset = true;\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " skip..." << d_binding_it->second << std::endl;\r
+ ++d_binding_it;\r
+ doReset = true;\r
+ }\r
+ }\r
+ if( !success ){\r
+ d_binding = false;\r
+ }else{\r
+ terminate = true;\r
+ if( d_binding_it==d_qni_bound.begin() ){\r
+ d_binding = false;\r
+ }\r
+ }\r
+ }\r
+ }while( !terminate );\r
+ //if not successful, clean up the variables you bound\r
+ if( !success ){\r
+ if( d_type==typ_eq || d_type==typ_pred ){\r
+ //clean up the constraints you added\r
+ for( std::map< int, TNode >::iterator it = d_qni_bound_cons.begin(); it != d_qni_bound_cons.end(); ++it ){\r
+ if( !it->second.isNull() ){\r
+ Debug("qcf-match") << " Clean up bound var " << it->first << (d_tgt ? "!" : "") << " = " << it->second << std::endl;\r
+ std::map< int, int >::iterator itb = d_qni_bound_cons_var.find( it->first );\r
+ int vn = itb!=d_qni_bound_cons_var.end() ? itb->second : -1;\r
+ //Trace("qcf-explain") << " cleanup: " << d_n << " remove constraint " << it->first << " -> " << it->second << " (vn=" << vn << ")" << ", d_tgt = " << d_tgt << std::endl;\r
+ qi->addConstraint( p, it->first, it->second, vn, d_tgt, true );\r
+ }\r
+ }\r
+ d_qni_bound_cons.clear();\r
+ d_qni_bound_cons_var.clear();\r
+ d_qni_bound.clear();\r
+ }else{\r
+ //clean up the matches you set\r
+ for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){\r
+ Debug("qcf-match") << " Clean up bound var " << it->second << std::endl;\r
+ Assert( it->second<qi->getNumVars() );\r
+ qi->d_match[ it->second ] = TNode::null();\r
+ qi->d_match_term[ it->second ] = TNode::null();\r
+ }\r
+ d_qni_bound.clear();\r
+ }\r
+ if( d_type==typ_tconstraint ){\r
+ //remove constraint if applicable\r
+ if( d_qni_bound_cons.find( 0 )!=d_qni_bound_cons.end() ){\r
+ qi->d_tconstraints.erase( d_n );\r
+ d_qni_bound_cons.clear();\r
+ }\r
+ }\r
+ /*\r
+ if( d_type==typ_var && p->d_effort==QuantConflictFind::effort_mc && !d_matched_basis ){\r
+ d_matched_basis = true;\r
+ Node f = getOperator( d_n );\r
+ TNode mbo = p->getQuantifiersEngine()->getTermDatabase()->getModelBasisOpTerm( f );\r
+ if( qi->setMatch( p, d_qni_var_num[0], mbo ) ){\r
+ success = true;\r
+ d_qni_bound[0] = d_qni_var_num[0];\r
+ }\r
+ }\r
+ */\r
+ }\r
+ Debug("qcf-match") << " ...finished matching for " << d_n << ", success = " << success << std::endl;\r
+ d_wasSet = success;\r
+ return success;\r
+ }else if( d_type==typ_formula || d_type==typ_ite_var ){\r
+ bool success = false;\r
+ if( d_child_counter<0 ){\r
+ if( d_child_counter<-1 ){\r
+ success = true;\r
+ d_child_counter = -1;\r
+ }\r
+ }else{\r
+ while( !success && d_child_counter>=0 ){\r
+ //transition system based on d_child_counter\r
+ if( d_n.getKind()==OR || d_n.getKind()==AND ){\r
+ if( (d_n.getKind()==AND)==d_tgt ){\r
+ //all children must match simultaneously\r
+ if( getChild( d_child_counter )->getNextMatch( p, qi ) ){\r
+ if( d_child_counter<(int)(getNumChildren()-1) ){\r
+ d_child_counter++;\r
+ Debug("qcf-match-debug") << " Reset child " << d_child_counter << " of " << d_n << std::endl;\r
+ getChild( d_child_counter )->reset( p, d_tgt, qi );\r
+ }else{\r
+ success = true;\r
+ }\r
+ }else{\r
+ //if( std::find( d_independent.begin(), d_independent.end(), d_child_counter )!=d_independent.end() ){\r
+ // d_child_counter--;\r
+ //}else{\r
+ d_child_counter--;\r
+ //}\r
+ }\r
+ }else{\r
+ //one child must match\r
+ if( !getChild( d_child_counter )->getNextMatch( p, qi ) ){\r
+ if( d_child_counter<(int)(getNumChildren()-1) ){\r
+ d_child_counter++;\r
+ Debug("qcf-match-debug") << " Reset child " << d_child_counter << " of " << d_n << ", one match" << std::endl;\r
+ getChild( d_child_counter )->reset( p, d_tgt, qi );\r
+ }else{\r
+ d_child_counter = -1;\r
+ }\r
+ }else{\r
+ success = true;\r
+ }\r
+ }\r
+ }else if( d_n.getKind()==IFF ){\r
+ //construct match based on both children\r
+ if( d_child_counter%2==0 ){\r
+ if( getChild( 0 )->getNextMatch( p, qi ) ){\r
+ d_child_counter++;\r
+ getChild( 1 )->reset( p, d_child_counter==1, qi );\r
+ }else{\r
+ if( d_child_counter==0 ){\r
+ d_child_counter = 2;\r
+ getChild( 0 )->reset( p, !d_tgt, qi );\r
+ }else{\r
+ d_child_counter = -1;\r
+ }\r
+ }\r
+ }\r
+ if( d_child_counter>=0 && d_child_counter%2==1 ){\r
+ if( getChild( 1 )->getNextMatch( p, qi ) ){\r
+ success = true;\r
+ }else{\r
+ d_child_counter--;\r
+ }\r
+ }\r
+ }else if( d_n.getKind()==ITE ){\r
+ if( d_child_counter%2==0 ){\r
+ int index1 = d_child_counter==4 ? 1 : 0;\r
+ if( getChild( index1 )->getNextMatch( p, qi ) ){\r
+ d_child_counter++;\r
+ getChild( d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2) )->reset( p, d_tgt, qi );\r
+ }else{\r
+ if( d_child_counter==4 || ( d_type==typ_ite_var && d_child_counter==2 ) ){\r
+ d_child_counter = -1;\r
+ }else{\r
+ d_child_counter +=2;\r
+ getChild( d_child_counter==2 ? 0 : 1 )->reset( p, d_child_counter==2 ? !d_tgt : d_tgt, qi );\r
+ }\r
+ }\r
+ }\r
+ if( d_child_counter>=0 && d_child_counter%2==1 ){\r
+ int index2 = d_child_counter==5 ? 2 : (d_tgt==(d_child_counter==1) ? 1 : 2);\r
+ if( getChild( index2 )->getNextMatch( p, qi ) ){\r
+ success = true;\r
+ }else{\r
+ d_child_counter--;\r
+ }\r
+ }\r
+ }else if( d_n.getKind()==FORALL ){\r
+ if( getChild( d_child_counter )->getNextMatch( p, qi ) ){\r
+ success = true;\r
+ }else{\r
+ d_child_counter = -1;\r
+ }\r
+ }\r
+ }\r
+ d_wasSet = success;\r
+ Debug("qcf-match") << " ...finished construct match for " << d_n << ", success = " << success << std::endl;\r
+ return success;\r
+ }\r
+ }\r
+ Debug("qcf-match") << " ...already finished for " << d_n << std::endl;\r
+ return false;\r
+}\r
+\r
+bool MatchGen::getExplanation( QuantConflictFind * p, QuantInfo * qi, std::vector< Node >& exp ) {\r
+ if( d_type==typ_eq ){\r
+ Node n[2];\r
+ for( unsigned i=0; i<2; i++ ){\r
+ Trace("qcf-explain") << "Explain term " << d_n[i] << "..." << std::endl;\r
+ n[i] = getExplanationTerm( p, qi, d_n[i], exp );\r
+ }\r
+ Node eq = n[0].eqNode( n[1] );\r
+ if( !d_tgt_orig ){\r
+ eq = eq.negate();\r
+ }\r
+ exp.push_back( eq );\r
+ Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << eq << ", set = " << d_wasSet << std::endl;\r
+ return true;\r
+ }else if( d_type==typ_pred ){\r
+ Trace("qcf-explain") << "Explain term " << d_n << "..." << std::endl;\r
+ Node n = getExplanationTerm( p, qi, d_n, exp );\r
+ if( !d_tgt_orig ){\r
+ n = n.negate();\r
+ }\r
+ exp.push_back( n );\r
+ Trace("qcf-explain") << "Explanation for " << d_n << " (tgt=" << d_tgt_orig << ") is " << n << ", set = " << d_wasSet << std::endl;\r
+ return true;\r
+ }else if( d_type==typ_formula ){\r
+ Trace("qcf-explain") << "Explanation get for " << d_n << ", counter = " << d_child_counter << ", tgt = " << d_tgt_orig << ", set = " << d_wasSet << std::endl;\r
+ if( d_n.getKind()==OR || d_n.getKind()==AND ){\r
+ if( (d_n.getKind()==AND)==d_tgt ){\r
+ for( unsigned i=0; i<getNumChildren(); i++ ){\r
+ if( !getChild( i )->getExplanation( p, qi, exp ) ){\r
+ return false;\r
+ }\r
+ }\r
+ }else{\r
+ return getChild( d_child_counter )->getExplanation( p, qi, exp );\r
+ }\r
+ }else if( d_n.getKind()==IFF ){\r
+ for( unsigned i=0; i<2; i++ ){\r
+ if( !getChild( i )->getExplanation( p, qi, exp ) ){\r
+ return false;\r
+ }\r
+ }\r
+ }else if( d_n.getKind()==ITE ){\r
+ for( unsigned i=0; i<3; i++ ){\r
+ bool isActive = ( ( i==0 && d_child_counter!=5 ) ||\r
+ ( i==1 && d_child_counter!=( d_tgt ? 3 : 1 ) ) ||\r
+ ( i==2 && d_child_counter!=( d_tgt ? 1 : 3 ) ) );\r
+ if( isActive ){\r
+ if( !getChild( i )->getExplanation( p, qi, exp ) ){\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ }else{\r
+ return false;\r
+ }\r
+ return true;\r
+ }else{\r
+ return false;\r
+ }\r
+}\r
+\r
+Node MatchGen::getExplanationTerm( QuantConflictFind * p, QuantInfo * qi, Node t, std::vector< Node >& exp ) {\r
+ Node v = qi->getCurrentExpValue( t );\r
+ if( isHandledUfTerm( t ) ){\r
+ for( unsigned i=0; i<t.getNumChildren(); i++ ){\r
+ Node vi = getExplanationTerm( p, qi, t[i], exp );\r
+ if( vi!=v[i] ){\r
+ Node eq = vi.eqNode( v[i] );\r
+ if( std::find( exp.begin(), exp.end(), eq )==exp.end() ){\r
+ Trace("qcf-explain") << " add : " << eq << "." << std::endl;\r
+ exp.push_back( eq );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return v;\r
+}\r
+\r
+bool MatchGen::doMatching( QuantConflictFind * p, QuantInfo * qi ) {\r
+ if( !d_qn.empty() ){\r
+ if( d_qn[0]==NULL ){\r
+ d_qn.clear();\r
+ return true;\r
+ }else{\r
+ Assert( d_type==typ_var );\r
+ Assert( d_qni_size>0 );\r
+ bool invalidMatch;\r
+ do {\r
+ invalidMatch = false;\r
+ Debug("qcf-match-debug") << " Do matching " << d_n << " " << d_qn.size() << " " << d_qni.size() << std::endl;\r
+ if( d_qn.size()==d_qni.size()+1 ) {\r
+ int index = (int)d_qni.size();\r
+ //initialize\r
+ TNode val;\r
+ std::map< int, int >::iterator itv = d_qni_var_num.find( index );\r
+ if( itv!=d_qni_var_num.end() ){\r
+ //get the representative variable this variable is equal to\r
+ int repVar = qi->getCurrentRepVar( itv->second );\r
+ Debug("qcf-match-debug") << " Match " << index << " is a variable " << itv->second << ", which is repVar " << repVar << std::endl;\r
+ //get the value the rep variable\r
+ //std::map< int, TNode >::iterator itm = qi->d_match.find( repVar );\r
+ if( !qi->d_match[repVar].isNull() ){\r
+ val = qi->d_match[repVar];\r
+ Debug("qcf-match-debug") << " Variable is already bound to " << val << std::endl;\r
+ }else{\r
+ //binding a variable\r
+ d_qni_bound[index] = repVar;\r
+ std::map< TNode, TermArgTrie >::iterator it = d_qn[index]->d_data.begin();\r
+ if( it != d_qn[index]->d_data.end() ) {\r
+ d_qni.push_back( it );\r
+ //set the match\r
+ if( qi->setMatch( p, d_qni_bound[index], it->first ) ){\r
+ Debug("qcf-match-debug") << " Binding variable" << std::endl;\r
+ if( d_qn.size()<d_qni_size ){\r
+ d_qn.push_back( &it->second );\r
+ }\r
+ }else{\r
+ Debug("qcf-match") << " Binding variable, currently fail." << std::endl;\r
+ invalidMatch = true;\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " Binding variable, fail, no more variables to bind" << std::endl;\r
+ d_qn.pop_back();\r
+ }\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " Match " << index << " is ground term" << std::endl;\r
+ Assert( d_qni_gterm.find( index )!=d_qni_gterm.end() );\r
+ Assert( d_qni_gterm_rep.find( index )!=d_qni_gterm_rep.end() );\r
+ val = d_qni_gterm_rep[index];\r
+ Assert( !val.isNull() );\r
+ }\r
+ if( !val.isNull() ){\r
+ //constrained by val\r
+ std::map< TNode, TermArgTrie >::iterator it = d_qn[index]->d_data.find( val );\r
+ if( it!=d_qn[index]->d_data.end() ){\r
+ Debug("qcf-match-debug") << " Match" << std::endl;\r
+ d_qni.push_back( it );\r
+ if( d_qn.size()<d_qni_size ){\r
+ d_qn.push_back( &it->second );\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " Failed to match" << std::endl;\r
+ d_qn.pop_back();\r
+ }\r
+ }\r
+ }else{\r
+ Assert( d_qn.size()==d_qni.size() );\r
+ int index = d_qni.size()-1;\r
+ //increment if binding this variable\r
+ bool success = false;\r
+ std::map< int, int >::iterator itb = d_qni_bound.find( index );\r
+ if( itb!=d_qni_bound.end() ){\r
+ d_qni[index]++;\r
+ if( d_qni[index]!=d_qn[index]->d_data.end() ){\r
+ success = true;\r
+ if( qi->setMatch( p, itb->second, d_qni[index]->first ) ){\r
+ Debug("qcf-match-debug") << " Bind next variable" << std::endl;\r
+ if( d_qn.size()<d_qni_size ){\r
+ d_qn.push_back( &d_qni[index]->second );\r
+ }\r
+ }else{\r
+ Debug("qcf-match-debug") << " Bind next variable, currently fail" << std::endl;\r
+ invalidMatch = true;\r
+ }\r
+ }else{\r
+ qi->d_match[ itb->second ] = TNode::null();\r
+ qi->d_match_term[ itb->second ] = TNode::null();\r
+ Debug("qcf-match-debug") << " Bind next variable, no more variables to bind" << std::endl;\r
+ }\r
+ }else{\r
+ //TODO : if it equal to something else, also try that\r
+ }\r
+ //if not incrementing, move to next\r
+ if( !success ){\r
+ d_qn.pop_back();\r
+ d_qni.pop_back();\r
+ }\r
+ }\r
+ }while( ( !d_qn.empty() && d_qni.size()!=d_qni_size ) || invalidMatch );\r
+ if( d_qni.size()==d_qni_size ){\r
+ //Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );\r
+ //Debug("qcf-match-debug") << " We matched " << d_qni[d_qni.size()-1]->second.d_children.begin()->first << std::endl;\r
+ Assert( !d_qni[d_qni.size()-1]->second.d_data.empty() );\r
+ TNode t = d_qni[d_qni.size()-1]->second.d_data.begin()->first;\r
+ Debug("qcf-match-debug") << " " << d_n << " matched " << t << std::endl;\r
+ qi->d_match_term[d_qni_var_num[0]] = t;\r
+ //set the match terms\r
+ for( std::map< int, int >::iterator it = d_qni_bound.begin(); it != d_qni_bound.end(); ++it ){\r
+ Debug("qcf-match-debug") << " position " << it->first << " bounded " << it->second << " / " << qi->d_q[0].getNumChildren() << std::endl;\r
+ //if( it->second<(int)qi->d_q[0].getNumChildren() ){ //if it is an actual variable, we are interested in knowing the actual term\r
+ if( it->first>0 ){\r
+ Assert( !qi->d_match[ it->second ].isNull() );\r
+ Assert( p->areEqual( t[it->first-1], qi->d_match[ it->second ] ) );\r
+ qi->d_match_term[it->second] = t[it->first-1];\r
+ }\r
+ //}\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return !d_qn.empty();\r
+}\r
+\r
+void MatchGen::debugPrintType( const char * c, short typ, bool isTrace ) {\r
+ if( isTrace ){\r
+ switch( typ ){\r
+ case typ_invalid: Trace(c) << "invalid";break;\r
+ case typ_ground: Trace(c) << "ground";break;\r
+ case typ_eq: Trace(c) << "eq";break;\r
+ case typ_pred: Trace(c) << "pred";break;\r
+ case typ_formula: Trace(c) << "formula";break;\r
+ case typ_var: Trace(c) << "var";break;\r
+ case typ_ite_var: Trace(c) << "ite_var";break;\r
+ case typ_bool_var: Trace(c) << "bool_var";break;\r
+ }\r
+ }else{\r
+ switch( typ ){\r
+ case typ_invalid: Debug(c) << "invalid";break;\r
+ case typ_ground: Debug(c) << "ground";break;\r
+ case typ_eq: Debug(c) << "eq";break;\r
+ case typ_pred: Debug(c) << "pred";break;\r
+ case typ_formula: Debug(c) << "formula";break;\r
+ case typ_var: Debug(c) << "var";break;\r
+ case typ_ite_var: Debug(c) << "ite_var";break;\r
+ case typ_bool_var: Debug(c) << "bool_var";break;\r
+ }\r
+ }\r
+}\r
+\r
+void MatchGen::setInvalid() {\r
+ d_type = typ_invalid;\r
+ d_children.clear();\r
+}\r
+\r
+bool MatchGen::isHandledBoolConnective( TNode n ) {\r
+ return n.getType().isBoolean() && ( n.getKind()==OR || n.getKind()==AND || n.getKind()==IFF || n.getKind()==ITE || n.getKind()==FORALL || n.getKind()==NOT );\r
+}\r
+\r
+bool MatchGen::isHandledUfTerm( TNode n ) {\r
+ //return n.getKind()==APPLY_UF || n.getKind()==STORE || n.getKind()==SELECT ||\r
+ // n.getKind()==APPLY_CONSTRUCTOR || n.getKind()==APPLY_SELECTOR_TOTAL || n.getKind()==APPLY_TESTER;\r
+ return inst::Trigger::isAtomicTriggerKind( n.getKind() ); \r
+}\r
+\r
+Node MatchGen::getOperator( QuantConflictFind * p, Node n ) {\r
+ if( isHandledUfTerm( n ) ){\r
+ return p->getQuantifiersEngine()->getTermDatabase()->getOperator( n );\r
+ }else{\r
+ return Node::null();\r
+ }\r
+}\r
+\r
+bool MatchGen::isHandled( TNode n ) {\r
+ if( n.getKind()!=BOUND_VARIABLE && n.hasBoundVar() ){\r
+ if( !isHandledBoolConnective( n ) && !isHandledUfTerm( n ) && n.getKind()!=EQUAL && n.getKind()!=ITE ){\r
+ return false;\r
+ }\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ if( !isHandled( n[i] ) ){\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ return true;\r
+}\r
+\r
+\r
+QuantConflictFind::QuantConflictFind( QuantifiersEngine * qe, context::Context* c ) :\r
+QuantifiersModule( qe ),\r
+d_c( c ),\r
+d_conflict( c, false ),\r
+d_qassert( c ) {\r
+ d_fid_count = 0;\r
+ d_true = NodeManager::currentNM()->mkConst<bool>(true);\r
+ d_false = NodeManager::currentNM()->mkConst<bool>(false);\r
+}\r
+\r
+Node QuantConflictFind::mkEqNode( Node a, Node b ) {\r
+ if( a.getType().isBoolean() ){\r
+ return a.iffNode( b );\r
+ }else{\r
+ return a.eqNode( b );\r
+ }\r
+}\r
+\r
+//-------------------------------------------------- registration\r
+\r
+void QuantConflictFind::registerQuantifier( Node q ) {\r
+ if( !TermDb::isRewriteRule( q ) ){\r
+ d_quants.push_back( q );\r
+ d_quant_id[q] = d_quants.size();\r
+ Trace("qcf-qregister") << "Register ";\r
+ debugPrintQuant( "qcf-qregister", q );\r
+ Trace("qcf-qregister") << " : " << q << std::endl;\r
+ //make QcfNode structure\r
+ Trace("qcf-qregister") << "- Get relevant equality/disequality pairs, calculate flattening..." << std::endl;\r
+ d_qinfo[q].initialize( q, q[1] );\r
+\r
+ //debug print\r
+ Trace("qcf-qregister") << "- Flattened structure is :" << std::endl;\r
+ Trace("qcf-qregister") << " ";\r
+ debugPrintQuantBody( "qcf-qregister", q, q[1] );\r
+ Trace("qcf-qregister") << std::endl;\r
+ if( d_qinfo[q].d_vars.size()>q[0].getNumChildren() ){\r
+ Trace("qcf-qregister") << " with additional constraints : " << std::endl;\r
+ for( unsigned j=q[0].getNumChildren(); j<d_qinfo[q].d_vars.size(); j++ ){\r
+ Trace("qcf-qregister") << " ?x" << j << " = ";\r
+ debugPrintQuantBody( "qcf-qregister", q, d_qinfo[q].d_vars[j], false );\r
+ Trace("qcf-qregister") << std::endl;\r
+ }\r
+ }\r
+\r
+ Trace("qcf-qregister") << "Done registering quantifier." << std::endl;\r
+ }\r
+}\r
+\r
+int QuantConflictFind::evaluate( Node n, bool pref, bool hasPref ) {\r
+ int ret = 0;\r
+ if( n.getKind()==EQUAL ){\r
+ Node n1 = evaluateTerm( n[0] );\r
+ Node n2 = evaluateTerm( n[1] );\r
+ Debug("qcf-eval") << "Evaluate : Normalize " << n << " to " << n1 << " = " << n2 << std::endl;\r
+ if( areEqual( n1, n2 ) ){\r
+ ret = 1;\r
+ }else if( areDisequal( n1, n2 ) ){\r
+ ret = -1;\r
+ }\r
+ //else if( d_effort>QuantConflictFind::effort_conflict ){\r
+ // ret = -1;\r
+ //}\r
+ }else if( MatchGen::isHandledUfTerm( n ) ){ //predicate\r
+ Node nn = evaluateTerm( n );\r
+ Debug("qcf-eval") << "Evaluate : Normalize " << nn << " to " << n << std::endl;\r
+ if( areEqual( nn, d_true ) ){\r
+ ret = 1;\r
+ }else if( areEqual( nn, d_false ) ){\r
+ ret = -1;\r
+ }\r
+ //else if( d_effort>QuantConflictFind::effort_conflict ){\r
+ // ret = -1;\r
+ //}\r
+ }else if( n.getKind()==NOT ){\r
+ return -evaluate( n[0] );\r
+ }else if( n.getKind()==ITE ){\r
+ int cev1 = evaluate( n[0] );\r
+ int cevc[2] = { 0, 0 };\r
+ for( unsigned i=0; i<2; i++ ){\r
+ if( ( i==0 && cev1!=-1 ) || ( i==1 && cev1!=1 ) ){\r
+ cevc[i] = evaluate( n[i+1] );\r
+ if( cev1!=0 ){\r
+ ret = cevc[i];\r
+ break;\r
+ }else if( cevc[i]==0 ){\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if( ret==0 && cevc[0]!=0 && cevc[0]==cevc[1] ){\r
+ ret = cevc[0];\r
+ }\r
+ }else if( n.getKind()==IFF ){\r
+ int cev1 = evaluate( n[0] );\r
+ if( cev1!=0 ){\r
+ int cev2 = evaluate( n[1] );\r
+ if( cev2!=0 ){\r
+ ret = cev1==cev2 ? 1 : -1;\r
+ }\r
+ }\r
+\r
+ }else{\r
+ int ssval = 0;\r
+ if( n.getKind()==OR ){\r
+ ssval = 1;\r
+ }else if( n.getKind()==AND ){\r
+ ssval = -1;\r
+ }\r
+ bool isUnk = false;\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ int cev = evaluate( n[i] );\r
+ if( cev==ssval ){\r
+ ret = ssval;\r
+ break;\r
+ }else if( cev==0 ){\r
+ isUnk = true;\r
+ }\r
+ }\r
+ if( ret==0 && !isUnk ){\r
+ ret = -ssval;\r
+ }\r
+ }\r
+ Debug("qcf-eval") << "Evaluate " << n << " to " << ret << std::endl;\r
+ return ret;\r
+}\r
+\r
+short QuantConflictFind::getMaxQcfEffort() {\r
+ if( options::qcfMode()==QCF_CONFLICT_ONLY ){\r
+ return effort_conflict;\r
+ }else if( options::qcfMode()==QCF_PROP_EQ ){\r
+ return effort_prop_eq;\r
+ }else if( options::qcfMode()==QCF_MC ){\r
+ return effort_mc;\r
+ }else{\r
+ return 0;\r
+ }\r
+}\r
+\r
+bool QuantConflictFind::areMatchEqual( TNode n1, TNode n2 ) {\r
+ //if( d_effort==QuantConflictFind::effort_mc ){\r
+ // return n1==n2 || !areDisequal( n1, n2 );\r
+ //}else{\r
+ return n1==n2;\r
+ //}\r
+}\r
+\r
+bool QuantConflictFind::areMatchDisequal( TNode n1, TNode n2 ) {\r
+ //if( d_effort==QuantConflictFind::effort_conflict ){\r
+ // return areDisequal( n1, n2 );\r
+ //}else{\r
+ return n1!=n2;\r
+ //}\r
+}\r
+\r
+//-------------------------------------------------- handling assertions / eqc\r
+\r
+void QuantConflictFind::assertNode( Node q ) {\r
+ if( !TermDb::isRewriteRule( q ) ){\r
+ Trace("qcf-proc") << "QCF : assertQuantifier : ";\r
+ debugPrintQuant("qcf-proc", q);\r
+ Trace("qcf-proc") << std::endl;\r
+ d_qassert.push_back( q );\r
+ //set the eqRegistries that this depends on to true\r
+ //for( std::map< EqRegistry *, bool >::iterator it = d_qinfo[q].d_rel_eqr.begin(); it != d_qinfo[q].d_rel_eqr.end(); ++it ){\r
+ // it->first->d_active.set( true );\r
+ //}\r
+ }\r
+}\r
+\r
+eq::EqualityEngine * QuantConflictFind::getEqualityEngine() {\r
+ //return ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( theory::THEORY_UF ))->getEqualityEngine();\r
+ return d_quantEngine->getTheoryEngine()->getMasterEqualityEngine();\r
+}\r
+bool QuantConflictFind::areEqual( Node n1, Node n2 ) {\r
+ return getEqualityEngine()->hasTerm( n1 ) && getEqualityEngine()->hasTerm( n2 ) && getEqualityEngine()->areEqual( n1,n2 );\r
+}\r
+bool QuantConflictFind::areDisequal( Node n1, Node n2 ) {\r
+ return n1!=n2 && getEqualityEngine()->hasTerm( n1 ) && getEqualityEngine()->hasTerm( n2 ) && getEqualityEngine()->areDisequal( n1,n2, false );\r
+}\r
+Node QuantConflictFind::getRepresentative( Node n ) {\r
+ if( getEqualityEngine()->hasTerm( n ) ){\r
+ return getEqualityEngine()->getRepresentative( n );\r
+ }else{\r
+ return n;\r
+ }\r
+}\r
+TermDb* QuantConflictFind::getTermDatabase() { \r
+ return d_quantEngine->getTermDatabase();\r
+}\r
+\r
+Node QuantConflictFind::evaluateTerm( Node n ) {\r
+ if( MatchGen::isHandledUfTerm( n ) ){\r
+ Node f = MatchGen::getOperator( this, n );\r
+ Node nn;\r
+ if( getEqualityEngine()->hasTerm( n ) ){\r
+ nn = getTermDatabase()->existsTerm( f, n );\r
+ }else{\r
+ std::vector< TNode > args;\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ Node c = evaluateTerm( n[i] );\r
+ args.push_back( c );\r
+ }\r
+ nn = getTermDatabase()->d_func_map_trie[f].existsTerm( args );\r
+ }\r
+ if( !nn.isNull() ){\r
+ Debug("qcf-eval") << "GT: Term " << nn << " for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n ) << std::endl;\r
+ return getRepresentative( nn );\r
+ }else{\r
+ Debug("qcf-eval") << "GT: No term for " << n << " hasTerm = " << getEqualityEngine()->hasTerm( n ) << std::endl;\r
+ return n;\r
+ }\r
+ }else if( n.getKind()==ITE ){\r
+ int v = evaluate( n[0], false, false );\r
+ if( v==1 ){\r
+ return evaluateTerm( n[1] );\r
+ }else if( v==-1 ){\r
+ return evaluateTerm( n[2] );\r
+ }\r
+ }\r
+ return getRepresentative( n );\r
+}\r
+\r
+/** new node */\r
+void QuantConflictFind::newEqClass( Node n ) {\r
+ //Trace("qcf-proc-debug") << "QCF : newEqClass : " << n << std::endl;\r
+ //Trace("qcf-proc2-debug") << "QCF : finished newEqClass : " << n << std::endl;\r
+}\r
+\r
+/** merge */\r
+void QuantConflictFind::merge( Node a, Node b ) {\r
+\r
+}\r
+\r
+/** assert disequal */\r
+void QuantConflictFind::assertDisequal( Node a, Node b ) {\r
+\r
+}\r
+\r
+//-------------------------------------------------- check function\r
+\r
+void QuantConflictFind::reset_round( Theory::Effort level ) {\r
+ d_needs_computeRelEqr = true;\r
+}\r
+\r
+/** check */\r
+void QuantConflictFind::check( Theory::Effort level ) {\r
+ Trace("qcf-check") << "QCF : check : " << level << std::endl;\r
+ if( d_conflict ){\r
+ Trace("qcf-check2") << "QCF : finished check : already in conflict." << std::endl;\r
+ if( level>=Theory::EFFORT_FULL ){\r
+ Trace("qcf-warn") << "ALREADY IN CONFLICT? " << level << std::endl;\r
+ //Assert( false );\r
+ }\r
+ }else{\r
+ int addedLemmas = 0;\r
+ if( d_performCheck ){\r
+ ++(d_statistics.d_inst_rounds);\r
+ double clSet = 0;\r
+ int prevEt = 0;\r
+ if( Trace.isOn("qcf-engine") ){\r
+ prevEt = d_statistics.d_entailment_checks.getData();\r
+ clSet = double(clock())/double(CLOCKS_PER_SEC);\r
+ Trace("qcf-engine") << "---Conflict Find Engine Round, effort = " << level << "---" << std::endl;\r
+ }\r
+ computeRelevantEqr();\r
+\r
+ //determine order for quantified formulas\r
+ std::vector< Node > qorder;\r
+ std::map< Node, bool > qassert;\r
+ //mark which are asserted\r
+ for( unsigned i=0; i<d_qassert.size(); i++ ){\r
+ qassert[d_qassert[i]] = true;\r
+ }\r
+ //add which ones are specified in the order\r
+ for( unsigned i=0; i<d_quant_order.size(); i++ ){\r
+ Node n = d_quant_order[i];\r
+ if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() && qassert.find( n )!=qassert.end() ){\r
+ qorder.push_back( n );\r
+ }\r
+ }\r
+ d_quant_order.clear();\r
+ d_quant_order.insert( d_quant_order.begin(), qorder.begin(), qorder.end() );\r
+ //add remaining\r
+ for( unsigned i=0; i<d_qassert.size(); i++ ){\r
+ Node n = d_qassert[i];\r
+ if( std::find( qorder.begin(), qorder.end(), n )==qorder.end() ){\r
+ qorder.push_back( n );\r
+ }\r
+ }\r
+\r
+ if( Trace.isOn("qcf-debug") ){\r
+ Trace("qcf-debug") << std::endl;\r
+ debugPrint("qcf-debug");\r
+ Trace("qcf-debug") << std::endl;\r
+ }\r
+ short end_e = getMaxQcfEffort();\r
+ for( short e = effort_conflict; e<=end_e; e++ ){\r
+ d_effort = e;\r
+ Trace("qcf-check") << "Checking quantified formulas at effort " << e << "..." << std::endl;\r
+ for( unsigned j=0; j<qorder.size(); j++ ){\r
+ Node q = qorder[j];\r
+ QuantInfo * qi = &d_qinfo[q];\r
+\r
+ Assert( d_qinfo.find( q )!=d_qinfo.end() );\r
+ if( qi->d_mg->isValid() ){\r
+ Trace("qcf-check") << "Check quantified formula ";\r
+ debugPrintQuant("qcf-check", q);\r
+ Trace("qcf-check") << " : " << q << "..." << std::endl;\r
+\r
+ Trace("qcf-check-debug") << "Reset round..." << std::endl;\r
+ qi->reset_round( this );\r
+ //try to make a matches making the body false\r
+ Trace("qcf-check-debug") << "Get next match..." << std::endl;\r
+ while( qi->d_mg->getNextMatch( this, qi ) ){\r
+ Trace("qcf-check") << "*** Produced match at effort " << e << " : " << std::endl;\r
+ qi->debugPrintMatch("qcf-check");\r
+ Trace("qcf-check") << std::endl;\r
+ std::vector< int > assigned;\r
+ if( !qi->isMatchSpurious( this ) ){\r
+ if( qi->completeMatch( this, assigned ) ){\r
+ std::vector< Node > terms;\r
+ qi->getMatch( terms );\r
+ if( !qi->isTConstraintSpurious( this, terms ) ){\r
+ if( Debug.isOn("qcf-check-inst") ){\r
+ //if( e==effort_conflict ){\r
+ Node inst = d_quantEngine->getInstantiation( q, terms );\r
+ Debug("qcf-check-inst") << "Check instantiation " << inst << "..." << std::endl;\r
+ Assert( evaluate( inst )!=1 );\r
+ Assert( evaluate( inst )==-1 || e>effort_conflict );\r
+ //}\r
+ }\r
+ if( d_quantEngine->addInstantiation( q, terms, false ) ){\r
+ Trace("qcf-check") << " ... Added instantiation" << std::endl;\r
+ Trace("qcf-inst") << "*** Was from effort " << e << " : " << std::endl;\r
+ qi->debugPrintMatch("qcf-inst");\r
+ Trace("qcf-inst") << std::endl;\r
+ ++addedLemmas;\r
+ if( e==effort_conflict ){\r
+ d_quant_order.insert( d_quant_order.begin(), q );\r
+ d_conflict.set( true );\r
+ ++(d_statistics.d_conflict_inst);\r
+ break;\r
+ }else if( e==effort_prop_eq ){\r
+ ++(d_statistics.d_prop_inst);\r
+ }\r
+ }else{\r
+ Trace("qcf-check") << " ... Failed to add instantiation" << std::endl;\r
+ //Assert( false );\r
+ }\r
+ }\r
+ //clean up assigned\r
+ qi->revertMatch( assigned );\r
+ d_tempCache.clear();\r
+ }else{\r
+ Trace("qcf-check") << " ... Spurious instantiation (cannot assign unassigned variables)" << std::endl;\r
+ }\r
+ }else{\r
+ Trace("qcf-check") << " ... Spurious instantiation (match is inconsistent)" << std::endl;\r
+ }\r
+ }\r
+ if( d_conflict ){\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if( addedLemmas>0 ){\r
+ d_quantEngine->flushLemmas();\r
+ break;\r
+ }\r
+ }\r
+ if( Trace.isOn("qcf-engine") ){\r
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);\r
+ Trace("qcf-engine") << "Finished conflict find engine, time = " << (clSet2-clSet);\r
+ if( addedLemmas>0 ){\r
+ Trace("qcf-engine") << ", effort = " << ( d_effort==effort_conflict ? "conflict" : ( d_effort==effort_prop_eq ? "prop_eq" : "mc" ) );\r
+ Trace("qcf-engine") << ", addedLemmas = " << addedLemmas;\r
+ }\r
+ Trace("qcf-engine") << std::endl;\r
+ int currEt = d_statistics.d_entailment_checks.getData();\r
+ if( currEt!=prevEt ){\r
+ Trace("qcf-engine") << " Entailment checks = " << ( currEt - prevEt ) << std::endl;\r
+ }\r
+ }\r
+ }\r
+ Trace("qcf-check2") << "QCF : finished check : " << level << std::endl;\r
+ }\r
+}\r
+\r
+bool QuantConflictFind::needsCheck( Theory::Effort level ) {\r
+ d_performCheck = false;\r
+ if( options::quantConflictFind() && !d_conflict ){\r
+ if( level==Theory::EFFORT_LAST_CALL ){\r
+ d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_LAST_CALL;\r
+ }else if( level==Theory::EFFORT_FULL ){\r
+ d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_DEFAULT;\r
+ }else if( level==Theory::EFFORT_STANDARD ){\r
+ d_performCheck = options::qcfWhenMode()==QCF_WHEN_MODE_STD;\r
+ }\r
+ }\r
+ return d_performCheck;\r
+}\r
+\r
+void QuantConflictFind::computeRelevantEqr() {\r
+ if( d_needs_computeRelEqr ){\r
+ d_needs_computeRelEqr = false;\r
+ Trace("qcf-check") << "Compute relevant equalities..." << std::endl;\r
+ //d_uf_terms.clear();\r
+ //d_eqc_uf_terms.clear();\r
+ d_eqcs.clear();\r
+ d_model_basis.clear();\r
+ //d_arg_reps.clear();\r
+ //double clSet = 0;\r
+ //if( Trace.isOn("qcf-opt") ){\r
+ // clSet = double(clock())/double(CLOCKS_PER_SEC);\r
+ //}\r
+\r
+ //long nTermst = 0;\r
+ //long nTerms = 0;\r
+ //long nEqc = 0;\r
+\r
+ //which nodes are irrelevant for disequality matches\r
+ std::map< TNode, bool > irrelevant_dnode;\r
+ //now, store matches\r
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );\r
+ while( !eqcs_i.isFinished() ){\r
+ //nEqc++;\r
+ Node r = (*eqcs_i);\r
+ TypeNode rtn = r.getType();\r
+ if( options::qcfMode()==QCF_MC ){\r
+ std::map< TypeNode, std::vector< TNode > >::iterator itt = d_eqcs.find( rtn );\r
+ if( itt==d_eqcs.end() ){\r
+ Node mb = getQuantifiersEngine()->getTermDatabase()->getModelBasisTerm( rtn );\r
+ if( !getEqualityEngine()->hasTerm( mb ) ){\r
+ Trace("qcf-warn") << "WARNING: Model basis term does not exist!" << std::endl;\r
+ Assert( false );\r
+ }\r
+ Node mbr = getRepresentative( mb );\r
+ if( mbr!=r ){\r
+ d_eqcs[rtn].push_back( mbr );\r
+ }\r
+ d_eqcs[rtn].push_back( r );\r
+ d_model_basis[rtn] = mb;\r
+ }else{\r
+ itt->second.push_back( r );\r
+ }\r
+ }else{\r
+ d_eqcs[rtn].push_back( r );\r
+ }\r
+ ++eqcs_i;\r
+ }\r
+ /*\r
+ if( Trace.isOn("qcf-opt") ){\r
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);\r
+ Trace("qcf-opt") << "Compute rel eqc : " << std::endl;\r
+ Trace("qcf-opt") << " " << nEqc << " equivalence classes. " << std::endl;\r
+ Trace("qcf-opt") << " " << nTerms << " / " << nTermst << " terms." << std::endl;\r
+ Trace("qcf-opt") << " Time : " << (clSet2-clSet) << std::endl;\r
+ }\r
+ */\r
+ }\r
+}\r
+\r
+\r
+//-------------------------------------------------- debugging\r
+\r
+\r
+void QuantConflictFind::debugPrint( const char * c ) {\r
+ //print the equivalance classes\r
+ Trace(c) << "----------EQ classes" << std::endl;\r
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( getEqualityEngine() );\r
+ while( !eqcs_i.isFinished() ){\r
+ Node n = (*eqcs_i);\r
+ //if( !n.getType().isInteger() ){\r
+ Trace(c) << " - " << n << " : {";\r
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( n, getEqualityEngine() );\r
+ bool pr = false;\r
+ while( !eqc_i.isFinished() ){\r
+ Node nn = (*eqc_i);\r
+ if( nn.getKind()!=EQUAL && nn!=n ){\r
+ Trace(c) << (pr ? "," : "" ) << " " << nn;\r
+ pr = true;\r
+ }\r
+ ++eqc_i;\r
+ }\r
+ Trace(c) << (pr ? " " : "" ) << "}" << std::endl;\r
+ /*\r
+ EqcInfo * eqcn = getEqcInfo( n, false );\r
+ if( eqcn ){\r
+ Trace(c) << " DEQ : {";\r
+ pr = false;\r
+ for( NodeBoolMap::iterator it = eqcn->d_diseq.begin(); it != eqcn->d_diseq.end(); ++it ){\r
+ if( (*it).second ){\r
+ Trace(c) << (pr ? "," : "" ) << " " << (*it).first;\r
+ pr = true;\r
+ }\r
+ }\r
+ Trace(c) << (pr ? " " : "" ) << "}" << std::endl;\r
+ }\r
+ //}\r
+ */\r
+ ++eqcs_i;\r
+ }\r
+}\r
+\r
+void QuantConflictFind::debugPrintQuant( const char * c, Node q ) {\r
+ Trace(c) << "Q" << d_quant_id[q];\r
+}\r
+\r
+void QuantConflictFind::debugPrintQuantBody( const char * c, Node q, Node n, bool doVarNum ) {\r
+ if( n.getNumChildren()==0 ){\r
+ Trace(c) << n;\r
+ }else if( doVarNum && d_qinfo[q].d_var_num.find( n )!=d_qinfo[q].d_var_num.end() ){\r
+ Trace(c) << "?x" << d_qinfo[q].d_var_num[n];\r
+ }else{\r
+ Trace(c) << "(";\r
+ if( n.getKind()==APPLY_UF ){\r
+ Trace(c) << n.getOperator();\r
+ }else{\r
+ Trace(c) << n.getKind();\r
+ }\r
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+ Trace(c) << " ";\r
+ debugPrintQuantBody( c, q, n[i] );\r
+ }\r
+ Trace(c) << ")";\r
+ }\r
+}\r
+\r
+QuantConflictFind::Statistics::Statistics():\r
+ d_inst_rounds("QuantConflictFind::Inst_Rounds", 0),\r
+ d_conflict_inst("QuantConflictFind::Instantiations_Conflict_Find", 0 ),\r
+ d_prop_inst("QuantConflictFind::Instantiations_Prop", 0 ),\r
+ d_entailment_checks("QuantConflictFind::Entailment_Checks",0)\r
+{\r
+ StatisticsRegistry::registerStat(&d_inst_rounds);\r
+ StatisticsRegistry::registerStat(&d_conflict_inst);\r
+ StatisticsRegistry::registerStat(&d_prop_inst);\r
+ StatisticsRegistry::registerStat(&d_entailment_checks);\r
+}\r
+\r
+QuantConflictFind::Statistics::~Statistics(){\r
+ StatisticsRegistry::unregisterStat(&d_inst_rounds);\r
+ StatisticsRegistry::unregisterStat(&d_conflict_inst);\r
+ StatisticsRegistry::unregisterStat(&d_prop_inst);\r
+ StatisticsRegistry::unregisterStat(&d_entailment_checks);\r
+}\r
+\r
+TNode QuantConflictFind::getZero( Kind k ) {\r
+ std::map< Kind, Node >::iterator it = d_zero.find( k );\r
+ if( it==d_zero.end() ){\r
+ Node nn;\r
+ if( k==PLUS ){\r
+ nn = NodeManager::currentNM()->mkConst( Rational(0) );\r
+ }\r
+ d_zero[k] = nn;\r
+ return nn;\r
+ }else{\r
+ return it->second;\r
+ }\r
+}\r
+\r
+\r
+}\r