Add new method for checking candidate models, --fmf-fmc. Add infrastructure for...
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 9 May 2013 01:02:10 +0000 (20:02 -0500)
committerAndrew Reynolds <andrew.j.reynolds@gmail.com>
Thu, 9 May 2013 01:02:22 +0000 (20:02 -0500)
26 files changed:
src/smt/smt_engine.cpp
src/theory/quantifiers/Makefile.am
src/theory/quantifiers/bounded_integers.cpp [new file with mode: 0755]
src/theory/quantifiers/bounded_integers.h [new file with mode: 0755]
src/theory/quantifiers/full_model_check.cpp [new file with mode: 0755]
src/theory/quantifiers/full_model_check.h [new file with mode: 0755]
src/theory/quantifiers/inst_match.cpp
src/theory/quantifiers/inst_match.h
src/theory/quantifiers/inst_match_generator.cpp
src/theory/quantifiers/inst_strategy_e_matching.cpp
src/theory/quantifiers/model_builder.cpp
src/theory/quantifiers/model_engine.cpp
src/theory/quantifiers/model_engine.h
src/theory/quantifiers/options
src/theory/quantifiers/quant_util.cpp
src/theory/quantifiers/quant_util.h
src/theory/quantifiers/term_database.cpp
src/theory/quantifiers/term_database.h
src/theory/quantifiers/trigger.cpp
src/theory/quantifiers/trigger.h
src/theory/quantifiers_engine.cpp
src/theory/quantifiers_engine.h
src/theory/uf/options
src/theory/uf/theory_uf_model.cpp
src/theory/uf/theory_uf_model.h
src/theory/uf/theory_uf_strong_solver.cpp

index 0bfc6e63453f38296955855f64d8567676bf9c2b..37ab9cd48fec0716d79a9602bd13609403f7ce7e 100644 (file)
@@ -1018,11 +1018,18 @@ void SmtEngine::setLogicInternal() throw() {
 
   //for finite model finding
   if( ! options::instWhenMode.wasSetByUser()){
+    //instantiate only on last call
     if( options::fmfInstEngine() ){
       Trace("smt") << "setting inst when mode to LAST_CALL" << endl;
       options::instWhenMode.set( INST_WHEN_LAST_CALL );
     }
   }
+  if ( ! options::fmfInstGen.wasSetByUser()) {
+    //if full model checking is on, disable inst-gen techniques
+    if( options::fmfFullModelCheck() ){
+      options::fmfInstGen.set( false );
+    }
+  }
 
   //until bugs 371,431 are fixed
   if( ! options::minisatUseElim.wasSetByUser()){
index 7fea8cf3abe0323eab3cefba2effc6b7b6756c59..1a1413ad660135a13c83f7491fc185a767da11f8 100644 (file)
@@ -44,7 +44,11 @@ libquantifiers_la_SOURCES = \
        inst_strategy_e_matching.h \
        inst_strategy_e_matching.cpp \
        inst_strategy_cbqi.h \
-       inst_strategy_cbqi.cpp
+       inst_strategy_cbqi.cpp \
+       full_model_check.h \
+       full_model_check.cpp \
+       bounded_integers.h \
+       bounded_integers.cpp
 
 EXTRA_DIST = \
        kinds \
diff --git a/src/theory/quantifiers/bounded_integers.cpp b/src/theory/quantifiers/bounded_integers.cpp
new file mode 100755 (executable)
index 0000000..7af6456
--- /dev/null
@@ -0,0 +1,98 @@
+/*********************                                                        */\r
+/*! \file bounded_integers.cpp\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2013  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 Bounded integers module\r
+ **\r
+ ** This class manages integer bounds for quantifiers\r
+ **/\r
+\r
+#include "theory/quantifiers/bounded_integers.h"\r
+#include "theory/quantifiers/quant_util.h"\r
+\r
+using namespace CVC4;\r
+using namespace std;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+using namespace CVC4::kind;\r
+\r
+BoundedIntegers::BoundedIntegers(QuantifiersEngine* qe) : QuantifiersModule(qe){\r
+\r
+}\r
+\r
+void BoundedIntegers::processLiteral( Node f, Node lit, bool pol ) {\r
+  if( lit.getKind()==GEQ && lit[0].getType().isInteger() ){\r
+    std::map< Node, Node > msum;\r
+    if (QuantArith::getMonomialSumLit( lit, msum )){\r
+      Trace("bound-integers") << "Literal " << lit << " is monomial sum : " << std::endl;\r
+      for(std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){\r
+        Trace("bound-integers") << "  ";\r
+        if( !it->second.isNull() ){\r
+          Trace("bound-integers") << it->second;\r
+          if( !it->first.isNull() ){\r
+            Trace("bound-integers") << " * ";\r
+          }\r
+        }\r
+        if( !it->first.isNull() ){\r
+          Trace("bound-integers") << it->first;\r
+        }\r
+        Trace("bound-integers") << std::endl;\r
+      }\r
+      Trace("bound-integers") << std::endl;\r
+      for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){\r
+        if ( !it->first.isNull() && it->first.getKind()==BOUND_VARIABLE ){\r
+          Node veq;\r
+          if( QuantArith::isolate( it->first, msum, veq, GEQ ) ){\r
+            Trace("bound-integers") << "Isolated for " << it->first << " : " << veq << std::endl;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }else if( lit.getKind()==LEQ || lit.getKind()==LT || lit.getKind()==GT ) {\r
+    std::cout << "BoundedIntegers : Bad kind for literal : " << lit << std::endl;\r
+    exit(0);\r
+  }\r
+}\r
+\r
+void BoundedIntegers::process( Node f, Node n, bool pol ){\r
+  if( (( n.getKind()==IMPLIES || n.getKind()==OR) && pol) || (n.getKind()==AND && !pol) ){\r
+    for( unsigned i=0; i<n.getNumChildren(); i++) {\r
+      bool newPol = n.getKind()==IMPLIES && i==0 ? !pol : pol;\r
+      process( f, n[i], newPol );\r
+    }\r
+  }else if( n.getKind()==NOT ){\r
+    process( f, n[0], !pol );\r
+  }else {\r
+    processLiteral( f, n, pol );\r
+  }\r
+}\r
+\r
+void BoundedIntegers::check( Theory::Effort e ) {\r
+\r
+}\r
+\r
+void BoundedIntegers::registerQuantifier( Node f ) {\r
+  bool hasIntType = false;\r
+  for( unsigned i=0; i<f[0].getNumChildren(); i++) {\r
+    if( f[0][i].getType().isInteger() ){\r
+      hasIntType = true;\r
+      break;\r
+    }\r
+  }\r
+  if( hasIntType ){\r
+    process( f, f[1], true );\r
+  }\r
+}\r
+\r
+void BoundedIntegers::assertNode( Node n ) {\r
+\r
+}\r
+\r
+Node BoundedIntegers::getNextDecisionRequest() {\r
+  return Node::null();\r
+}\r
diff --git a/src/theory/quantifiers/bounded_integers.h b/src/theory/quantifiers/bounded_integers.h
new file mode 100755 (executable)
index 0000000..570e27a
--- /dev/null
@@ -0,0 +1,47 @@
+/*********************                                                        */\r
+/*! \file bounded_integers.h\r
+** \verbatim\r
+** Original author: Andrew Reynolds\r
+** This file is part of the CVC4 project.\r
+** Copyright (c) 2009-2013  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 This class manages integer bounds for quantifiers\r
+**/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__BOUNDED_INTEGERS_H\r
+#define __CVC4__BOUNDED_INTEGERS_H\r
+\r
+\r
+#include "theory/quantifiers_engine.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+class BoundedIntegers : public QuantifiersModule\r
+{\r
+private:\r
+  std::map< Node, std::map< Node, Node > > d_lowers;\r
+  std::map< Node, std::map< Node, Node > > d_uppers;\r
+  std::map< Node, std::map< Node, bool > > d_set;\r
+  void hasFreeVar( Node f, Node n );\r
+  void process( Node f, Node n, bool pol );\r
+  void processLiteral( Node f, Node lit, bool pol );\r
+public:\r
+  BoundedIntegers( QuantifiersEngine* qe );\r
+\r
+  void check( Theory::Effort e );\r
+  void registerQuantifier( Node f );\r
+  void assertNode( Node n );\r
+  Node getNextDecisionRequest();\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif
\ No newline at end of file
diff --git a/src/theory/quantifiers/full_model_check.cpp b/src/theory/quantifiers/full_model_check.cpp
new file mode 100755 (executable)
index 0000000..efd193f
--- /dev/null
@@ -0,0 +1,943 @@
+\r
+/*********************                                                        */\r
+/*! \file full_model_check.cpp\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2013  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 Implementation of full model check class\r
+ **/\r
+\r
+#include "theory/quantifiers/full_model_check.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+#include "theory/quantifiers/options.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+using namespace CVC4::theory::inst;\r
+using namespace CVC4::theory::quantifiers::fmcheck;\r
+\r
+\r
+bool EntryTrie::hasGeneralization( FullModelChecker * m, Node c, int index ) {\r
+  if (index==(int)c.getNumChildren()) {\r
+    return d_data!=-1;\r
+  }else{\r
+    Node st = m->getStar(c[index].getType());\r
+    if(d_child.find(st)!=d_child.end()) {\r
+      if( d_child[st].hasGeneralization(m, c, index+1) ){\r
+        return true;\r
+      }\r
+    }\r
+    if( d_child.find( c[index] )!=d_child.end() ){\r
+      if( d_child[ c[index] ].hasGeneralization(m, c, index+1) ){\r
+        return true;\r
+      }\r
+    }\r
+    return false;\r
+  }\r
+}\r
+\r
+int EntryTrie::getGeneralizationIndex( FullModelChecker * m, std::vector<Node> & inst, int index ) {\r
+  if (index==(int)inst.size()) {\r
+    return d_data;\r
+  }else{\r
+    int minIndex = -1;\r
+    Node st = m->getStar(inst[index].getType());\r
+    if(d_child.find(st)!=d_child.end()) {\r
+      minIndex = d_child[st].getGeneralizationIndex(m, inst, index+1);\r
+    }\r
+    Node cc = inst[index];\r
+    if( d_child.find( cc )!=d_child.end() ){\r
+      int gindex = d_child[ cc ].getGeneralizationIndex(m, inst, index+1);\r
+      if (minIndex==-1 || (gindex!=-1 && gindex<minIndex) ){\r
+        minIndex = gindex;\r
+      }\r
+    }\r
+    return minIndex;\r
+  }\r
+}\r
+\r
+void EntryTrie::addEntry( FullModelChecker * m, Node c, Node v, int data, int index ) {\r
+  if (index==(int)c.getNumChildren()) {\r
+    if(d_data==-1) {\r
+      d_data = data;\r
+    }\r
+  }\r
+  else {\r
+    d_child[ c[index] ].addEntry(m,c,v,data,index+1);\r
+  }\r
+}\r
+\r
+void EntryTrie::getEntries( FullModelChecker * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index, bool is_gen ) {\r
+  if (index==(int)c.getNumChildren()) {\r
+    if( d_data!=-1) {\r
+      if( is_gen ){\r
+        gen.push_back(d_data);\r
+      }\r
+      compat.push_back(d_data);\r
+    }\r
+  }else{\r
+    if (m->isStar(c[index])) {\r
+      for ( std::map<Node,EntryTrie>::iterator it = d_child.begin(); it != d_child.end(); ++it ){\r
+        it->second.getEntries(m, c, compat, gen, index+1, is_gen );\r
+      }\r
+    }else{\r
+      Node st = m->getStar(c[index].getType());\r
+      if(d_child.find(st)!=d_child.end()) {\r
+        d_child[st].getEntries(m, c, compat, gen, index+1, false);\r
+      }\r
+      if( d_child.find( c[index] )!=d_child.end() ){\r
+        d_child[ c[index] ].getEntries(m, c, compat, gen, index+1, is_gen);\r
+      }\r
+    }\r
+\r
+  }\r
+}\r
+\r
+bool EntryTrie::getWitness( FullModelChecker * m, FirstOrderModel * fm, Node c, std::vector<Node> & inst, int index) {\r
+\r
+  return false;\r
+}\r
+\r
+\r
+bool Def::addEntry( FullModelChecker * m, Node c, Node v) {\r
+  if (!d_et.hasGeneralization(m, c)) {\r
+    int newIndex = (int)d_cond.size();\r
+    if (!d_has_simplified) {\r
+      std::vector<int> compat;\r
+      std::vector<int> gen;\r
+      d_et.getEntries(m, c, compat, gen);\r
+      for( unsigned i=0; i<compat.size(); i++) {\r
+        if( d_status[compat[i]]==status_unk ){\r
+          if( d_value[compat[i]]!=v ){\r
+            d_status[compat[i]] = status_non_redundant;\r
+          }\r
+        }\r
+      }\r
+      for( unsigned i=0; i<gen.size(); i++) {\r
+        if( d_status[gen[i]]==status_unk ){\r
+          if( d_value[gen[i]]==v ){\r
+            d_status[gen[i]] = status_redundant;\r
+          }\r
+        }\r
+      }\r
+      d_status.push_back( status_unk );\r
+    }\r
+    d_et.addEntry(m, c, v, newIndex);\r
+    d_cond.push_back(c);\r
+    d_value.push_back(v);\r
+    return true;\r
+  }else{\r
+    return false;\r
+  }\r
+}\r
+\r
+Node Def::evaluate( FullModelChecker * m, std::vector<Node> inst ) {\r
+  int gindex = d_et.getGeneralizationIndex(m, inst);\r
+  if (gindex!=-1) {\r
+    return d_value[gindex];\r
+  }else{\r
+    return Node::null();\r
+  }\r
+}\r
+\r
+int Def::getGeneralizationIndex( FullModelChecker * m, std::vector<Node> inst ) {\r
+  return d_et.getGeneralizationIndex(m, inst);\r
+}\r
+\r
+void Def::simplify(FullModelChecker * m) {\r
+  d_has_simplified = true;\r
+  std::vector< Node > cond;\r
+  cond.insert( cond.end(), d_cond.begin(), d_cond.end() );\r
+  d_cond.clear();\r
+  std::vector< Node > value;\r
+  value.insert( value.end(), d_value.begin(), d_value.end() );\r
+  d_value.clear();\r
+  d_et.reset();\r
+  for (unsigned i=0; i<d_status.size(); i++) {\r
+    if( d_status[i]!=status_redundant ){\r
+      addEntry(m, d_cond[i], d_value[i]);\r
+    }\r
+  }\r
+  d_status.clear();\r
+}\r
+\r
+void Def::debugPrint(const char * tr, Node op, FullModelChecker * m) {\r
+  if (!op.isNull()) {\r
+    Trace(tr) << "Model for " << op << " : " << std::endl;\r
+  }\r
+  for( unsigned i=0; i<d_cond.size(); i++) {\r
+    //print the condition\r
+    if (!op.isNull()) {\r
+      Trace(tr) << op;\r
+    }\r
+    m->debugPrintCond(tr, d_cond[i], true);\r
+    Trace(tr) << " -> ";\r
+    m->debugPrint(tr, d_value[i]);\r
+    Trace(tr) << std::endl;\r
+  }\r
+}\r
+\r
+\r
+FullModelChecker::FullModelChecker(QuantifiersEngine* qe) : d_qe(qe){\r
+  d_true = NodeManager::currentNM()->mkConst(true);\r
+  d_false = NodeManager::currentNM()->mkConst(false);\r
+}\r
+\r
+void FullModelChecker::reset(FirstOrderModel * fm) {\r
+  Trace("fmc") << "---Full Model Check reset() " << std::endl;\r
+  for( std::map<Node, Def * >::iterator it = d_models.begin(); it != d_models.end(); ++it ){\r
+    it->second->reset();\r
+  }\r
+  d_quant_models.clear();\r
+  d_models_init.clear();\r
+  d_rep_ids.clear();\r
+  d_model_basis_rep.clear();\r
+  d_star_insts.clear();\r
+  //process representatives\r
+  for( std::map< TypeNode, std::vector< Node > >::iterator it = fm->d_rep_set.d_type_reps.begin();\r
+       it != fm->d_rep_set.d_type_reps.end(); ++it ){\r
+    if( it->first.isSort() ){\r
+      if( d_type_star.find(it->first)==d_type_star.end() ){\r
+        Node st = NodeManager::currentNM()->mkSkolem( "star_$$", it->first, "skolem created for full-model checking" );\r
+        d_type_star[it->first] = st;\r
+      }\r
+      Trace("fmc") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;\r
+      Node mbt = d_qe->getTermDatabase()->getModelBasisTerm(it->first);\r
+      Node rmbt = fm->getRepresentative(mbt);\r
+      int mbt_index = -1;\r
+      Trace("fmc") << "  Model basis term : " << mbt << std::endl;\r
+      for( size_t a=0; a<it->second.size(); a++ ){\r
+        //Node r2 = ((EqualityQueryQuantifiersEngine*)d_qe->getEqualityQuery())->getRepresentative( it->second[a] );\r
+        //Node ir = ((EqualityQueryQuantifiersEngine*)d_qe->getEqualityQuery())->getInternalRepresentative( it->second[a], Node::null(), 0 );\r
+        Node r = fm->getRepresentative( it->second[a] );\r
+        std::vector< Node > eqc;\r
+        ((EqualityQueryQuantifiersEngine*)d_qe->getEqualityQuery())->getEquivalenceClass( r, eqc );\r
+        Trace("fmc-model-debug") << "   " << (it->second[a]==r) << (r==mbt);\r
+        Trace("fmc-model-debug") << " : " << it->second[a] << " : " << r << " : ";\r
+        //Trace("fmc-model-debug") << r2 << " : " << ir << " : ";\r
+        Trace("fmc-model-debug") << " {";\r
+        //find best selection for representative\r
+        for( size_t i=0; i<eqc.size(); i++ ){\r
+          Trace("fmc-model-debug") << eqc[i] << ", ";\r
+        }\r
+        Trace("fmc-model-debug") << "}" << std::endl;\r
+\r
+        //if this is the model basis eqc, replace with actual model basis term\r
+        if (r==rmbt || (mbt_index==-1 && a==(it->second.size()-1))) {\r
+          d_model_basis_rep[it->first] = r;\r
+          r = mbt;\r
+          mbt_index = a;\r
+        }\r
+        d_rep_ids[it->first][r] = (int)a;\r
+      }\r
+      Trace("fmc-model-debug") << std::endl;\r
+\r
+      if (mbt_index==-1) {\r
+        std::cout << "   WARNING: model basis term is not a representative!" << std::endl;\r
+        exit(0);\r
+      }else{\r
+        Trace("fmc") << "Star index for " << it->first << " is " << mbt_index << std::endl;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+Node FullModelChecker::getRepresentative(FirstOrderModel * fm, Node n) {\r
+  //Assert( fm->hasTerm(n) );\r
+  TypeNode tn = n.getType();\r
+  if( tn.isBoolean() ){\r
+    return fm->areEqual(n, d_true) ? d_true : d_false;\r
+  }else{\r
+    Node r = fm->getRepresentative(n);\r
+    if (r==d_model_basis_rep[tn]) {\r
+      r = d_qe->getTermDatabase()->getModelBasisTerm(tn);\r
+    }\r
+    return r;\r
+  }\r
+}\r
+\r
+struct ModelBasisArgSort\r
+{\r
+  std::vector< Node > d_terms;\r
+  bool operator() (int i,int j) {\r
+    return (d_terms[i].getAttribute(ModelBasisArgAttribute()) <\r
+            d_terms[j].getAttribute(ModelBasisArgAttribute()) );\r
+  }\r
+};\r
+\r
+void FullModelChecker::addEntry( FirstOrderModel * fm, Node op, Node c, Node v,\r
+                                 std::vector< Node > & conds,\r
+                                 std::vector< Node > & values,\r
+                                 std::vector< Node > & entry_conds ) {\r
+  std::vector< Node > children;\r
+  std::vector< Node > entry_children;\r
+  children.push_back(op);\r
+  entry_children.push_back(op);\r
+  bool hasNonStar = false;\r
+  for( unsigned i=0; i<c.getNumChildren(); i++) {\r
+    Node ri = getRepresentative(fm, c[i]);\r
+    children.push_back(ri);\r
+    if (isModelBasisTerm(ri)) {\r
+      ri = d_type_star[ri.getType()];\r
+    }else{\r
+      hasNonStar = true;\r
+    }\r
+    entry_children.push_back(ri);\r
+  }\r
+  Node n = NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
+  Node nv = getRepresentative(fm, v);\r
+  Node en = (useSimpleModels() && hasNonStar) ? n : NodeManager::currentNM()->mkNode( APPLY_UF, entry_children );\r
+  if( std::find(conds.begin(), conds.end(), n )==conds.end() ){\r
+    Trace("fmc-model-debug") << "- add " << n << " -> " << nv << " (entry is " << en << ")" << std::endl;\r
+    conds.push_back(n);\r
+    values.push_back(nv);\r
+    entry_conds.push_back(en);\r
+  }\r
+}\r
+\r
+Def * FullModelChecker::getModel(FirstOrderModel * fm, Node op) {\r
+  if( d_models_init.find(op)==d_models_init.end() ){\r
+    if( d_models.find(op)==d_models.end() ){\r
+      d_models[op] = new Def;\r
+      //make sure star's are defined\r
+      TypeNode tn = op.getType();\r
+      for(unsigned i=0; i<tn.getNumChildren()-1; i++) {\r
+        if( d_type_star.find(tn[i])==d_type_star.end() ){\r
+          Node st = NodeManager::currentNM()->mkSkolem( "star_$$", tn[i], "skolem created for full-model checking" );\r
+          d_type_star[tn[i]] = st;\r
+        }\r
+      }\r
+    }\r
+    //reset the model\r
+    d_models[op]->reset();\r
+\r
+    std::vector< Node > conds;\r
+    std::vector< Node > values;\r
+    std::vector< Node > entry_conds;\r
+    Trace("fmc-model-debug") << "Model values for " << op << " ... " << std::endl;\r
+    for( size_t i=0; i<fm->d_uf_terms[op].size(); i++ ){\r
+      Node r = getRepresentative(fm, fm->d_uf_terms[op][i]);\r
+      Trace("fmc-model-debug") << fm->d_uf_terms[op][i] << " -> " << r << std::endl;\r
+    }\r
+    Trace("fmc-model-debug") << std::endl;\r
+    //initialize the model\r
+    for( int j=0; j<2; j++ ){\r
+      for( int k=1; k>=0; k-- ){\r
+        Trace("fmc-model-debug")<< "Set values " << j << " " << k << " : " << std::endl;\r
+        for( std::map< Node, Node >::iterator it = fm->d_uf_model_gen[op].d_set_values[j][k].begin();\r
+             it != fm->d_uf_model_gen[op].d_set_values[j][k].end(); ++it ){\r
+          Trace("fmc-model-debug") << "   process : " << it->first << " -> " << it->second << std::endl;\r
+          if( j==1 ){\r
+            addEntry(fm, op, it->first, it->second, conds, values, entry_conds);\r
+          }\r
+        }\r
+      }\r
+    }\r
+    //add for default value\r
+    if (!fm->d_uf_model_gen[op].d_default_value.isNull()) {\r
+      Node n = d_qe->getTermDatabase()->getModelBasisOpTerm(op);\r
+      addEntry(fm, op, n, fm->d_uf_model_gen[op].d_default_value, conds, values, entry_conds);\r
+    }\r
+\r
+    //find other default values (TODO: figure out why these entries are added to d_uf_model_gen)\r
+    if( conds.empty() ){\r
+      //for( std::map< Node, Node >::iterator it = fm->d_uf_model_gen[op].d_set_values[1][0].begin();\r
+      //     it != fm->d_uf_model_gen[op].d_set_values[1][0].end(); ++it ){\r
+      //  Trace("fmc-model-debug") << "   process : " << it->first << " -> " << it->second << std::endl;\r
+      //  addEntry(fm, op, it->first, it->second, conds, values, entry_conds);\r
+      //}\r
+      Trace("fmc-warn") << "WARNING: No entries for " << op << ", make default entry." << std::endl;\r
+      //choose a complete arbitrary term\r
+      Node n = d_qe->getTermDatabase()->getModelBasisOpTerm(op);\r
+      TypeNode tn = n.getType();\r
+      Node v = fm->d_rep_set.d_type_reps[tn][0];\r
+      addEntry(fm, op, n, v, conds, values, entry_conds);\r
+    }\r
+\r
+    //sort based on # default arguments\r
+    std::vector< int > indices;\r
+    ModelBasisArgSort mbas;\r
+    for (int i=0; i<(int)conds.size(); i++) {\r
+      d_qe->getTermDatabase()->computeModelBasisArgAttribute( conds[i] );\r
+      mbas.d_terms.push_back(conds[i]);\r
+      indices.push_back(i);\r
+    }\r
+    std::sort( indices.begin(), indices.end(), mbas );\r
+\r
+\r
+    for (int i=0; i<(int)indices.size(); i++) {\r
+      d_models[op]->addEntry(this, entry_conds[indices[i]], values[indices[i]]);\r
+    }\r
+    d_models[op]->debugPrint("fmc-model", op, this);\r
+    Trace("fmc-model") << std::endl;\r
+\r
+    d_models[op]->simplify( this );\r
+    Trace("fmc-model-simplify") << "After simplification : " << std::endl;\r
+    d_models[op]->debugPrint("fmc-model-simplify", op, this);\r
+    Trace("fmc-model-simplify") << std::endl;\r
+\r
+    d_models_init[op] = true;\r
+  }\r
+  return d_models[op];\r
+}\r
+\r
+\r
+bool FullModelChecker::isStar(Node n) {\r
+  return n==d_type_star[n.getType()];\r
+}\r
+\r
+bool FullModelChecker::isModelBasisTerm(Node n) {\r
+  return n==getModelBasisTerm(n.getType());\r
+}\r
+\r
+Node FullModelChecker::getModelBasisTerm(TypeNode tn) {\r
+  return d_qe->getTermDatabase()->getModelBasisTerm(tn);\r
+}\r
+\r
+void FullModelChecker::debugPrintCond(const char * tr, Node n, bool dispStar) {\r
+  Trace(tr) << "(";\r
+  for( unsigned j=0; j<n.getNumChildren(); j++) {\r
+    if( j>0 ) Trace(tr) << ", ";\r
+    debugPrint(tr, n[j], dispStar);\r
+  }\r
+  Trace(tr) << ")";\r
+}\r
+\r
+void FullModelChecker::debugPrint(const char * tr, Node n, bool dispStar) {\r
+  if( n.isNull() ){\r
+    Trace(tr) << "null";\r
+  }\r
+  else if(isStar(n) && dispStar) {\r
+    Trace(tr) << "*";\r
+  }else{\r
+    TypeNode tn = n.getType();\r
+    if( d_rep_ids.find(tn)!=d_rep_ids.end() ){\r
+      if (d_rep_ids[tn].find(n)!=d_rep_ids[tn].end()) {\r
+        Trace(tr) << d_rep_ids[tn][n];\r
+      }else{\r
+        Trace(tr) << n;\r
+      }\r
+    }else{\r
+        Trace(tr) << n;\r
+    }\r
+  }\r
+}\r
+\r
+\r
+int FullModelChecker::exhaustiveInstantiate(FirstOrderModel * fm, Node f, int effort) {\r
+  int addedLemmas = 0;\r
+  Trace("fmc") << "Full model check " << f << ", effort = " << effort << "..." << std::endl;\r
+  if (effort==0) {\r
+    //register the quantifier\r
+    if (d_quant_cond.find(f)==d_quant_cond.end()) {\r
+      std::vector< TypeNode > types;\r
+      for(unsigned i=0; i<f[0].getNumChildren(); i++){\r
+        types.push_back(f[0][i].getType());\r
+        d_quant_var_id[f][f[0][i]] = i;\r
+      }\r
+      TypeNode typ = NodeManager::currentNM()->mkFunctionType( types, NodeManager::currentNM()->booleanType() );\r
+      Node op = NodeManager::currentNM()->mkSkolem( "fmc_$$", typ, "op created for full-model checking" );\r
+      d_quant_cond[f] = op;\r
+    }\r
+\r
+    //model check the quantifier\r
+    doCheck(fm, f, d_quant_models[f], f[1]);\r
+    Trace("fmc") << "Definition for quantifier " << f << " is : " << std::endl;\r
+    d_quant_models[f].debugPrint("fmc", Node::null(), this);\r
+    Trace("fmc") << std::endl;\r
+    //consider all entries going to false\r
+    for (unsigned i=0; i<d_quant_models[f].d_cond.size(); i++) {\r
+      if( d_quant_models[f].d_value[i]!=d_true) {\r
+        Trace("fmc-inst") << "Instantiate based on " << d_quant_models[f].d_cond[i] << "..." << std::endl;\r
+        bool hasStar = false;\r
+        std::vector< Node > inst;\r
+        for (unsigned j=0; j<d_quant_models[f].d_cond[i].getNumChildren(); j++) {\r
+          if (isStar(d_quant_models[f].d_cond[i][j])) {\r
+            hasStar = true;\r
+            inst.push_back(getModelBasisTerm(d_quant_models[f].d_cond[i][j].getType()));\r
+          }else{\r
+            inst.push_back(d_quant_models[f].d_cond[i][j]);\r
+          }\r
+        }\r
+        bool addInst = true;\r
+        if( hasStar ){\r
+          //try obvious (specified by inst)\r
+          Node ev = d_quant_models[f].evaluate(this, inst);\r
+          if (ev==d_true) {\r
+            addInst = false;\r
+          }\r
+        }else{\r
+          //for debugging\r
+          if (Trace.isOn("fmc-test-inst")) {\r
+            Node ev = d_quant_models[f].evaluate(this, inst);\r
+            if( ev==d_true ){\r
+              std::cout << "WARNING: instantiation was true! " << f << " " << d_quant_models[f].d_cond[i] << std::endl;\r
+              exit(0);\r
+            }else{\r
+              Trace("fmc-test-inst") << "...instantiation evaluated to false." << std::endl;\r
+            }\r
+          }\r
+        }\r
+        if( addInst ){\r
+          InstMatch m;\r
+          for( unsigned j=0; j<inst.size(); j++) {\r
+            m.set( d_qe, f, j, inst[j] );\r
+          }\r
+          if (isActive()) {\r
+            if( d_qe->addInstantiation( f, m ) ){\r
+              addedLemmas++;\r
+            }else{\r
+              //this can happen if evaluation is unknown\r
+              //might try it next effort level\r
+              d_star_insts[f].push_back(i);\r
+            }\r
+          }\r
+        }else{\r
+          //might try it next effort level\r
+          d_star_insts[f].push_back(i);\r
+        }\r
+      }\r
+    }\r
+  }else{\r
+    //TODO\r
+    Trace("fmc-exh") << "Definition was : " << std::endl;\r
+    d_quant_models[f].debugPrint("fmc-exh", Node::null(), this);\r
+    Trace("fmc-exh") << std::endl;\r
+    Def temp;\r
+    //simplify the exceptions?\r
+    for( int i=(d_star_insts[f].size()-1); i>=0; i--) {\r
+      //get witness for d_star_insts[f][i]\r
+      int j = d_star_insts[f][i];\r
+      if( temp.addEntry( this, d_quant_models[f].d_cond[j], d_quant_models[f].d_value[j] ) ){\r
+        int lem = exhaustiveInstantiate(fm, f, d_quant_models[f].d_cond[j], j );\r
+        if( lem==-1 ){\r
+          return -1;\r
+        }else{\r
+          addedLemmas += lem;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return addedLemmas;\r
+}\r
+\r
+int FullModelChecker::exhaustiveInstantiate(FirstOrderModel * fm, Node f, Node c, int c_index) {\r
+  int addedLemmas = 0;\r
+  RepSetIterator riter( &(fm->d_rep_set) );\r
+  Trace("fmc-exh") << "Exhaustive instantiate based on index " << c_index << " : " << c << " ";\r
+  debugPrintCond("fmc-exh", c, true);\r
+  Trace("fmc-exh")<< std::endl;\r
+  if( riter.setQuantifier( f ) ){\r
+    std::vector< RepDomain > dom;\r
+    for (unsigned i=0; i<c.getNumChildren(); i++) {\r
+      TypeNode tn = c[i].getType();\r
+      if( d_rep_ids.find(tn)!=d_rep_ids.end() ){\r
+        RepDomain rd;\r
+        if( isStar(c[i]) ){\r
+          //add the full range\r
+          for( std::map< Node, int >::iterator it = d_rep_ids[tn].begin();\r
+               it != d_rep_ids[tn].end(); ++it ){\r
+            rd.push_back(it->second);\r
+          }\r
+        }else{\r
+          if (d_rep_ids[tn].find(c[i])!=d_rep_ids[tn].end()) {\r
+            rd.push_back(d_rep_ids[tn][c[i]]);\r
+          }else{\r
+            return -1;\r
+          }\r
+        }\r
+        dom.push_back(rd);\r
+      }else{\r
+        return -1;\r
+      }\r
+    }\r
+    riter.setDomain(dom);\r
+    //now do full iteration\r
+    while( !riter.isFinished() ){\r
+      Trace("fmc-exh-debug") << "Inst : ";\r
+      std::vector< Node > inst;\r
+      for( int i=0; i<riter.getNumTerms(); i++ ){\r
+        //m.set( d_quantEngine, f, riter.d_index_order[i], riter.getTerm( i ) );\r
+        Node r = getRepresentative( fm, riter.getTerm( i ) );\r
+        debugPrint("fmc-exh-debug", r);\r
+        Trace("fmc-exh-debug") << " ";\r
+        inst.push_back(r);\r
+      }\r
+\r
+      int ev_index = d_quant_models[f].getGeneralizationIndex(this, inst);\r
+      Trace("fmc-exh-debug") << ", index = " << ev_index;\r
+      Node ev = ev_index==-1 ? Node::null() : d_quant_models[f].d_value[ev_index];\r
+      if (ev!=d_true) {\r
+        InstMatch m;\r
+        for( int i=0; i<riter.getNumTerms(); i++ ){\r
+          m.set( d_qe, f, i, riter.getTerm( i ) );\r
+        }\r
+        Trace("fmc-exh-debug") << ", add!";\r
+        //add as instantiation\r
+        if( d_qe->addInstantiation( f, m ) ){\r
+          addedLemmas++;\r
+        }\r
+      }\r
+      Trace("fmc-exh-debug") << std::endl;\r
+      riter.increment();\r
+    }\r
+  }\r
+  return addedLemmas;\r
+}\r
+\r
+void FullModelChecker::doCheck(FirstOrderModel * fm, Node f, Def & d, Node n ) {\r
+  Trace("fmc-debug") << "Check " << n << " " << n.getKind() << std::endl;\r
+  if( n.getKind() == kind::BOUND_VARIABLE ){\r
+    d.addEntry(this, mkCondDefault(f), n);\r
+  }\r
+  else if( n.getNumChildren()==0 ){\r
+    Node r = n;\r
+    if( !fm->hasTerm(n) ){\r
+      if (fm->d_rep_set.hasType(n.getType())) {\r
+        r = fm->d_rep_set.d_type_reps[n.getType()][0];\r
+      }else{\r
+        //should never happen?\r
+      }\r
+    }\r
+    r = getRepresentative(fm, r);\r
+    d.addEntry(this, mkCondDefault(f), r);\r
+  }\r
+  else if( n.getKind() == kind::NOT ){\r
+    //just do directly\r
+    doCheck( fm, f, d, n[0] );\r
+    doNegate( d );\r
+  }\r
+  else if( n.getKind() == kind::FORALL ){\r
+    d.addEntry(this, mkCondDefault(f), Node::null());\r
+  }\r
+  else{\r
+    std::vector< int > var_ch;\r
+    std::vector< Def > children;\r
+    for( int i=0; i<(int)n.getNumChildren(); i++) {\r
+      Def dc;\r
+      doCheck(fm, f, dc, n[i]);\r
+      children.push_back(dc);\r
+      if( n[i].getKind() == kind::BOUND_VARIABLE ){\r
+        var_ch.push_back(i);\r
+      }\r
+    }\r
+\r
+    if( n.getKind()==APPLY_UF ){\r
+      Trace("fmc-debug") << "Do uninterpreted compose " << n << std::endl;\r
+      //uninterpreted compose\r
+      doUninterpretedCompose( fm, f, d, n.getOperator(), children );\r
+    } else {\r
+      if( !var_ch.empty() ){\r
+        if( n.getKind()==EQUAL ){\r
+          if( var_ch.size()==2 ){\r
+            Trace("fmc-debug") << "Do variable equality " << n << std::endl;\r
+            doVariableEquality( fm, f, d, n );\r
+          }else{\r
+            Trace("fmc-debug") << "Do variable relation " << n << std::endl;\r
+            doVariableRelation( fm, f, d, var_ch[0]==0 ? children[1] : children[0], var_ch[0]==0 ? n[0] : n[1] );\r
+          }\r
+        }else{\r
+          std::cout << "Don't know how to check " << n << std::endl;\r
+          exit(0);\r
+        }\r
+      }else{\r
+        Trace("fmc-debug") << "Do interpreted compose " << n << std::endl;\r
+        std::vector< Node > cond;\r
+        mkCondDefaultVec(f, cond);\r
+        std::vector< Node > val;\r
+        //interpreted compose\r
+        doInterpretedCompose( fm, f, d, n, children, 0, cond, val );\r
+      }\r
+    }\r
+    d.simplify(this);\r
+  }\r
+  Trace("fmc-debug") << "Definition for " << n << " is : " << std::endl;\r
+  d.debugPrint("fmc-debug", Node::null(), this);\r
+  Trace("fmc-debug") << std::endl;\r
+}\r
+\r
+void FullModelChecker::doNegate( Def & dc ) {\r
+  for (unsigned i=0; i<dc.d_cond.size(); i++) {\r
+    if (!dc.d_value[i].isNull()) {\r
+      dc.d_value[i] = dc.d_value[i]==d_true ? d_false : d_true;\r
+    }\r
+  }\r
+}\r
+\r
+void FullModelChecker::doVariableEquality( FirstOrderModel * fm, Node f, Def & d, Node eq ) {\r
+  std::vector<Node> cond;\r
+  mkCondDefaultVec(f, cond);\r
+  if (eq[0]==eq[1]){\r
+    d.addEntry(this, mkCond(cond), d_true);\r
+  }else{\r
+    int j = getVariableId(f, eq[0]);\r
+    int k = getVariableId(f, eq[1]);\r
+    TypeNode tn = eq[0].getType();\r
+    for (unsigned i=0; i<fm->d_rep_set.d_type_reps[tn].size(); i++) {\r
+      Node r = getRepresentative( fm, fm->d_rep_set.d_type_reps[tn][i] );\r
+      cond[j+1] = r;\r
+      cond[k+1] = r;\r
+      d.addEntry( this, mkCond(cond), d_true);\r
+    }\r
+    d.addEntry(this, mkCondDefault(f), d_false);\r
+  }\r
+}\r
+\r
+void FullModelChecker::doVariableRelation( FirstOrderModel * fm, Node f, Def & d, Def & dc, Node v) {\r
+  int j = getVariableId(f, v);\r
+  for (unsigned i=0; i<dc.d_cond.size(); i++) {\r
+    Node val = dc.d_value[i];\r
+    if( dc.d_cond[i][j]!=val ){\r
+      if (isStar(dc.d_cond[i][j])) {\r
+        std::vector<Node> cond;\r
+        mkCondVec(dc.d_cond[i],cond);\r
+        cond[j+1] = val;\r
+        d.addEntry(this, mkCond(cond), d_true);\r
+        cond[j+1] = d_type_star[val.getType()];\r
+        d.addEntry(this, mkCond(cond), d_false);\r
+      }else{\r
+        d.addEntry( this, dc.d_cond[i], d_false);\r
+      }\r
+    }else{\r
+      d.addEntry( this, dc.d_cond[i], d_true);\r
+    }\r
+  }\r
+}\r
+\r
+void FullModelChecker::doUninterpretedCompose( FirstOrderModel * fm, Node f, Def & d, Node op, std::vector< Def > & dc ) {\r
+  Trace("fmc-uf-debug") << "Definition : " << std::endl;\r
+  d_models[op]->debugPrint("fmc-uf-debug", op, this);\r
+  Trace("fmc-uf-debug") << std::endl;\r
+\r
+  std::vector< Node > cond;\r
+  mkCondDefaultVec(f, cond);\r
+  std::vector< Node > val;\r
+  doUninterpretedCompose( fm, f, op, d, dc, 0, cond, val);\r
+}\r
+\r
+void FullModelChecker::doUninterpretedCompose( FirstOrderModel * fm, Node f, Node op, Def & d,\r
+                                               std::vector< Def > & dc, int index,\r
+                                               std::vector< Node > & cond, std::vector<Node> & val ) {\r
+  Trace("fmc-uf-process") << "process at " << index << std::endl;\r
+  for( unsigned i=1; i<cond.size(); i++) {\r
+    debugPrint("fmc-uf-process", cond[i], true);\r
+    Trace("fmc-uf-process") << " ";\r
+  }\r
+  Trace("fmc-uf-process") << std::endl;\r
+  if (index==(int)dc.size()) {\r
+    //we have an entry, now do actual compose\r
+    std::map< int, Node > entries;\r
+    doUninterpretedCompose2( fm, f, entries, 0, cond, val, d_models[op]->d_et);\r
+    //add them to the definition\r
+    for( unsigned e=0; e<d_models[op]->d_cond.size(); e++ ){\r
+      if ( entries.find(e)!=entries.end() ){\r
+        d.addEntry(this, entries[e], d_models[op]->d_value[e] );\r
+      }\r
+    }\r
+  }else{\r
+    for (unsigned i=0; i<dc[index].d_cond.size(); i++) {\r
+      if (isCompat(cond, dc[index].d_cond[i])!=0) {\r
+        std::vector< Node > new_cond;\r
+        new_cond.insert(new_cond.end(), cond.begin(), cond.end());\r
+        if( doMeet(new_cond, dc[index].d_cond[i]) ){\r
+          Trace("fmc-uf-process") << "index " << i << " succeeded meet." << std::endl;\r
+          val.push_back(dc[index].d_value[i]);\r
+          doUninterpretedCompose(fm, f, op, d, dc, index+1, new_cond, val);\r
+          val.pop_back();\r
+        }else{\r
+          Trace("fmc-uf-process") << "index " << i << " failed meet." << std::endl;\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void FullModelChecker::doUninterpretedCompose2( FirstOrderModel * fm, Node f,\r
+                                                std::map< int, Node > & entries, int index,\r
+                                                std::vector< Node > & cond, std::vector< Node > & val,\r
+                                                EntryTrie & curr ) {\r
+  Trace("fmc-uf-process") << "compose " << index << std::endl;\r
+  for( unsigned i=1; i<cond.size(); i++) {\r
+    debugPrint("fmc-uf-process", cond[i], true);\r
+    Trace("fmc-uf-process") << " ";\r
+  }\r
+  Trace("fmc-uf-process") << std::endl;\r
+  if (index==(int)val.size()) {\r
+    Node c = mkCond(cond);\r
+    Trace("fmc-uf-entry") << "Entry : " << c << " -> index[" << curr.d_data << "]" << std::endl;\r
+    entries[curr.d_data] = c;\r
+  }else{\r
+    Node v = val[index];\r
+    bool bind_var = false;\r
+    if( v.getKind()==kind::BOUND_VARIABLE ){\r
+      int j = getVariableId(f, v);\r
+      Trace("fmc-uf-process") << v << " is variable #" << j << std::endl;\r
+      if (!isStar(cond[j+1])) {\r
+        v = cond[j+1];\r
+      }else{\r
+        bind_var = true;\r
+      }\r
+    }\r
+    if (bind_var) {\r
+      Trace("fmc-uf-process") << "bind variable..." << std::endl;\r
+      int j = getVariableId(f, v);\r
+      for (std::map<Node, EntryTrie>::iterator it = curr.d_child.begin(); it != curr.d_child.end(); ++it) {\r
+        cond[j+1] = it->first;\r
+        doUninterpretedCompose2(fm, f, entries, index+1, cond, val, it->second);\r
+      }\r
+      cond[j+1] = getStar(v.getType());\r
+    }else{\r
+      if (curr.d_child.find(v)!=curr.d_child.end()) {\r
+        Trace("fmc-uf-process") << "follow value..." << std::endl;\r
+        doUninterpretedCompose2(fm, f, entries, index+1, cond, val, curr.d_child[v]);\r
+      }\r
+      Node st = d_type_star[v.getType()];\r
+      if (curr.d_child.find(st)!=curr.d_child.end()) {\r
+        Trace("fmc-uf-process") << "follow star..." << std::endl;\r
+        doUninterpretedCompose2(fm, f, entries, index+1, cond, val, curr.d_child[st]);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void FullModelChecker::doInterpretedCompose( FirstOrderModel * fm, Node f, Def & d, Node n,\r
+                                             std::vector< Def > & dc, int index,\r
+                                             std::vector< Node > & cond, std::vector<Node> & val ) {\r
+  if ( index==(int)dc.size() ){\r
+    Node c = mkCond(cond);\r
+    Node v = evaluateInterpreted(n, val);\r
+    d.addEntry(this, c, v);\r
+  }\r
+  else {\r
+    TypeNode vtn = n.getType();\r
+    for (unsigned i=0; i<dc[index].d_cond.size(); i++) {\r
+      if (isCompat(cond, dc[index].d_cond[i])!=0) {\r
+        std::vector< Node > new_cond;\r
+        new_cond.insert(new_cond.end(), cond.begin(), cond.end());\r
+        if( doMeet(new_cond, dc[index].d_cond[i]) ){\r
+          bool process = true;\r
+          if (vtn.isBoolean()) {\r
+            //short circuit\r
+            if( (n.getKind()==OR && dc[index].d_value[i]==d_true) ||\r
+                (n.getKind()==AND && dc[index].d_value[i]==d_false) ){\r
+              Node c = mkCond(new_cond);\r
+              d.addEntry(this, c, dc[index].d_value[i]);\r
+              process = false;\r
+            }\r
+          }\r
+          if (process) {\r
+            val.push_back(dc[index].d_value[i]);\r
+            doInterpretedCompose(fm, f, d, n, dc, index+1, new_cond, val);\r
+            val.pop_back();\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+int FullModelChecker::isCompat( std::vector< Node > & cond, Node c ) {\r
+  Assert(cond.size()==c.getNumChildren()+1);\r
+  for (unsigned i=1; i<cond.size(); i++) {\r
+    if( cond[i]!=c[i-1] && !isStar(cond[i]) && !isStar(c[i-1]) ) {\r
+      return 0;\r
+    }\r
+  }\r
+  return 1;\r
+}\r
+\r
+bool FullModelChecker::doMeet( std::vector< Node > & cond, Node c ) {\r
+  Assert(cond.size()==c.getNumChildren()+1);\r
+  for (unsigned i=1; i<cond.size(); i++) {\r
+    if( cond[i]!=c[i-1] ) {\r
+      if( isStar(cond[i]) ){\r
+        cond[i] = c[i-1];\r
+      }else if( !isStar(c[i-1]) ){\r
+        return false;\r
+      }\r
+    }\r
+  }\r
+  return true;\r
+}\r
+\r
+Node FullModelChecker::mkCond( std::vector< Node > & cond ) {\r
+  return NodeManager::currentNM()->mkNode(APPLY_UF, cond);\r
+}\r
+\r
+Node FullModelChecker::mkCondDefault( Node f) {\r
+  std::vector< Node > cond;\r
+  mkCondDefaultVec(f, cond);\r
+  return mkCond(cond);\r
+}\r
+\r
+void FullModelChecker::mkCondDefaultVec( Node f, std::vector< Node > & cond ) {\r
+  //get function symbol for f\r
+  cond.push_back(d_quant_cond[f]);\r
+  for (unsigned i=0; i<f[0].getNumChildren(); i++) {\r
+    cond.push_back(d_type_star[f[0][i].getType()]);\r
+  }\r
+}\r
+\r
+void FullModelChecker::mkCondVec( Node n, std::vector< Node > & cond ) {\r
+  cond.push_back(n.getOperator());\r
+  for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+    cond.push_back( n[i] );\r
+  }\r
+}\r
+\r
+Node FullModelChecker::evaluateInterpreted( Node n, std::vector< Node > & vals ) {\r
+  if( n.getKind()==EQUAL ){\r
+    return vals[0]==vals[1] ? d_true : d_false;\r
+  }else if( n.getKind()==ITE ){\r
+    if( vals[0]==d_true ){\r
+      return vals[1];\r
+    }else if( vals[0]==d_false ){\r
+      return vals[2];\r
+    }else{\r
+      return vals[1]==vals[2] ? vals[1] : Node::null();\r
+    }\r
+  }else if( n.getKind()==AND || n.getKind()==OR ){\r
+    bool isNull = false;\r
+    for (unsigned i=0; i<vals.size(); i++) {\r
+      if((vals[i]==d_true && n.getKind()==OR) || (vals[i]==d_false && n.getKind()==AND)) {\r
+        return vals[i];\r
+      }else if( vals[i].isNull() ){\r
+        isNull = true;\r
+      }\r
+    }\r
+    return isNull ? Node::null() : vals[0];\r
+  }else{\r
+    std::vector<Node> children;\r
+    if( n.getMetaKind() == kind::metakind::PARAMETERIZED ){\r
+      children.push_back( n.getOperator() );\r
+    }\r
+    for (unsigned i=0; i<vals.size(); i++) {\r
+      if( vals[i].isNull() ){\r
+        return Node::null();\r
+      }else{\r
+        children.push_back( vals[i] );\r
+      }\r
+    }\r
+    Node nc = NodeManager::currentNM()->mkNode(n.getKind(), children);\r
+    Trace("fmc-eval") << "Evaluate " << nc << " to ";\r
+    nc = Rewriter::rewrite(nc);\r
+    Trace("fmc-eval") << nc << std::endl;\r
+    return nc;\r
+  }\r
+}\r
+\r
+bool FullModelChecker::isActive() {\r
+  return options::fmfFullModelCheck();\r
+}\r
+\r
+bool FullModelChecker::useSimpleModels() {\r
+  return options::fmfFullModelCheckSimple();\r
+}\r
diff --git a/src/theory/quantifiers/full_model_check.h b/src/theory/quantifiers/full_model_check.h
new file mode 100755 (executable)
index 0000000..3f54b05
--- /dev/null
@@ -0,0 +1,150 @@
+/*********************                                                        */\r
+/*! \file full_model_check.h\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-2013  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 Full model check class\r
+ **/\r
+\r
+#ifndef FULL_MODEL_CHECK\r
+#define FULL_MODEL_CHECK\r
+\r
+#include "theory/quantifiers/model_builder.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+namespace fmcheck {\r
+\r
+\r
+class FullModelChecker;\r
+\r
+class EntryTrie\r
+{\r
+public:\r
+  EntryTrie() : d_data(-1){}\r
+  std::map<Node,EntryTrie> d_child;\r
+  int d_data;\r
+  void reset() { d_data = -1; d_child.clear(); }\r
+  void addEntry( FullModelChecker * m, Node c, Node v, int data, int index = 0 );\r
+  bool hasGeneralization( FullModelChecker * m, Node c, int index = 0 );\r
+  int getGeneralizationIndex( FullModelChecker * m, std::vector<Node> & inst, int index = 0 );\r
+  void getEntries( FullModelChecker * m, Node c, std::vector<int> & compat, std::vector<int> & gen, int index = 0, bool is_gen = true );\r
+  //if possible, get ground instance of c that evaluates to the entry\r
+  bool getWitness( FullModelChecker * m, FirstOrderModel * fm, Node c, std::vector<Node> & inst, int index = 0 );\r
+};\r
+\r
+\r
+class Def\r
+{\r
+public:\r
+  EntryTrie d_et;\r
+  //cond is APPLY_UF whose arguments are returned by FullModelChecker::getRepresentative\r
+  std::vector< Node > d_cond;\r
+  //value is returned by FullModelChecker::getRepresentative\r
+  std::vector< Node > d_value;\r
+private:\r
+  enum {\r
+    status_unk,\r
+    status_redundant,\r
+    status_non_redundant\r
+  };\r
+  std::vector< int > d_status;\r
+  bool d_has_simplified;\r
+public:\r
+  Def() : d_has_simplified(false){}\r
+  void reset() {\r
+    d_et.reset();\r
+    d_cond.clear();\r
+    d_value.clear();\r
+    d_status.clear();\r
+    d_has_simplified = false;\r
+  }\r
+  bool addEntry( FullModelChecker * m, Node c, Node v);\r
+  Node evaluate( FullModelChecker * m, std::vector<Node> inst );\r
+  int getGeneralizationIndex( FullModelChecker * m, std::vector<Node> inst );\r
+  void simplify( FullModelChecker * m );\r
+  void debugPrint(const char * tr, Node op, FullModelChecker * m);\r
+};\r
+\r
+\r
+class FullModelChecker\r
+{\r
+private:\r
+  Node d_true;\r
+  Node d_false;\r
+  QuantifiersEngine* d_qe;\r
+  std::map<TypeNode, std::map< Node, int > > d_rep_ids;\r
+  std::map<TypeNode, Node > d_model_basis_rep;\r
+  std::map<Node, Def * > d_models;\r
+  std::map<Node, Def > d_quant_models;\r
+  std::map<Node, bool > d_models_init;\r
+  std::map<Node, Node > d_quant_cond;\r
+  std::map<TypeNode, Node > d_type_star;\r
+  std::map<Node, std::map< Node, int > > d_quant_var_id;\r
+  std::map<Node, std::vector< int > > d_star_insts;\r
+  Node getRepresentative(FirstOrderModel * fm, Node n);\r
+  Node normalizeArgReps(FirstOrderModel * fm, Node op, Node n);\r
+  void addEntry( FirstOrderModel * fm, Node op, Node c, Node v,\r
+                 std::vector< Node > & conds,\r
+                 std::vector< Node > & values,\r
+                 std::vector< Node > & entry_conds );\r
+  int exhaustiveInstantiate(FirstOrderModel * fm, Node f, Node c, int c_index);\r
+private:\r
+  void doCheck(FirstOrderModel * fm, Node f, Def & d, Node n );\r
+\r
+  void doNegate( Def & dc );\r
+  void doVariableEquality( FirstOrderModel * fm, Node f, Def & d, Node eq );\r
+  void doVariableRelation( FirstOrderModel * fm, Node f, Def & d, Def & dc, Node v);\r
+  void doUninterpretedCompose( FirstOrderModel * fm, Node f, Def & d, Node n, std::vector< Def > & dc );\r
+\r
+  void doUninterpretedCompose( FirstOrderModel * fm, Node f, Node op, Def & d,\r
+                               std::vector< Def > & dc, int index,\r
+                               std::vector< Node > & cond, std::vector<Node> & val );\r
+  void doUninterpretedCompose2( FirstOrderModel * fm, Node f,\r
+                                std::map< int, Node > & entries, int index,\r
+                                std::vector< Node > & cond, std::vector< Node > & val,\r
+                                EntryTrie & curr);\r
+\r
+  void doInterpretedCompose( FirstOrderModel * fm, Node f, Def & d, Node n,\r
+                             std::vector< Def > & dc, int index,\r
+                             std::vector< Node > & cond, std::vector<Node> & val );\r
+  int isCompat( std::vector< Node > & cond, Node c );\r
+  bool doMeet( std::vector< Node > & cond, Node c );\r
+  Node mkCond( std::vector< Node > & cond );\r
+  Node mkCondDefault( Node f );\r
+  void mkCondDefaultVec( Node f, std::vector< Node > & cond );\r
+  void mkCondVec( Node n, std::vector< Node > & cond );\r
+  Node evaluateInterpreted( Node n, std::vector< Node > & vals );\r
+public:\r
+  FullModelChecker( QuantifiersEngine* qe );\r
+  ~FullModelChecker(){}\r
+\r
+  int getVariableId(Node f, Node n) { return d_quant_var_id[f][n]; }\r
+  bool isStar(Node n);\r
+  Node getStar(TypeNode tn) { return d_type_star[tn]; }\r
+  bool isModelBasisTerm(Node n);\r
+  Node getModelBasisTerm(TypeNode tn);\r
+  void reset(FirstOrderModel * fm);\r
+  Def * getModel(FirstOrderModel * fm, Node op);\r
+\r
+  void debugPrintCond(const char * tr, Node n, bool dispStar = false);\r
+  void debugPrint(const char * tr, Node n, bool dispStar = false);\r
+\r
+  int exhaustiveInstantiate(FirstOrderModel * fm, Node f, int effort);\r
+  bool hasStarExceptions( Node f ) { return !d_star_insts[f].empty(); }\r
+\r
+  bool isActive();\r
+  bool useSimpleModels();\r
+};\r
+\r
+}\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index f6a0dad1150aa894f4e11ad4214fb1703e4f28d5..d4988f22351ad6bd3a029b2f2f3a7a35058548e8 100644 (file)
@@ -134,18 +134,27 @@ Node InstMatch::getValue( Node var ) const{
   }
 }
 
+Node InstMatch::get( QuantifiersEngine* qe, Node f, int i ) {
+  return get( qe->getTermDatabase()->getInstantiationConstant( f, i ) );
+}
+
 void InstMatch::set(TNode var, TNode n){
   Assert( !var.isNull() );
-  if( !n.isNull() &&// For a strange use in inst_match.cpp InstMatchGeneratorSimple::addInstantiations
-       //var.getType() == n.getType()
-       !n.getType().isSubtypeOf( var.getType() ) ){
-    Trace("inst-match-warn") << var.getAttribute(InstConstantAttribute()) << std::endl;
-    Trace("inst-match-warn") << var << " " << var.getType() << " " << n << " " << n.getType() << std::endl ;
-    Assert(false);
+  if (Trace.isOn("inst-match-warn")) {
+    // For a strange use in inst_match.cpp InstMatchGeneratorSimple::addInstantiations
+    if( !n.isNull() && !n.getType().isSubtypeOf( var.getType() ) ){
+      Trace("inst-match-warn") << var.getAttribute(InstConstantAttribute()) << std::endl;
+      Trace("inst-match-warn") << var << " " << var.getType() << " " << n << " " << n.getType() << std::endl ;
+    }
   }
+  Assert( n.isNull() || n.getType().isSubtypeOf( var.getType() ) );
   d_map[var] = n;
 }
 
+void InstMatch::set( QuantifiersEngine* qe, Node f, int i, TNode n ) {
+  set( qe->getTermDatabase()->getInstantiationConstant( f, i ), n );
+}
+
 /** add match m for quantifier f starting at index, take into account equalities q, return true if successful */
 void InstMatchTrie::addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio ){
   if( long(index)<long(f[0].getNumChildren()) && ( !imtio || long(index)<long(imtio->d_order.size()) ) ){
index 127f83c608b07193832316908e038d47b9a00c36..72447fd662e0d44cd14ae4c00367d6cc41277fa5 100644 (file)
@@ -92,8 +92,11 @@ public:
   void erase(Node node){ d_map.erase(node); }
   /** get */
   Node get( TNode var ) { return d_map[var]; }
+  Node get( QuantifiersEngine* qe, Node f, int i );
   /** set */
   void set(TNode var, TNode n);
+  void set( QuantifiersEngine* qe, Node f, int i, TNode n );
+  /** size */
   size_t size(){ return d_map.size(); }
   /* iterator */
   std::map< Node, Node >::iterator begin(){ return d_map.begin(); };
index de7f2f373e99065898ff7b72b98ff20971c3adab..105575c4900f19215f60fb64cdc7f657b7a78a0f 100644 (file)
@@ -52,22 +52,28 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
       //we want to add the children of the NOT
       d_match_pattern = d_pattern[0];
     }
-    if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL ){
-      if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ){
+    if( d_match_pattern.getKind()==IFF || d_match_pattern.getKind()==EQUAL || d_match_pattern.getKind()==GEQ ){
+      if( !d_match_pattern[0].hasAttribute(InstConstantAttribute()) ||
+          d_match_pattern[0].getKind()==INST_CONSTANT ){
         Assert( d_match_pattern[1].hasAttribute(InstConstantAttribute()) );
+        Node mp = d_match_pattern[1];
         //swap sides
         Node pat = d_pattern;
-        d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
-        d_pattern = pat.getKind()==NOT ? d_pattern.notNode() : d_pattern;
-        if( pat.getKind()!=NOT ){   //TEMPORARY until we do better implementation of disequality matching
-          d_match_pattern = d_match_pattern[1];
+        if(d_match_pattern.getKind()==GEQ){
+          d_pattern = NodeManager::currentNM()->mkNode( kind::GT, d_match_pattern[1], d_match_pattern[0] );
+          d_pattern = d_pattern.negate();
         }else{
-          d_match_pattern = d_pattern[0][0];
+          d_pattern = NodeManager::currentNM()->mkNode( d_match_pattern.getKind(), d_match_pattern[1], d_match_pattern[0] );
         }
-      }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ){
+        d_pattern = pat.getKind()==NOT ? d_pattern.negate() : d_pattern;
+        d_match_pattern = mp;
+      }else if( !d_match_pattern[1].hasAttribute(InstConstantAttribute()) ||
+                d_match_pattern[1].getKind()==INST_CONSTANT ){
         Assert( d_match_pattern[0].hasAttribute(InstConstantAttribute()) );
         if( d_pattern.getKind()!=NOT ){   //TEMPORARY until we do better implementation of disequality matching
           d_match_pattern = d_match_pattern[0];
+        }else if( d_match_pattern[1].getKind()==INST_CONSTANT ){
+          d_match_pattern = d_match_pattern[0];
         }
       }
     }
@@ -96,17 +102,23 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
         //candidates will be all disequalities
         d_cg = new inst::CandidateGeneratorQELitDeq( qe, d_match_pattern );
       }
-    }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF || d_pattern.getKind()==NOT ){
+    }else if( d_pattern.getKind()==EQUAL || d_pattern.getKind()==IFF ||
+              d_pattern.getKind()==GEQ || d_pattern.getKind()==GT || d_pattern.getKind()==NOT ){
       Assert( d_matchPolicy==MATCH_GEN_DEFAULT );
       if( d_pattern.getKind()==NOT ){
-        Unimplemented("Disequal generator unimplemented");
+        if (d_pattern[0][1].getKind()!=INST_CONSTANT) {
+          Unimplemented("Disequal generator unimplemented");
+        }else{
+          d_eq_class = d_pattern[0][1];
+        }
       }else{
-        Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
-        //we are matching only in a particular equivalence class
-        d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
         //store the equivalence class that we will call d_cg->reset( ... ) on
         d_eq_class = d_pattern[1];
       }
+      Assert( Trigger::isAtomicTrigger( d_match_pattern ) );
+      //we are matching only in a particular equivalence class
+      d_cg = new inst::CandidateGeneratorQE( qe, d_match_pattern.getOperator() );
+
     }else if( Trigger::isAtomicTrigger( d_match_pattern ) ){
       //if( d_matchPolicy==MATCH_GEN_EFFICIENT_E_MATCH ){
         //Warning() << "Currently efficient e matching is not taken into account for quantifiers: " << d_pattern << std::endl;
@@ -134,7 +146,7 @@ void InstMatchGenerator::initialize( QuantifiersEngine* qe, std::vector< InstMat
 /** get match (not modulo equality) */
 bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngine* qe ){
   Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
-                    << m << ")" << ", " << d_children.size() << std::endl;
+                    << m << ")" << ", " << d_children.size() << ", pattern is " << d_pattern << std::endl;
   Assert( !d_match_pattern.isNull() );
   if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
     return true;
@@ -182,6 +194,36 @@ bool InstMatchGenerator::getMatch( Node f, Node t, InstMatch& m, QuantifiersEngi
         }
       }
     }
+    //for relational matching
+    if( !d_eq_class.isNull() && d_eq_class.getKind()==INST_CONSTANT ){
+      //also must fit match to equivalence class
+      bool pol = d_pattern.getKind()!=NOT;
+      Node pat = d_pattern.getKind()==NOT ? d_pattern[0] : d_pattern;
+      Node t_match;
+      if( pol ){
+        if (pat.getKind()==GT) {
+          Node r = NodeManager::currentNM()->mkConst( Rational(-1) );
+          t_match = NodeManager::currentNM()->mkNode(PLUS, t, r);
+        }else{
+          t_match = t;
+        }
+      }else{
+        if(pat.getKind()==EQUAL) {
+          Node r = NodeManager::currentNM()->mkConst( Rational(1) );
+          t_match = NodeManager::currentNM()->mkNode(PLUS, t, r);
+        }else if( pat.getKind()==IFF ){
+          t_match = NodeManager::currentNM()->mkConst( !q->areEqual( NodeManager::currentNM()->mkConst(true), t ) );
+        }else if( pat.getKind()==GEQ ){
+          Node r = NodeManager::currentNM()->mkConst( Rational(1) );
+          t_match = NodeManager::currentNM()->mkNode(PLUS, t, r);
+        }else if( pat.getKind()==GT ){
+          t_match = t;
+        }
+      }
+      if( !t_match.isNull() && !m.setMatch( q, d_eq_class, t_match ) ){
+        success = false;
+      }
+    }
     if( success ){
       //now, fit children into match
       //we will be requesting candidates for matching terms for each child
@@ -286,7 +328,7 @@ void InstMatchGenerator::reset( Node eqc, QuantifiersEngine* qe ){
   //we have a specific equivalence class in mind
   //we are producing matches for f(E) ~ t, where E is a non-ground vector of terms, and t is a ground term
   //just look in equivalence class of the RHS
-  d_cg->reset( d_eq_class );
+  d_cg->reset( d_eq_class.getKind()==INST_CONSTANT ? Node::null() : d_eq_class );
 }
 
 bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine* qe ){
@@ -306,7 +348,7 @@ bool InstMatchGenerator::getNextMatch( Node f, InstMatch& m, QuantifiersEngine*
   if( !success ){
     //Debug("matching") << this << " failed, reset " << d_eq_class << std::endl;
     //we failed, must reset
-    reset( d_eq_class, qe );
+    reset( d_eq_class.getKind()==INST_CONSTANT ? Node::null() : d_eq_class, qe );
   }
   return success;
 }
index 0e1266e0d752575720375703ce263be73d2073ad..ef81d55a1be0163084da79fe7858cc89e229a644 100644 (file)
@@ -144,7 +144,11 @@ int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e )
     }
     if( gen ){
       generateTriggers( f, effort, e, status );
+      if( d_auto_gen_trigger[f].empty() && f.getNumChildren()==2 ){
+        Trace("no-trigger") << "Could not find trigger for " << f << std::endl;
+      }
     }
+
     //if( e==4 ){
     //  d_processed_trigger.clear();
     //  d_quantEngine->getEqualityQuery()->setLiberal( true );
index 0b74cfc5e56df5a161f410741f4d5ab33f3052aa..059c76b21cc7c101cf001c7d7f2ab0371e1fc4de 100644 (file)
@@ -192,6 +192,7 @@ void ModelEngineBuilder::processBuildModel( TheoryModel* m, bool fullModel ) {
           Trace("model-engine-debug") << "Building model..." << std::endl;
           //build model for UF
           for( std::map< Node, uf::UfModelTree >::iterator it = fm->d_uf_model_tree.begin(); it != fm->d_uf_model_tree.end(); ++it ){
+            Trace("model-engine-debug-uf") << "Building model for " << it->first << "..." << std::endl;
             constructModelUf( fm, it->first );
           }
           /*
@@ -273,7 +274,7 @@ void ModelEngineBuilder::analyzeModel( FirstOrderModel* fm ){
         }
       }
       //for calculating terms that we don't need to consider
-      if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){
+      if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())!=0 ){
         if( !n.getAttribute(BasisNoMatchAttribute()) ){
           //need to consider if it is not congruent modulo model basis
           if( !tabt.addTerm( fm, n ) ){
@@ -352,7 +353,7 @@ bool ModelEngineBuilder::isQuantifierActive( Node f ){
 
 bool ModelEngineBuilder::isTermActive( Node n ){
   return !n.getAttribute(NoMatchAttribute()) || //it is not congruent to another active term
-         ( n.getAttribute(ModelBasisArgAttribute())==1 && !n.getAttribute(BasisNoMatchAttribute()) ); //or it has model basis arguments
+         ( n.getAttribute(ModelBasisArgAttribute())!=0 && !n.getAttribute(BasisNoMatchAttribute()) ); //or it has model basis arguments
                                                                                                       //and is not congruent modulo model basis
                                                                                                       //to another active term
 }
@@ -597,7 +598,7 @@ void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op )
         fm->d_uf_model_gen[op].setValue( fm, n, v );
         if( fm->d_uf_model_gen[op].optUsePartialDefaults() ){
           //also set as default value if necessary
-          if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 ){
+          if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())!=0 ){
             Trace("fmf-model-cons") << "  Set as default." << std::endl;
             fm->d_uf_model_gen[op].setValue( fm, n, v, false );
             if( n==defaultTerm ){
@@ -619,6 +620,13 @@ void ModelEngineBuilderDefault::constructModelUf( FirstOrderModel* fm, Node op )
       Trace("fmf-model-cons") << "  Choose default value..." << std::endl;
       //chose defaultVal based on heuristic, currently the best ratio of "pro" responses
       Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
+      if( defaultVal.isNull() ){
+        if (!fm->d_rep_set.hasType(defaultTerm.getType())) {
+          Node mbt = d_qe->getTermDatabase()->getModelBasisTerm(defaultTerm.getType());
+          fm->d_rep_set.d_type_reps[defaultTerm.getType()].push_back(mbt);
+        }
+        defaultVal = fm->d_rep_set.d_type_reps[defaultTerm.getType()][0];
+      }
       Assert( !defaultVal.isNull() );
       Trace("fmf-model-cons") << "Set default term : " << fm->d_rep_set.getIndexFor( defaultVal ) << std::endl;
       fm->d_uf_model_gen[op].setValue( fm, defaultTerm, defaultVal, false );
@@ -935,7 +943,7 @@ void ModelEngineBuilderInstGen::setSelectedTerms( Node s ){
   if( s.getKind()==APPLY_UF ){
     Assert( s.hasAttribute(ModelBasisArgAttribute()) );
     if( !s.hasAttribute(ModelBasisArgAttribute()) ) std::cout << "no mba!! " << s << std::endl;
-    if( s.getAttribute(ModelBasisArgAttribute())==1 ){
+    if( s.getAttribute(ModelBasisArgAttribute())!=0 ){
       d_term_selected[ s ] = true;
       Trace("sel-form-term") << "  " << s << " is a selected term." << std::endl;
     }
index a69b278c05a41965d03641e1dc63b33171cbd4fc..90b8c62bace8f8ab7164feeb2d657fec8ec9d207 100644 (file)
@@ -36,7 +36,8 @@ using namespace CVC4::theory::inst;
 //Model Engine constructor
 ModelEngine::ModelEngine( context::Context* c, QuantifiersEngine* qe ) :
 QuantifiersModule( qe ),
-d_rel_domain( qe, qe->getModel() ){
+d_rel_domain( qe, qe->getModel() ),
+d_fmc( qe ){
 
   if( options::fmfNewInstGen() ){
     d_builder = new ModelEngineBuilderInstGen( c, qe );
@@ -75,6 +76,11 @@ void ModelEngine::check( Theory::Effort e ){
           //let the strong solver verify that the model is minimal
           //for debugging, this will if there are terms in the model that the strong solver was not notified of
           ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->theoryOf( THEORY_UF ))->getStrongSolver()->debugModel( fm );
+          //for full model checking
+          if( d_fmc.isActive() ){
+            Trace("model-engine-debug") << "Reset full model checker..." << std::endl;
+            d_fmc.reset( fm );
+          }
           Trace("model-engine-debug") << "Check model..." << std::endl;
           d_incomplete_check = false;
           //print debug
@@ -161,15 +167,23 @@ int ModelEngine::checkModel( int checkOption ){
       if( it->first.isSort() ){
         Trace("model-engine") << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;
         Trace("model-engine-debug") << "   ";
+        Node mbt = d_quantEngine->getTermDatabase()->getModelBasisTerm(it->first);
         for( size_t i=0; i<it->second.size(); i++ ){
           //Trace("model-engine-debug") << it->second[i] << "  ";
           Node r = ((EqualityQueryQuantifiersEngine*)d_quantEngine->getEqualityQuery())->getRepresentative( it->second[i] );
           Trace("model-engine-debug") << r << " ";
         }
         Trace("model-engine-debug") << std::endl;
+        Trace("model-engine-debug") << "  Model basis term : " << mbt << std::endl;
       }
     }
   }
+  //full model checking: construct models for all functions
+  if( d_fmc.isActive() ){
+    for (std::map< Node, uf::UfModelTreeGenerator >::iterator it = fm->d_uf_model_gen.begin(); it != fm->d_uf_model_gen.end(); ++it) {
+      d_fmc.getModel(fm, it->first);
+    }
+  }
   //compute the relevant domain if necessary
   if( optUseRelevantDomain() ){
     d_rel_domain.compute();
@@ -179,36 +193,41 @@ int ModelEngine::checkModel( int checkOption ){
   d_relevantLemmas = 0;
   d_totalLemmas = 0;
   Trace("model-engine-debug") << "Do exhaustive instantiation..." << std::endl;
-  for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
-    Node f = fm->getAssertedQuantifier( i );
-    //keep track of total instantiations for statistics
-    int totalInst = 1;
-    for( size_t i=0; i<f[0].getNumChildren(); i++ ){
-      TypeNode tn = f[0][i].getType();
-      if( fm->d_rep_set.hasType( tn ) ){
-        totalInst = totalInst * (int)fm->d_rep_set.d_type_reps[ tn ].size();
-      }
-    }
-    d_totalLemmas += totalInst;
-    //determine if we should check this quantifiers
-    bool checkQuant = false;
-    if( checkOption==check_model_full ){
-      checkQuant = d_builder->isQuantifierActive( f );
-    }else if( checkOption==check_model_no_inst_gen ){
-      checkQuant = !d_builder->hasInstGen( f );
-    }
-    //if we need to consider this quantifier on this iteration
-    if( checkQuant ){
-      addedLemmas += exhaustiveInstantiate( f, optUseRelevantDomain() );
-      if( Trace.isOn("model-engine-warn") ){
-        if( addedLemmas>10000 ){
-          Debug("fmf-exit") << std::endl;
-          debugPrint("fmf-exit");
-          exit( 0 );
+  int e_max = d_fmc.isActive() ? 2 : 1;
+  for( int e=0; e<e_max; e++) {
+    if (addedLemmas==0) {
+      for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+        Node f = fm->getAssertedQuantifier( i );
+        //keep track of total instantiations for statistics
+        int totalInst = 1;
+        for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+          TypeNode tn = f[0][i].getType();
+          if( fm->d_rep_set.hasType( tn ) ){
+            totalInst = totalInst * (int)fm->d_rep_set.d_type_reps[ tn ].size();
+          }
+        }
+        d_totalLemmas += totalInst;
+        //determine if we should check this quantifiers
+        bool checkQuant = false;
+        if( checkOption==check_model_full ){
+          checkQuant = d_builder->isQuantifierActive( f );
+        }else if( checkOption==check_model_no_inst_gen ){
+          checkQuant = !d_builder->hasInstGen( f );
+        }
+        //if we need to consider this quantifier on this iteration
+        if( checkQuant ){
+          addedLemmas += exhaustiveInstantiate( f, optUseRelevantDomain(), e );
+          if( Trace.isOn("model-engine-warn") ){
+            if( addedLemmas>10000 ){
+              Debug("fmf-exit") << std::endl;
+              debugPrint("fmf-exit");
+              exit( 0 );
+            }
+          }
+          if( optOneQuantPerRound() && addedLemmas>0 ){
+            break;
+          }
         }
-      }
-      if( optOneQuantPerRound() && addedLemmas>0 ){
-        break;
       }
     }
   }
@@ -222,100 +241,115 @@ int ModelEngine::checkModel( int checkOption ){
   return addedLemmas;
 }
 
-int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
+int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain, int effort ){
   int addedLemmas = 0;
-  Trace("inst-fmf-ei") << "Exhaustive instantiate " << f << "..." << std::endl;
-  Debug("inst-fmf-ei") << "   Instantiation Constants: ";
-  for( size_t i=0; i<f[0].getNumChildren(); i++ ){
-    Debug("inst-fmf-ei") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
-  }
-  Debug("inst-fmf-ei") << std::endl;
 
-  //create a rep set iterator and iterate over the (relevant) domain of the quantifier
-  RepSetIterator riter( &(d_quantEngine->getModel()->d_rep_set) );
-  if( riter.setQuantifier( f ) ){
-    //set the domain for the iterator (the sufficient set of instantiations to try)
-    if( useRelInstDomain ){
-      riter.setDomain( d_rel_domain.d_quant_inst_domain[f] );
+  bool useModel = d_builder->optUseModel();
+  if (d_fmc.isActive() && effort==0) {
+    addedLemmas = d_fmc.exhaustiveInstantiate(d_quantEngine->getModel(), f, effort);
+  }else if( !d_fmc.isActive() || (effort==1 && d_fmc.hasStarExceptions(f)) ) {
+    if(d_fmc.isActive()){
+      useModel = false;
+      int lem = d_fmc.exhaustiveInstantiate(d_quantEngine->getModel(), f, effort);
+      if( lem!=-1 ){
+        return lem;
+      }
     }
-    d_quantEngine->getModel()->resetEvaluate();
-    int tests = 0;
-    int triedLemmas = 0;
-    while( !riter.isFinished() && ( addedLemmas==0 || !optOneInstPerQuantRound() ) ){
-      d_testLemmas++;
-      int eval = 0;
-      int depIndex;
-      if( d_builder->optUseModel() ){
-        //see if instantiation is already true in current model
-        Debug("fmf-model-eval") << "Evaluating ";
-        riter.debugPrintSmall("fmf-model-eval");
-        Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
-        tests++;
-        //if evaluate(...)==1, then the instantiation is already true in the model
-        //  depIndex is the index of the least significant variable that this evaluation relies upon
-        depIndex = riter.getNumTerms()-1;
-        eval = d_quantEngine->getModel()->evaluate( d_quantEngine->getTermDatabase()->getInstConstantBody( f ), depIndex, &riter );
-        if( eval==1 ){
-          Debug("fmf-model-eval") << "  Returned success with depIndex = " << depIndex << std::endl;
-        }else{
-          Debug("fmf-model-eval") << "  Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
-        }
+    Trace("inst-fmf-ei") << "Exhaustive instantiate " << f << ", effort = " << effort << "..." << std::endl;
+    Debug("inst-fmf-ei") << "   Instantiation Constants: ";
+    for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+      Debug("inst-fmf-ei") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
+    }
+    Debug("inst-fmf-ei") << std::endl;
+    //create a rep set iterator and iterate over the (relevant) domain of the quantifier
+    RepSetIterator riter( &(d_quantEngine->getModel()->d_rep_set) );
+    if( riter.setQuantifier( f ) ){
+      Debug("inst-fmf-ei") << "Set domain..." << std::endl;
+      //set the domain for the iterator (the sufficient set of instantiations to try)
+      if( useRelInstDomain ){
+        riter.setDomain( d_rel_domain.d_quant_inst_domain[f] );
       }
-      if( eval==1 ){
-        //instantiation is already true -> skip
-        riter.increment2( depIndex );
-      }else{
-        //instantiation was not shown to be true, construct the match
-        InstMatch m;
-        for( int i=0; i<riter.getNumTerms(); i++ ){
-          m.set( d_quantEngine->getTermDatabase()->getInstantiationConstant( f, riter.d_index_order[i] ), riter.getTerm( i ) );
+      Debug("inst-fmf-ei") << "Reset evaluate..." << std::endl;
+      d_quantEngine->getModel()->resetEvaluate();
+      Debug("inst-fmf-ei") << "Begin instantiation..." << std::endl;
+      int tests = 0;
+      int triedLemmas = 0;
+      while( !riter.isFinished() && ( addedLemmas==0 || !optOneInstPerQuantRound() ) ){
+        d_testLemmas++;
+        int eval = 0;
+        int depIndex;
+        if( useModel ){
+          //see if instantiation is already true in current model
+          Debug("fmf-model-eval") << "Evaluating ";
+          riter.debugPrintSmall("fmf-model-eval");
+          Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
+          tests++;
+          //if evaluate(...)==1, then the instantiation is already true in the model
+          //  depIndex is the index of the least significant variable that this evaluation relies upon
+          depIndex = riter.getNumTerms()-1;
+          eval = d_quantEngine->getModel()->evaluate( d_quantEngine->getTermDatabase()->getInstConstantBody( f ), depIndex, &riter );
+          if( eval==1 ){
+            Debug("fmf-model-eval") << "  Returned success with depIndex = " << depIndex << std::endl;
+          }else{
+            Debug("fmf-model-eval") << "  Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
+          }
         }
-        Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
-        triedLemmas++;
-        d_triedLemmas++;
-        //add as instantiation
-        if( d_quantEngine->addInstantiation( f, m ) ){
-          addedLemmas++;
-          //if the instantiation is show to be false, and we wish to skip multiple instantiations at once
-          if( eval==-1 && optExhInstEvalSkipMultiple() ){
-            riter.increment2( depIndex );
+        if( eval==1 ){
+          //instantiation is already true -> skip
+          riter.increment2( depIndex );
+        }else{
+          //instantiation was not shown to be true, construct the match
+          InstMatch m;
+          for( int i=0; i<riter.getNumTerms(); i++ ){
+            m.set( d_quantEngine, f, riter.d_index_order[i], riter.getTerm( i ) );
+          }
+          Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
+          triedLemmas++;
+          d_triedLemmas++;
+          //add as instantiation
+          if( d_quantEngine->addInstantiation( f, m ) ){
+            addedLemmas++;
+            //if the instantiation is show to be false, and we wish to skip multiple instantiations at once
+            if( eval==-1 && optExhInstEvalSkipMultiple() ){
+              riter.increment2( depIndex );
+            }else{
+              riter.increment();
+            }
           }else{
+            Debug("fmf-model-eval") << "* Failed Add instantiation " << m << std::endl;
             riter.increment();
           }
-        }else{
-          Debug("fmf-model-eval") << "* Failed Add instantiation " << m << std::endl;
-          riter.increment();
         }
       }
+      //print debugging information
+      d_statistics.d_eval_formulas += d_quantEngine->getModel()->d_eval_formulas;
+      d_statistics.d_eval_uf_terms += d_quantEngine->getModel()->d_eval_uf_terms;
+      d_statistics.d_eval_lits += d_quantEngine->getModel()->d_eval_lits;
+      d_statistics.d_eval_lits_unknown += d_quantEngine->getModel()->d_eval_lits_unknown;
+      int relevantInst = 1;
+      for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+        relevantInst = relevantInst * (int)riter.d_domain[i].size();
+      }
+      d_relevantLemmas += relevantInst;
+      Trace("inst-fmf-ei") << "Finished: " << std::endl;
+      //Debug("inst-fmf-ei") << "   Inst Total: " << totalInst << std::endl;
+      Trace("inst-fmf-ei") << "   Inst Relevant: " << relevantInst << std::endl;
+      Trace("inst-fmf-ei") << "   Inst Tried: " << triedLemmas << std::endl;
+      Trace("inst-fmf-ei") << "   Inst Added: " << addedLemmas << std::endl;
+      Trace("inst-fmf-ei") << "   # Tests: " << tests << std::endl;
+      if( addedLemmas>1000 ){
+        Trace("model-engine-warn") << "WARNING: many instantiations produced for " << f << ": " << std::endl;
+        //Trace("model-engine-warn") << "   Inst Total: " << totalInst << std::endl;
+        Trace("model-engine-warn") << "   Inst Relevant: " << relevantInst << std::endl;
+        Trace("model-engine-warn") << "   Inst Tried: " << triedLemmas << std::endl;
+        Trace("model-engine-warn") << "   Inst Added: " << addedLemmas << std::endl;
+        Trace("model-engine-warn") << "   # Tests: " << tests << std::endl;
+        Trace("model-engine-warn") << std::endl;
+      }
     }
-    //print debugging information
-    d_statistics.d_eval_formulas += d_quantEngine->getModel()->d_eval_formulas;
-    d_statistics.d_eval_uf_terms += d_quantEngine->getModel()->d_eval_uf_terms;
-    d_statistics.d_eval_lits += d_quantEngine->getModel()->d_eval_lits;
-    d_statistics.d_eval_lits_unknown += d_quantEngine->getModel()->d_eval_lits_unknown;
-    int relevantInst = 1;
-    for( size_t i=0; i<f[0].getNumChildren(); i++ ){
-      relevantInst = relevantInst * (int)riter.d_domain[i].size();
-    }
-    d_relevantLemmas += relevantInst;
-    Trace("inst-fmf-ei") << "Finished: " << std::endl;
-    //Debug("inst-fmf-ei") << "   Inst Total: " << totalInst << std::endl;
-    Trace("inst-fmf-ei") << "   Inst Relevant: " << relevantInst << std::endl;
-    Trace("inst-fmf-ei") << "   Inst Tried: " << triedLemmas << std::endl;
-    Trace("inst-fmf-ei") << "   Inst Added: " << addedLemmas << std::endl;
-    Trace("inst-fmf-ei") << "   # Tests: " << tests << std::endl;
-    if( addedLemmas>1000 ){
-      Trace("model-engine-warn") << "WARNING: many instantiations produced for " << f << ": " << std::endl;
-      //Trace("model-engine-warn") << "   Inst Total: " << totalInst << std::endl;
-      Trace("model-engine-warn") << "   Inst Relevant: " << relevantInst << std::endl;
-      Trace("model-engine-warn") << "   Inst Tried: " << triedLemmas << std::endl;
-      Trace("model-engine-warn") << "   Inst Added: " << addedLemmas << std::endl;
-      Trace("model-engine-warn") << "   # Tests: " << tests << std::endl;
-      Trace("model-engine-warn") << std::endl;
-    }
+     //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
+    d_incomplete_check = d_incomplete_check || riter.d_incomplete;
   }
-   //if the iterator is incomplete, we will return unknown instead of sat if no instantiations are added this round
-  d_incomplete_check = d_incomplete_check || riter.d_incomplete;
   return addedLemmas;
 }
 
index 38686416400faa465ce8d7703a4b1a1df86338e8..d2cd8807aa8daadd4886d81c5f1b50542449bae8 100644 (file)
@@ -21,6 +21,7 @@
 #include "theory/quantifiers/model_builder.h"
 #include "theory/model.h"
 #include "theory/quantifiers/relevant_domain.h"
+#include "theory/quantifiers/full_model_check.h"
 
 namespace CVC4 {
 namespace theory {
@@ -35,6 +36,8 @@ private:
 private:    //analysis of current model:
   //relevant domain
   RelevantDomain d_rel_domain;
+  //full model checker
+  fmcheck::FullModelChecker d_fmc;
   //is the exhaustive instantiation incomplete?
   bool d_incomplete_check;
 private:
@@ -51,7 +54,7 @@ private:
   //check model
   int checkModel( int checkOption );
   //exhaustively instantiate quantifier (possibly using mbqi), return number of lemmas produced
-  int exhaustiveInstantiate( Node f, bool useRelInstDomain = false );
+  int exhaustiveInstantiate( Node f, bool useRelInstDomain = false, int effort = 0 );
 private:
   //temporary statistics
   int d_triedLemmas;
@@ -63,6 +66,7 @@ public:
   ~ModelEngine(){}
   //get the builder
   ModelEngineBuilder* getModelBuilder() { return d_builder; }
+  fmcheck::FullModelChecker* getFullModelChecker() { return &d_fmc; }
 public:
   void check( Theory::Effort e );
   void registerQuantifier( Node f );
index 60f5a171d25b1787c94c08c68cb5d4566dcccbbb..a9b7f269f9f0d24176337852109cb1df29b3248d 100644 (file)
@@ -54,6 +54,8 @@ option smartTriggers /--disable-smart-triggers bool :default true
 # Whether to use relevent triggers
 option relevantTriggers /--disable-relevant-triggers bool :default true
  prefer triggers that are more relevant based on SInE style analysis
+option relationalTriggers --relational-triggers bool :default false
+ choose relational triggers such as x = f(y), x >= f(y)
 
 # Whether to consider terms in the bodies of quantifiers for matching
 option registerQuantBodyTerms --register-quant-body-terms bool :default false
@@ -88,6 +90,11 @@ option finiteModelFind --finite-model-find bool :default false
 option fmfModelBasedInst /--disable-fmf-mbqi bool :default true
  disable model-based quantifier instantiation for finite model finding
 
+option fmfFullModelCheck --fmf-fmc bool :default false
+ enable full model check for finite model finding
+option fmfFullModelCheckSimple /--disable-fmf-fmc-simple bool :default true
+ disable simple models in full model check for finite model finding
+
 option fmfOneInstPerRound --fmf-one-inst-per-round bool :default false
  only add one instantiation per quantifier per round for fmf
 option fmfOneQuantPerRound --fmf-one-quant-per-round bool :default false
@@ -98,8 +105,8 @@ option fmfRelevantDomain --fmf-relevant-domain bool :default false
  use relevant domain computation, similar to complete instantiation (Ge, deMoura 09)
 option fmfNewInstGen --fmf-new-inst-gen bool :default false
  use new inst gen technique for answering sat without exhaustive instantiation
-option fmfInstGen /--disable-fmf-inst-gen bool :default true
- disable Inst-Gen instantiation techniques for finite model finding
+option fmfInstGen --fmf-inst-gen/--disable-fmf-inst-gen bool :read-write :default true
enable/disable Inst-Gen instantiation techniques for finite model finding
 option fmfInstGenOneQuantPerRound --fmf-inst-gen-one-quant-per-round bool :default false
  only perform Inst-Gen instantiation techniques on one quantifier per round
 option fmfFreshDistConst --fmf-fresh-dc bool :default false
index 36db56d0d0e0069d886979300901d8c36b7adfb4..6b07a87e0075a1b3c0cee438cb387b0b787011e6 100644 (file)
@@ -22,6 +22,96 @@ using namespace CVC4::kind;
 using namespace CVC4::context;
 using namespace CVC4::theory;
 
+
+bool QuantArith::getMonomial( Node n, std::map< Node, Node >& msum ) {
+  if ( n.getKind()==MULT ){
+    if( n.getNumChildren()==2 && msum.find(n[1])==msum.end() && n[0].isConst() ){
+      msum[n[1]] = n[0];
+      return true;
+    }
+  }else{
+    if( msum.find(n)==msum.end() ){
+      msum[n] = Node::null();
+      return true;
+    }
+  }
+  return false;
+}
+
+bool QuantArith::getMonomialSum( Node n, std::map< Node, Node >& msum ) {
+  if ( n.getKind()==PLUS ){
+    for( unsigned i=0; i<n.getNumChildren(); i++) {
+      if (!getMonomial( n[i], msum )){
+        return false;
+      }
+    }
+    return true;
+  }else{
+    return getMonomial( n, msum );
+  }
+}
+
+bool QuantArith::getMonomialSumLit( Node lit, std::map< Node, Node >& msum ) {
+  if( lit.getKind()==GEQ || lit.getKind()==EQUAL ){
+    if( getMonomialSum( lit[0], msum ) ){
+      if( lit[1].isConst() ){
+        if( !lit[1].getConst<Rational>().isZero() ){
+          msum[Node::null()] = negate( lit[1] );
+        }
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool QuantArith::isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k ) {
+  if( msum.find(v)!=msum.end() ){
+    std::vector< Node > children;
+    Rational r = msum[v].isNull() ? Rational(1) : msum[v].getConst<Rational>();
+    if ( r.sgn()!=0 ){
+      for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){
+        if( it->first!=v ){
+          Node m;
+          if( !it->first.isNull() ){
+            if ( !it->second.isNull() ){
+              m = NodeManager::currentNM()->mkNode( MULT, it->second, it->first );
+            }else{
+              m = it->first;
+            }
+          }else{
+            m = it->second;
+          }
+          children.push_back(m);
+        }
+      }
+      veq = children.size()>1 ? NodeManager::currentNM()->mkNode( PLUS, children ) :
+                                (children.size()==1 ? children[0] : NodeManager::currentNM()->mkConst( Rational(0) ));
+      if( !r.isNegativeOne() ){
+        if( r.isOne() ){
+          veq = negate(veq);
+        }else{
+          //TODO
+          return false;
+        }
+      }
+      veq = Rewriter::rewrite( veq );
+      veq = NodeManager::currentNM()->mkNode( k, r.sgn()==1 ? v : veq, r.sgn()==1 ? veq : v );
+      return true;
+    }
+    return false;
+  }else{
+    return false;
+  }
+}
+
+Node QuantArith::negate( Node t ) {
+  Node tt = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) ), t );
+  tt = Rewriter::rewrite( tt );
+  return tt;
+}
+
+
 void QuantRelevance::registerQuantifier( Node f ){
   //compute symbols in f
   std::vector< Node > syms;
index 6a5726cc777ae3e1881e1e9c806c3825170747ad..d248a8999aa6e0389ad21cc1c1de62af205e0052 100644 (file)
@@ -28,6 +28,17 @@ namespace CVC4 {
 namespace theory {
 
 
+class QuantArith
+{
+public:
+  static bool getMonomial( Node n, std::map< Node, Node >& msum );
+  static bool getMonomialSum( Node n, std::map< Node, Node >& msum );
+  static bool getMonomialSumLit( Node lit, std::map< Node, Node >& msum );
+  static bool isolate( Node v, std::map< Node, Node >& msum, Node & veq, Kind k );
+  static Node negate( Node t );
+};
+
+
 class QuantRelevance
 {
 private:
index 3153a3c640096106c81913bba0f5cb498bc0c8a2..417b4ae3a9fdd67b6251e049fc68041eb263552d 100644 (file)
@@ -254,8 +254,7 @@ void TermDb::computeModelBasisArgAttribute( Node n ){
     //determine if it has model basis attribute
     for( int j=0; j<(int)n.getNumChildren(); j++ ){
       if( n[j].getAttribute(ModelBasisAttribute()) ){
-        val = 1;
-        break;
+        val++;
       }
     }
     ModelBasisArgAttribute mbaa;
index 231d0ee9eec2c02e44833982f4282680b00bf61b..e5154476af2b61af600a0c22020c58e11f51c87c 100644 (file)
@@ -83,10 +83,15 @@ public:
 };/* class TermArgTrie */
 
 
+namespace fmcheck {
+  class FullModelChecker;
+}
+
 class TermDb {
   friend class ::CVC4::theory::QuantifiersEngine;
   friend class ::CVC4::theory::inst::Trigger;
   friend class ::CVC4::theory::rrinst::Trigger;
+  friend class ::CVC4::theory::quantifiers::fmcheck::FullModelChecker;
 private:
   /** reference to the quantifiers engine */
   QuantifiersEngine* d_quantEngine;
index cab94fb5c5628947bee9f80acde0e3b68231a06d..1f1667522658be0bdacc05c09ba21800b64deaba 100644 (file)
@@ -28,8 +28,6 @@ using namespace CVC4::context;
 using namespace CVC4::theory;
 using namespace CVC4::theory::inst;
 
-//#define NESTED_PATTERN_SELECTION
-
 /** trigger class constructor */
 Trigger::Trigger( QuantifiersEngine* qe, Node f, std::vector< Node >& nodes, int matchOption, bool smartTriggers ) :
 d_quantEngine( qe ), d_f( f ){
@@ -249,11 +247,75 @@ bool Trigger::isUsable( Node n, Node f ){
   }
 }
 
-bool Trigger::isUsableTrigger( Node n, Node f ){
-  //return n.getAttribute(InstConstantAttribute())==f && n.getKind()==APPLY_UF;
+bool nodeContainsVar( Node n, Node v ){
+  if( n==v) {
+    return true;
+  }else{
+    for( unsigned i=0; i<n.getNumChildren(); i++) {
+      if( nodeContainsVar(n[i], v) ){
+        return true;
+      }
+    }
+    return false;
+  }
+}
+
+Node Trigger::getIsUsableTrigger( Node n, Node f, bool pol, bool hasPol ) {
+  if( options::relationalTriggers() ){
+    if( n.getKind()==EQUAL || n.getKind()==IFF || n.getKind()==GEQ ){
+      Node rtr;
+      for( unsigned i=0; i<2; i++) {
+        unsigned j = (i==0) ? 1 : 0;
+        if( n[j].getKind()==INST_CONSTANT && isUsableTrigger(n[i], f) && !nodeContainsVar( n[i], n[j] ) ) {
+          rtr = n;
+          break;
+        }
+      }
+      if( n[0].getType().isInteger() ){
+        //try to rearrange?
+        std::map< Node, Node > m;
+        if (QuantArith::getMonomialSumLit(n, m) ){
+          for( std::map< Node, Node >::iterator it = m.begin(); it!=m.end(); ++it ){
+            if( !it->first.isNull() && it->first.getKind()==INST_CONSTANT ){
+              Node veq;
+              if( QuantArith::isolate( it->first, m, veq, n.getKind() ) ){
+                int vti = veq[0]==it->first ? 1 : 0;
+                if( isUsableTrigger(veq[vti], f) && !nodeContainsVar( veq[vti], veq[vti==0 ? 1 : 0]) ){
+                  rtr = veq;
+                  InstConstantAttribute ica;
+                  rtr.setAttribute(ica,veq[vti].getAttribute(InstConstantAttribute()) );
+                }
+              }
+            }
+          }
+        }
+      }
+      if( !rtr.isNull() ){
+        Trace("relational-trigger") << "Relational trigger : " << std::endl;
+        Trace("relational-trigger") << "    " << rtr << " (from " << n << ")" << std::endl;
+        Trace("relational-trigger") << "    in quantifier " << f << std::endl;
+        if( hasPol ){
+          Trace("relational-trigger") << "    polarity : " << pol << std::endl;
+        }
+        Node rtr2 = (hasPol && pol) ? rtr.negate() : rtr;
+        InstConstantAttribute ica;
+        rtr2.setAttribute(ica,rtr.getAttribute(InstConstantAttribute()) );
+        return rtr2;
+      }
+    }
+  }
   bool usable = n.getAttribute(InstConstantAttribute())==f && isAtomicTrigger( n ) && isUsable( n, f );
   Trace("usable") << n << " usable : " << usable << std::endl;
-  return usable;
+  if( usable ){
+    return n;
+  }else{
+    return Node::null();
+  }
+}
+
+bool Trigger::isUsableTrigger( Node n, Node f ){
+  Node nu = getIsUsableTrigger(n,f);
+  return !nu.isNull();
 }
 
 bool Trigger::isAtomicTrigger( Node n ){
@@ -274,55 +336,51 @@ bool Trigger::isSimpleTrigger( Node n ){
 }
 
 
-bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt ){
+bool Trigger::collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, bool pol, bool hasPol ){
   if( patMap.find( n )==patMap.end() ){
     patMap[ n ] = false;
+    bool newHasPol = (n.getKind()==IFF || n.getKind()==XOR) ? false : hasPol;
+    bool newPol = n.getKind()==NOT ? !pol : pol;
     if( tstrt==TS_MIN_TRIGGER ){
       if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
-        //return collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt );
-        return collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt );
-#else
         return false;
-#endif
       }else{
         bool retVal = false;
         for( int i=0; i<(int)n.getNumChildren(); i++ ){
-          if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+          bool newPol2 = (n.getKind()==IMPLIES && i==0) ? !newPol : newPol;
+          bool newHasPol2 = (n.getKind()==ITE && i==0) ? false : newHasPol;
+          if( collectPatTerms2( qe, f, n[i], patMap, tstrt, newPol2, newHasPol2 ) ){
             retVal = true;
           }
         }
         if( retVal ){
           return true;
-        }else if( isUsableTrigger( n, f ) ){
-          patMap[ n ] = true;
-          return true;
         }else{
-          return false;
+          Node nu = getIsUsableTrigger( n, f, pol, hasPol );
+          if( !nu.isNull() ){
+            patMap[ nu ] = true;
+            return true;
+          }else{
+            return false;
+          }
         }
       }
     }else{
       bool retVal = false;
-      if( isUsableTrigger( n, f ) ){
-        patMap[ n ] = true;
+      Node nu = getIsUsableTrigger( n, f, pol, hasPol );
+      if( !nu.isNull() ){
+        patMap[ nu ] = true;
         if( tstrt==TS_MAX_TRIGGER ){
           return true;
         }else{
           retVal = true;
         }
       }
-      if( n.getKind()==FORALL ){
-#ifdef NESTED_PATTERN_SELECTION
-        //if( collectPatTerms2( qe, f, qe->getOrCreateCounterexampleBody( n ), patMap, tstrt ) ){
-        //  retVal = true;
-        //}
-        if( collectPatTerms2( qe, f, qe->getBoundBody( n ), patMap, tstrt ) ){
-          retVal = true;
-        }
-#endif
-      }else{
+      if( n.getKind()!=FORALL ){
         for( int i=0; i<(int)n.getNumChildren(); i++ ){
-          if( collectPatTerms2( qe, f, n[i], patMap, tstrt ) ){
+          bool newPol2 = (n.getKind()==IMPLIES && i==0) ? !newPol : newPol;
+          bool newHasPol2 = (n.getKind()==ITE && i==0) ? false : newHasPol;
+          if( collectPatTerms2( qe, f, n[i], patMap, tstrt, newPol2, newHasPol2 ) ){
             retVal = true;
           }
         }
@@ -367,7 +425,7 @@ void Trigger::collectPatTerms( QuantifiersEngine* qe, Node f, Node n, std::vecto
       }
     }
   }
-  collectPatTerms2( qe, f, n, patMap, tstrt );
+  collectPatTerms2( qe, f, n, patMap, tstrt, true, true );
   for( std::map< Node, bool >::iterator it = patMap.begin(); it != patMap.end(); ++it ){
     if( it->second ){
       patTerms.push_back( it->first );
index ca91247518b92e1021469f7b2aa0ce05aa8f5d17..28fb2acda9648c30f23187ff8d3736734a01b573 100644 (file)
@@ -92,8 +92,9 @@ public:
 private:
   /** is subterm of trigger usable */
   static bool isUsable( Node n, Node f );
+  static Node getIsUsableTrigger( Node n, Node f, bool pol = true, bool hasPol = false );
   /** collect all APPLY_UF pattern terms for f in n */
-  static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt );
+  static bool collectPatTerms2( QuantifiersEngine* qe, Node f, Node n, std::map< Node, bool >& patMap, int tstrt, bool pol, bool hasPol );
 public:
   //different strategies for choosing trigger terms
   enum {
index 0bb0f1f798699947fd7435b9d335900f61366a1a..5c24f89b7f06db87bd77edac82b9f45c023967d8 100644 (file)
@@ -27,6 +27,7 @@
 #include "theory/quantifiers/trigger.h"
 #include "theory/rewriterules/efficient_e_matching.h"
 #include "theory/rewriterules/rr_trigger.h"
+#include "theory/quantifiers/bounded_integers.h"
 
 using namespace std;
 using namespace CVC4;
@@ -60,8 +61,12 @@ d_lemmas_produced_c(u){
   if( options::finiteModelFind() ){
     d_model_engine = new quantifiers::ModelEngine( c, this );
     d_modules.push_back( d_model_engine );
+
+    d_bint = new quantifiers::BoundedIntegers( this );
+    d_modules.push_back( d_bint );
   }else{
     d_model_engine = NULL;
+    d_bint = NULL;
   }
 
   //options
index bfa19bb98b649361d8423cc946cb7a7489b4625c..85da530874611d499facb704208eb7c9b5e20c60 100644 (file)
@@ -56,7 +56,7 @@ public:
   virtual void assertNode( Node n ) = 0;
   virtual void propagate( Theory::Effort level ){}
   virtual Node getNextDecisionRequest() { return TNode::null(); }
-  virtual Node explain(TNode n) = 0;
+  virtual Node explain(TNode n) { return TNode::null(); }
 };/* class QuantifiersModule */
 
 namespace quantifiers {
@@ -64,6 +64,7 @@ namespace quantifiers {
   class ModelEngine;
   class TermDb;
   class FirstOrderModel;
+  class BoundedIntegers;
 }/* CVC4::theory::quantifiers */
 
 namespace inst {
@@ -99,6 +100,8 @@ private:
   std::map< Node, QuantPhaseReq* > d_phase_reqs;
   /** efficient e-matcher */
   EfficientEMatcher* d_eem;
+  /** bounded integers utility */
+  quantifiers::BoundedIntegers * d_bint;
 private:
   /** list of all quantifiers seen */
   std::vector< Node > d_quants;
index 33d1255ef2d2f18da0683e782b88e8828d605748..bea11621ab870ed0e6dc6779499b607200841e94 100644 (file)
@@ -30,5 +30,7 @@ option ufssSimpleCliques --uf-ss-simple-cliques bool :default true
  always use simple clique lemmas for uf strong solver
 option ufssDiseqPropagation --uf-ss-deq-prop bool :default false
  eagerly propagate disequalities for uf strong solver
+option ufssMinimalModel /--disable-uf-ss-min-model bool :default true
+ disable finding a minimal model in uf strong solver
 
 endmodule
index 228cfd2c4b2119a0d822152ec92af972e9f7c6c0..2c853a4fa60f961e696e60bdc7b0f7e83242bf90 100644 (file)
@@ -17,6 +17,7 @@
 #include "theory/uf/equality_engine.h"
 #include "theory/uf/theory_uf.h"
 #include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/options.h"
 
 #define RECONSIDER_FUNC_DEFAULT_VALUE
 #define USE_PARTIAL_DEFAULT_VALUES
@@ -309,19 +310,21 @@ void UfModelTreeGenerator::setValue( TheoryModel* m, Node n, Node v, bool ground
     if( !ground ){
       int defSize = (int)d_defaults.size();
       for( int i=0; i<defSize; i++ ){
-        bool isGround;
         //for soundness, to allow variable order-independent function interpretations,
         //  we must ensure that the intersection of all default terms
         //  is also defined.
         //for example, if we have that f( e, a ) = ..., and f( b, e ) = ...,
         //  then we must define f( b, a ).
-        Node ni = getIntersection( m, n, d_defaults[i], isGround );
-        if( !ni.isNull() ){
-          //if the intersection exists, and is not already defined
-          if( d_set_values[0][ isGround ? 1 : 0 ].find( ni )==d_set_values[0][ isGround ? 1 : 0 ].end() &&
-              d_set_values[1][ isGround ? 1 : 0 ].find( ni )==d_set_values[1][ isGround ? 1 : 0 ].end() ){
-            //use the current value
-            setValue( m, ni, v, isGround, false );
+        if (!options::fmfFullModelCheck()) {
+          bool isGround;
+          Node ni = getIntersection( m, n, d_defaults[i], isGround );
+          if( !ni.isNull() ){
+            //if the intersection exists, and is not already defined
+            if( d_set_values[0][ isGround ? 1 : 0 ].find( ni )==d_set_values[0][ isGround ? 1 : 0 ].end() &&
+                d_set_values[1][ isGround ? 1 : 0 ].find( ni )==d_set_values[1][ isGround ? 1 : 0 ].end() ){
+              //use the current value
+              setValue( m, ni, v, isGround, false );
+            }
           }
         }
       }
index 12c1cf24438974af509ab4cb66fab91097854f88..9140806ecf60a397b9741d45650f307db31b003e 100644 (file)
@@ -153,9 +153,10 @@ public:
   static Node toIte( TypeNode type, Node fm_node, const char* argPrefix );
 };
 
+
 class UfModelTreeGenerator
 {
-private:
+public:
   //store for set values
   Node d_default_value;
   std::map< Node, Node > d_set_values[2][2];
index d64f7df605229495b5bbfdcf0b38913ccca79042..e868460f84e703a792d797652fe5c5cc79ff2c5e 100644 (file)
@@ -595,9 +595,11 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
           if( d_regions[i]->d_valid ){
             std::vector< Node > clique;
             if( d_regions[i]->check( level, d_cardinality, clique ) ){
-              //add clique lemma
-              addCliqueLemma( clique, out );
-              return;
+              if( options::ufssMinimalModel() ){
+                //add clique lemma
+                addCliqueLemma( clique, out );
+                return;
+              }
             }else{
               Trace("uf-ss-debug") << "No clique in Region #" << i << std::endl;
             }
@@ -659,13 +661,17 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel
               //naive strategy, force region combination involving the first valid region
               for( int i=0; i<(int)d_regions_index; i++ ){
                 if( d_regions[i]->d_valid ){
-                  forceCombineRegion( i, false );
-                  recheck = true;
-                  break;
+                  int fcr = forceCombineRegion( i, false );
+                  Trace("uf-ss-debug") << "Combined regions " << i << " " << fcr << std::endl;
+                  if( options::ufssMinimalModel() || fcr!=-1 ){
+                    recheck = true;
+                    break;
+                  }
                 }
               }
             }
             if( recheck ){
+              Trace("uf-ss-debug") << "Must recheck." << std::endl;
               check( level, out );
             }
           }
@@ -869,8 +875,10 @@ void StrongSolverTheoryUF::SortModel::checkRegion( int ri, bool checkCombine ){
     //now check if region is in conflict
     std::vector< Node > clique;
     if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
-      //explain clique
-      addCliqueLemma( clique, &d_thss->getOutputChannel() );
+      if( options::ufssMinimalModel() ){
+        //explain clique
+        addCliqueLemma( clique, &d_thss->getOutputChannel() );
+      }
     }
   }
 }
@@ -1013,8 +1021,8 @@ void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){
 }
 
 bool StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
+  Node s;
   if( r->hasSplits() ){
-    Node s;
     if( !options::ufssSmartSplits() ){
       //take the first split you find
       for( NodeBoolMap::iterator it = r->d_splits.begin(); it != r->d_splits.end(); ++it ){
@@ -1038,8 +1046,26 @@ bool StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){
         }
       }
     }
+    Assert( s!=Node::null() );
+  }else{
+    if( !options::ufssMinimalModel() ){
+      //since candidate clique is not reported, we may need to find splits manually
+      for ( std::map< Node, Region::RegionNodeInfo* >::iterator it = r->d_nodes.begin(); it != r->d_nodes.end(); ++it ){
+        if ( it->second->d_valid ){
+          for ( std::map< Node, Region::RegionNodeInfo* >::iterator it2 = r->d_nodes.begin(); it2 != r->d_nodes.end(); ++it2 ){
+            if ( it->second!=it2->second && it2->second->d_valid ){
+              if( !r->isDisequal( it->first, it2->first, 1 ) ){
+                s = NodeManager::currentNM()->mkNode( EQUAL, it->first, it2->first );
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  if (!s.isNull() ){
     //add lemma to output channel
-    Assert( s!=Node::null() && s.getKind()==EQUAL );
+    Assert( s.getKind()==EQUAL );
     s = Rewriter::rewrite( s );
     Trace("uf-ss-lemma") << "*** Split on " << s << std::endl;
     if( options::sortInference()) {