First draft of ambqi_builder (new implementation of MBQI based on disjoint sets).
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Tue, 6 May 2014 13:19:04 +0000 (08:19 -0500)
committerAndrew Reynolds <andrew.j.reynolds@gmail.com>
Tue, 6 May 2014 13:19:16 +0000 (08:19 -0500)
src/Makefile.am
src/theory/quantifiers/ambqi_builder.cpp [new file with mode: 0755]
src/theory/quantifiers/ambqi_builder.h [new file with mode: 0755]
src/theory/quantifiers/first_order_model.cpp
src/theory/quantifiers/first_order_model.h
src/theory/quantifiers/model_engine.cpp
src/theory/quantifiers/modes.cpp
src/theory/quantifiers/modes.h
src/theory/quantifiers/options_handlers.h
src/theory/quantifiers_engine.cpp

index e7cc9628e9f0dda1f635642e6046b923ce3ac262..573181ccfad2d28befff735cf3cc001f557be5ac 100644 (file)
@@ -306,6 +306,8 @@ libcvc4_la_SOURCES = \
        theory/quantifiers/symmetry_breaking.cpp \
        theory/quantifiers/qinterval_builder.h \
        theory/quantifiers/qinterval_builder.cpp \
+       theory/quantifiers/ambqi_builder.h \
+       theory/quantifiers/ambqi_builder.cpp \
        theory/quantifiers/quant_conflict_find.h \
        theory/quantifiers/quant_conflict_find.cpp \
        theory/quantifiers/options_handlers.h \
diff --git a/src/theory/quantifiers/ambqi_builder.cpp b/src/theory/quantifiers/ambqi_builder.cpp
new file mode 100755 (executable)
index 0000000..7a296c9
--- /dev/null
@@ -0,0 +1,715 @@
+/*********************                                                        */\r
+/*! \file ambqi_builder.cpp\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-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 abstract MBQI builder\r
+ **/\r
+\r
+\r
+#include "theory/quantifiers/ambqi_builder.h"\r
+#include "theory/quantifiers/term_database.h"\r
+\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
+\r
+void AbsDef::construct_func( FirstOrderModelAbs * m, std::vector< TNode >& fapps, unsigned depth ) {\r
+  d_def.clear();\r
+  Assert( !fapps.empty() );\r
+  if( depth==fapps[0].getNumChildren() ){\r
+    //get representative in model for this term\r
+    Assert( fapps.size()==1 );\r
+    d_value = m->getRepresentativeId( fapps[0] );\r
+    Assert( d_value!=-1 );\r
+  }else{\r
+    TypeNode tn = fapps[0][depth].getType();\r
+    std::map< unsigned, std::vector< TNode > > fapp_child;\r
+\r
+    //partition based on evaluations of fapps[1][depth]....fapps[n][depth]\r
+    for( unsigned i=0; i<fapps.size(); i++ ){\r
+      unsigned r = m->getRepresentativeId( fapps[i][depth] );\r
+      Assert( r < 32 );\r
+      fapp_child[r].push_back( fapps[i] );\r
+    }\r
+\r
+    //do completion\r
+    std::map< unsigned, unsigned > fapp_child_index;\r
+    unsigned def = m->d_domain[ tn ];\r
+    unsigned minSize = fapp_child.begin()->second.size();\r
+    unsigned minSizeIndex = fapp_child.begin()->first;\r
+    for( std::map< unsigned, std::vector< TNode > >::iterator it = fapp_child.begin(); it != fapp_child.end(); ++it ){\r
+      fapp_child_index[it->first] = ( 1 << it->first );\r
+      def = def & ~( 1 << it->first );\r
+      if( it->second.size()<minSize ){\r
+        minSize = it->second.size();\r
+        minSizeIndex = it->first;\r
+      }\r
+    }\r
+    fapp_child_index[minSizeIndex] |= def;\r
+    d_default = fapp_child_index[minSizeIndex];\r
+\r
+    //construct children\r
+    for( std::map< unsigned, std::vector< TNode > >::iterator it = fapp_child.begin(); it != fapp_child.end(); ++it ){\r
+      Trace("abs-model-debug") << "Construct " << it->first << " : " << fapp_child_index[it->first] << " : ";\r
+      debugPrintUInt( "abs-model-debug", m->d_rep_set.d_type_reps[tn].size(), fapp_child_index[it->first] );\r
+      Trace("abs-model-debug") << " : " << it->second.size() << " terms." << std::endl;\r
+      d_def[fapp_child_index[it->first]].construct_func( m, it->second, depth+1 );\r
+    }\r
+  }\r
+}\r
+\r
+void AbsDef::simplify( FirstOrderModelAbs * m, Node q, unsigned depth ) {\r
+  if( d_value==-1 ){\r
+    //process the default\r
+    std::map< unsigned, AbsDef >::iterator defd = d_def.find( d_default );\r
+    unsigned newDef = d_default;\r
+    std::vector< unsigned > to_erase;\r
+    defd->second.simplify( m, q, depth+1 );\r
+    bool isConstant = ( defd->second.d_value!=-1 );\r
+    //process each child\r
+    for( std::map< unsigned, AbsDef >::iterator it = d_def.begin(); it != d_def.end(); ++it ){\r
+      if( it->first!=d_default ){\r
+        it->second.simplify( m, q, depth+1 );\r
+        if( it->second.d_value==defd->second.d_value && it->second.d_value!=-1 ){\r
+          newDef = d_default | it->first;\r
+          to_erase.push_back( it->first );\r
+        }else{\r
+          isConstant = false;\r
+        }\r
+      }\r
+    }\r
+    if( !to_erase.empty() ){\r
+      //erase old default\r
+      int defVal = defd->second.d_value;\r
+      d_def.erase( d_default );\r
+      //set new default\r
+      d_default = newDef;\r
+      d_def[d_default].construct_def_entry( m, q, defVal, depth+1 );\r
+      //erase redundant entries\r
+      for( unsigned i=0; i<to_erase.size(); i++ ){\r
+        d_def.erase( to_erase[i] );\r
+      }\r
+    }\r
+    //if constant, propagate the value upwards\r
+    if( isConstant ){\r
+      d_value = defd->second.d_value;\r
+    }\r
+  }\r
+}\r
+\r
+void AbsDef::debugPrintUInt( const char * c, unsigned dSize, unsigned u ) {\r
+  for( unsigned i=0; i<dSize; i++ ){\r
+    Trace(c) << ( ( u & ( 1 << i ) )!=0 ? "1" : "0");\r
+  }\r
+}\r
+\r
+void AbsDef::debugPrint( const char * c, FirstOrderModelAbs * m, Node f, unsigned depth ) {\r
+  if( Trace.isOn(c) ){\r
+    if( depth==f.getNumChildren() ){\r
+      for( unsigned i=0; i<depth; i++ ){ Trace(c) << "  ";}\r
+      Trace(c) << "V[" << d_value << "]" << std::endl;\r
+    }else{\r
+      TypeNode tn = f[depth].getType();\r
+      unsigned dSize = m->d_rep_set.d_type_reps[tn].size();\r
+      Assert( dSize<32 );\r
+      for( std::map< unsigned, AbsDef >::iterator it = d_def.begin(); it != d_def.end(); ++it ){\r
+        for( unsigned i=0; i<depth; i++ ){ Trace(c) << "  ";}\r
+        debugPrintUInt( c, dSize, it->first );\r
+        if( it->first==d_default ){\r
+          Trace(c) << "*";\r
+        }\r
+        if( it->second.d_value!=-1 ){\r
+          Trace(c) << " -> V[" << it->second.d_value << "]";\r
+        }\r
+        Trace(c) << std::endl;\r
+        it->second.debugPrint( c, m, f, depth+1 );\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+int AbsDef::addInstantiations( FirstOrderModelAbs * m, QuantifiersEngine * qe, Node q, std::vector< Node >& terms, unsigned depth ) {\r
+  if( depth==q[0].getNumChildren() ){\r
+    if( d_value!=1 ){\r
+      if( qe->addInstantiation( q, terms ) ){\r
+        return 1;\r
+      }\r
+    }\r
+    return 0;\r
+  }else{\r
+    int sum = 0;\r
+    TypeNode tn = q[0][depth].getType();\r
+    for( std::map< unsigned, AbsDef >::iterator it = d_def.begin(); it != d_def.end(); ++it ){\r
+      //get witness term\r
+      int index = getId( it->first );\r
+      terms.push_back( m->d_rep_set.d_type_reps[tn][index] );\r
+      sum += it->second.addInstantiations( m, qe, q, terms, depth+1 );\r
+      terms.pop_back();\r
+    }\r
+    return sum;\r
+  }\r
+}\r
+\r
+void AbsDef::construct_entry( std::vector< unsigned >& entry, std::vector< bool >& entry_def, int v, unsigned depth ) {\r
+  if( depth==entry.size() ){\r
+    d_value = v;\r
+  }else{\r
+    d_def[entry[depth]].construct_entry( entry, entry_def, v, depth+1 );\r
+    if( entry_def[depth] ){\r
+      d_default = entry[depth];\r
+    }\r
+  }\r
+}\r
+\r
+void AbsDef::construct_def_entry( FirstOrderModelAbs * m, Node q, int v, unsigned depth ) {\r
+  if( depth==q[0].getNumChildren() ){\r
+    d_value = v;\r
+  }else{\r
+    unsigned dom = m->d_domain[q[0][depth].getType()];\r
+    d_def[dom].construct_def_entry( m, q, v, depth+1 );\r
+    d_default = dom;\r
+  }\r
+}\r
+\r
+void AbsDef::apply_ucompose( std::vector< unsigned >& entry, std::vector< bool >& entry_def,\r
+                             std::vector< int >& terms, std::map< unsigned, int >& vchildren,\r
+                             AbsDef * a, unsigned depth ) {\r
+  if( depth==terms.size() ){\r
+    a->construct_entry( entry, entry_def, d_value );\r
+  }else{\r
+    unsigned id;\r
+    if( terms[depth]==-1 ){\r
+      //a variable\r
+      std::map< unsigned, int >::iterator itv = vchildren.find( depth );\r
+      Assert( itv!=vchildren.end() );\r
+      unsigned prev_v = entry[itv->second];\r
+      bool prev_vd = entry_def[itv->second];\r
+      for( std::map< unsigned, AbsDef >::iterator it = d_def.begin(); it != d_def.end(); ++it ){\r
+        entry[itv->second] = it->first & prev_v;\r
+        entry_def[itv->second] = ( it->first==d_default ) && prev_vd;\r
+        if( entry[itv->second]!=0 ){\r
+          it->second.apply_ucompose( entry, entry_def, terms, vchildren, a, depth+1 );\r
+        }\r
+      }\r
+      entry[itv->second] = prev_v;\r
+      entry_def[itv->second] = prev_vd;\r
+    }else{\r
+      id = (unsigned)terms[depth];\r
+      Assert( id<32 );\r
+      unsigned fid = 1 << id;\r
+      std::map< unsigned, AbsDef >::iterator it = d_def.find( fid );\r
+      if( it!=d_def.end() ){\r
+        it->second.apply_ucompose( entry, entry_def, terms, vchildren, a, depth+1 );\r
+      }else{\r
+        d_def[d_default].apply_ucompose( entry, entry_def, terms, vchildren, a, depth+1 );\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void AbsDef::construct_var_eq( FirstOrderModelAbs * m, Node q, unsigned v1, unsigned v2, int curr, int currv, unsigned depth ) {\r
+  if( depth==q[0].getNumChildren() ){\r
+    Assert( currv!=-1 );\r
+    d_value = currv;\r
+  }else{\r
+    TypeNode tn = q[0][depth].getType();\r
+    unsigned dom = m->d_domain[tn];\r
+    int vindex = depth==v1 ? 0 : ( depth==v2 ? 1 : -1 );\r
+    if( vindex==-1 ){\r
+      d_def[dom].construct_var_eq( m, q, v1, v2, curr, currv, depth+1 );\r
+      d_default = dom;\r
+    }else{\r
+      Assert( currv==-1 );\r
+      if( curr==-1 ){\r
+        unsigned numReps = m->d_rep_set.d_type_reps[tn].size();\r
+        Assert( numReps < 32 );\r
+        for( unsigned i=0; i<numReps; i++ ){\r
+          curr = 1 << i;\r
+          d_def[curr].construct_var_eq( m, q, v1, v2, curr, currv, depth+1 );\r
+        }\r
+        d_default = curr;\r
+      }else{\r
+        d_def[curr].construct_var_eq( m, q, v1, v2, curr, 1, depth+1 );\r
+        dom = dom & ~curr;\r
+        d_def[dom].construct_var_eq( m, q, v1, v2, curr, 0, depth+1 );\r
+        d_default = dom;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void AbsDef::construct_var( FirstOrderModelAbs * m, Node q, unsigned v, int currv, unsigned depth ) {\r
+  if( depth==q[0].getNumChildren() ){\r
+    Assert( currv!=-1 );\r
+    d_value = currv;\r
+  }else{\r
+    TypeNode tn = q[0][depth].getType();\r
+    if( v==depth ){\r
+      unsigned numReps = m->d_rep_set.d_type_reps[tn].size();\r
+      Assert( numReps>0 && numReps < 32 );\r
+      for( unsigned i=0; i<numReps; i++ ){\r
+        d_def[ 1 << i ].construct_var( m, q, v, i, depth+1 );\r
+      }\r
+      d_default = 1 << (numReps-1);\r
+    }else{\r
+      unsigned dom = m->d_domain[tn];\r
+      d_def[dom].construct_var( m, q, v, currv, depth+1 );\r
+      d_default = dom;\r
+    }\r
+  }\r
+}\r
+\r
+void AbsDef::construct_compose( FirstOrderModelAbs * m, Node q, Node n, AbsDef * f,\r
+                                std::map< unsigned, AbsDef * >& children,\r
+                                std::map< unsigned, int >& bchildren, std::map< unsigned, int >& vchildren,\r
+                                std::vector< unsigned >& entry, std::vector< bool >& entry_def,\r
+                                bool incomplete ) {\r
+  if( Trace.isOn("ambqi-check-debug2") ){\r
+    for( unsigned i=0; i<entry.size(); i++ ){ Trace("ambqi-check-debug2") << "  "; }\r
+  }\r
+  if( n.getKind()==OR || n.getKind()==AND ){\r
+    // short circuiting\r
+    for( std::map< unsigned, AbsDef * >::iterator it = children.begin(); it != children.end(); ++it ){\r
+      if( ( it->second->d_value==0 && n.getKind()==AND ) ||\r
+          ( it->second->d_value==1 && n.getKind()==OR ) ){\r
+        construct_entry( entry, entry_def, it->second->d_value );\r
+        return;\r
+      }\r
+    }\r
+  }\r
+  if( entry.size()==q[0].getNumChildren() ){\r
+    if( incomplete ){\r
+      //if a child is unknown, we must return unknown\r
+      construct_entry( entry, entry_def, -1 );\r
+    }else{\r
+      if( f ){\r
+        Trace("ambqi-check-debug2") << "Evaluate uninterpreted function entry..." << std::endl;\r
+        //we are composing with an uninterpreted function\r
+        std::vector< int > values;\r
+        values.resize( n.getNumChildren(), -1 );\r
+        for( std::map< unsigned, AbsDef * >::iterator it = children.begin(); it != children.end(); ++it ){\r
+          values[it->first] = it->second->d_value;\r
+        }\r
+        for( std::map< unsigned, int >::iterator it = bchildren.begin(); it != bchildren.end(); ++it ){\r
+          values[it->first] = it->second;\r
+        }\r
+        //look up value(s)\r
+        f->apply_ucompose( entry, entry_def, values, vchildren, this );\r
+      }else{\r
+        //we are composing with an interpreted function\r
+        std::vector< TNode > values;\r
+        values.resize( n.getNumChildren(), TNode::null() );\r
+        for( std::map< unsigned, AbsDef * >::iterator it = children.begin(); it != children.end(); ++it ){\r
+          Assert( it->second->d_value>=0 && it->second->d_value<(int)m->d_rep_set.d_type_reps[n[it->first].getType()].size() );\r
+          values[it->first] = m->d_rep_set.d_type_reps[n[it->first].getType()][it->second->d_value];\r
+          Trace("ambqi-check-debug2") << it->first << " : " << it->second->d_value << " ->> " << values[it->first] << std::endl;\r
+        }\r
+        for( std::map< unsigned, int >::iterator it = bchildren.begin(); it != bchildren.end(); ++it ){\r
+          Assert( it->second>=0 && it->second<(int)m->d_rep_set.d_type_reps[n[it->first].getType()].size() );\r
+          values[it->first] = m->d_rep_set.d_type_reps[n[it->first].getType()][it->second];\r
+          Trace("ambqi-check-debug2") << it->first << " : " << it->second << " ->> " << values[it->first] << std::endl;\r
+        }\r
+        Assert( vchildren.empty() );\r
+        if( Trace.isOn("ambqi-check-debug2") ){\r
+          Trace("ambqi-check-debug2") << "Evaluate interpreted function entry ( ";\r
+          for( unsigned i=0; i<values.size(); i++ ){\r
+            Trace("ambqi-check-debug2") << values[i] << " ";\r
+          }\r
+          Trace("ambqi-check-debug2") << ")..." << std::endl;\r
+        }\r
+        //evaluate\r
+        Node vv = NodeManager::currentNM()->mkNode( n.getKind(), values );\r
+        vv = Rewriter::rewrite( vv );\r
+        int v = m->getRepresentativeId( vv );\r
+        construct_entry( entry, entry_def, v );\r
+      }\r
+    }\r
+  }else{\r
+    //take product of arguments\r
+    TypeNode tn = q[0][entry.size()].getType();\r
+    unsigned def = m->d_domain[tn];\r
+    Trace("ambqi-check-debug2") << "Take product of arguments" << std::endl;\r
+    for( std::map< unsigned, AbsDef * >::iterator it = children.begin(); it != children.end(); ++it ){\r
+      //process each child\r
+      for( std::map< unsigned, AbsDef >::iterator itd = it->second->d_def.begin(); itd != it->second->d_def.end(); ++itd ){\r
+        if( itd->first!=it->second->d_default && ( def & itd->first )!=0 ){\r
+          def &= ~( itd->first );\r
+          //process this value\r
+          std::map< unsigned, AbsDef * > cchildren;\r
+          for( std::map< unsigned, AbsDef * >::iterator it2 = children.begin(); it2 != children.end(); ++it2 ){\r
+            std::map< unsigned, AbsDef >::iterator itdf = it->second->d_def.find( itd->first );\r
+            if( itdf!=it->second->d_def.end() ){\r
+              cchildren[it->first] = &itdf->second;\r
+            }else{\r
+              cchildren[it->first] = it2->second->getDefault();\r
+            }\r
+          }\r
+          if( Trace.isOn("ambqi-check-debug2") ){\r
+            for( unsigned i=0; i<entry.size(); i++ ){ Trace("ambqi-check-debug2") << "  "; }\r
+            Trace("ambqi-check-debug2") << "...process : ";\r
+            debugPrintUInt("ambqi-check-debug2", m->d_rep_set.d_type_reps[tn].size(), itd->first );\r
+            Trace("ambqi-check-debug2") << std::endl;\r
+          }\r
+          entry.push_back( itd->first );\r
+          entry_def.push_back( def==0 );\r
+          construct_compose( m, q, n, f, cchildren, bchildren, vchildren, entry, entry_def, incomplete );\r
+          entry_def.pop_back();\r
+          entry.pop_back();\r
+          if( def==0 ){\r
+            break;\r
+          }\r
+        }\r
+      }\r
+      if( def==0 ){\r
+        break;\r
+      }\r
+    }\r
+    if( def!=0 ){\r
+      std::map< unsigned, AbsDef * > cdchildren;\r
+      for( std::map< unsigned, AbsDef * >::iterator it = children.begin(); it != children.end(); ++it ){\r
+        cdchildren[it->first] = it->second->getDefault();\r
+      }\r
+      if( Trace.isOn("ambqi-check-debug2") ){\r
+        for( unsigned i=0; i<entry.size(); i++ ){ Trace("ambqi-check-debug2") << "  "; }\r
+        Trace("ambqi-check-debug2") << "...process default : ";\r
+        debugPrintUInt("ambqi-check-debug2", m->d_rep_set.d_type_reps[tn].size(), def );\r
+        Trace("ambqi-check-debug2") << std::endl;\r
+      }\r
+      entry.push_back( def );\r
+      entry_def.push_back( true );\r
+      construct_compose( m, q, n, f, cdchildren, bchildren, vchildren, entry, entry_def, incomplete );\r
+      entry_def.pop_back();\r
+      entry.pop_back();\r
+    }\r
+  }\r
+}\r
+\r
+bool AbsDef::construct( FirstOrderModelAbs * m, Node q, Node n, AbsDef * f,\r
+                        std::map< unsigned, AbsDef * >& children,\r
+                        std::map< unsigned, int >& bchildren, std::map< unsigned, int >& vchildren,\r
+                        int varChCount, bool incomplete ) {\r
+  if( varChCount==0 || f ){\r
+    //short-circuit\r
+    if( n.getKind()==AND || n.getKind()==OR ){\r
+      for( std::map< unsigned, int >::iterator it = bchildren.begin(); it !=bchildren.end(); ++it ){\r
+        if( ( it->second==0 && n.getKind()==AND ) ||\r
+            ( it->second==1 && n.getKind()==OR ) ){\r
+          construct_def_entry( m, q, it->second );\r
+          return true;\r
+        }\r
+      }\r
+    }\r
+    Trace("ambqi-check-debug2") << "Construct compose..." << std::endl;\r
+    std::vector< unsigned > entry;\r
+    std::vector< bool > entry_def;\r
+    construct_compose( m, q, n, f, children, bchildren, vchildren, entry, entry_def, incomplete );\r
+    return true;\r
+  }else if( varChCount==1 && n.getKind()==EQUAL ){\r
+    Trace("ambqi-check-debug2") << "Expand variable child..." << std::endl;\r
+    //expand the variable based on its finite domain\r
+    AbsDef a;\r
+    a.construct_var( m, q, vchildren.begin()->second, -1 );\r
+    children[vchildren.begin()->first] = &a;\r
+    vchildren.clear();\r
+    std::vector< unsigned > entry;\r
+    std::vector< bool > entry_def;\r
+    Trace("ambqi-check-debug2") << "Construct compose with variable..." << std::endl;\r
+    construct_compose( m, q, n, f, children, bchildren, vchildren, entry, entry_def, incomplete );\r
+    return true;\r
+  }else if( varChCount==2 && n.getKind()==EQUAL ){\r
+    Trace("ambqi-check-debug2") << "Construct variable equality..." << std::endl;\r
+    //efficient expansion of the equality\r
+    construct_var_eq( m, q, vchildren[0], vchildren[1], -1, -1 );\r
+    return true;\r
+  }else{\r
+    return false;\r
+  }\r
+}\r
+\r
+Node AbsDef::getFunctionValue( FirstOrderModelAbs * m, TNode op, std::vector< Node >& vars, unsigned depth ) {\r
+  if( depth==vars.size() ){\r
+    TypeNode tn = op.getType();\r
+    if( tn.getNumChildren()>0 ){\r
+      tn = tn[tn.getNumChildren()-1];\r
+    }\r
+    if( d_value>=0 ){\r
+      Assert( d_value<(int)m->d_rep_set.d_type_reps[tn].size() );\r
+      if( tn.isBoolean() ){\r
+        return NodeManager::currentNM()->mkConst( d_value==1 );\r
+      }else{\r
+        return m->d_rep_set.d_type_reps[tn][d_value];\r
+      }\r
+    }else{\r
+      return Node::null();\r
+    }\r
+  }else{\r
+    TypeNode tn = vars[depth].getType();\r
+    Node curr;\r
+    curr = d_def[d_default].getFunctionValue( m, op, vars, depth+1 );\r
+    for( std::map< unsigned, AbsDef >::iterator it = d_def.begin(); it != d_def.end(); ++it ){\r
+      if( it->first!=d_default ){\r
+        unsigned id = getId( it->first );\r
+        Assert( id<m->d_rep_set.d_type_reps[tn].size() );\r
+        TNode n = m->d_rep_set.d_type_reps[tn][id];\r
+        Node fv = it->second.getFunctionValue( m, op, vars, depth+1 );\r
+        if( !curr.isNull() && !fv.isNull() ){\r
+          curr = NodeManager::currentNM()->mkNode( ITE, vars[depth].eqNode( n ), fv, curr );\r
+        }else{\r
+          curr = Node::null();\r
+        }\r
+      }\r
+    }\r
+    return curr;\r
+  }\r
+}\r
+\r
+unsigned AbsDef::getId( unsigned n ) {\r
+  Assert( n!=0 );\r
+  unsigned index = 0;\r
+  while( (n & ( 1 << index )) == 0 ){\r
+    index++;\r
+  }\r
+  return index;\r
+}\r
+\r
+Node AbsDef::evaluate( FirstOrderModelAbs * m, TypeNode retTyp, std::vector< Node >& args ) {\r
+  std::vector< unsigned > iargs;\r
+  for( unsigned i=0; i<args.size(); i++ ){\r
+    unsigned v = 1 << m->getRepresentativeId( args[i] );\r
+    iargs.push_back( v );\r
+  }\r
+  return evaluate( m, retTyp, iargs, 0 );\r
+}\r
+\r
+Node AbsDef::evaluate( FirstOrderModelAbs * m, TypeNode retTyp, std::vector< unsigned >& iargs, unsigned depth ) {\r
+  if( d_value!=-1 ){\r
+    Assert( d_value>=0 && d_value<(int)m->d_rep_set.d_type_reps[retTyp].size() );\r
+    return m->d_rep_set.d_type_reps[retTyp][d_value];\r
+  }else{\r
+    std::map< unsigned, AbsDef >::iterator it = d_def.find( iargs[depth] );\r
+    if( it==d_def.end() ){\r
+      return d_def[d_default].evaluate( m, retTyp, iargs, depth+1 );\r
+    }else{\r
+      return it->second.evaluate( m, retTyp, iargs, depth+1 );\r
+    }\r
+  }\r
+}\r
+\r
+AbsMbqiBuilder::AbsMbqiBuilder( context::Context* c, QuantifiersEngine* qe ) :\r
+QModelBuilder( c, qe ){\r
+  d_true = NodeManager::currentNM()->mkConst( true );\r
+  d_false = NodeManager::currentNM()->mkConst( false );\r
+}\r
+\r
+\r
+//------------------------model construction----------------------------\r
+\r
+void AbsMbqiBuilder::processBuildModel(TheoryModel* m, bool fullModel) {\r
+  Trace("ambqi-debug") << "process build model " << fullModel << std::endl;\r
+  FirstOrderModel* f = (FirstOrderModel*)m;\r
+  FirstOrderModelAbs* fm = f->asFirstOrderModelAbs();\r
+  if( fullModel ){\r
+    Trace("ambqi-model") << "Construct model representation..." << std::endl;\r
+    //make function values\r
+    for( std::map<Node, AbsDef * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ) {\r
+      if( it->first.getType().getNumChildren()>1 ){\r
+        Trace("ambqi-model") << "Construct for " << it->first << "..." << std::endl;\r
+        m->d_uf_models[ it->first ] = fm->getFunctionValue( it->first, "$x" );\r
+      }\r
+    }\r
+    TheoryEngineModelBuilder::processBuildModel( m, fullModel );\r
+    //mark that the model has been set\r
+    fm->markModelSet();\r
+    //debug the model\r
+    debugModel( fm );\r
+  }else{\r
+    fm->initialize( d_considerAxioms );\r
+    //process representatives\r
+    fm->d_rep_id.clear();\r
+    fm->d_domain.clear();\r
+\r
+    //initialize boolean sort\r
+    TypeNode b = d_true.getType();\r
+    fm->d_rep_set.d_type_reps[b].clear();\r
+    fm->d_rep_set.d_type_reps[b].push_back( d_false );\r
+    fm->d_rep_set.d_type_reps[b].push_back( d_true );\r
+    fm->d_rep_id[d_false] = 0;\r
+    fm->d_rep_id[d_true] = 1;\r
+\r
+    //initialize unintpreted sorts\r
+    Trace("ambqi-model") << std::endl << "Making representatives..." << std::endl;\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
+        Assert( !it->second.empty() );\r
+        //set the domain\r
+        fm->d_domain[it->first] = 0;\r
+        Trace("ambqi-model") << "Representatives for " << it->first << " : " << std::endl;\r
+        for( unsigned i=0; i<it->second.size(); i++ ){\r
+          if( i<32 ){\r
+            fm->d_domain[it->first] |= ( 1 << i );\r
+          }\r
+          Trace("ambqi-model") << i << " : " << it->second[i] << std::endl;\r
+          fm->d_rep_id[it->second[i]] = i;\r
+        }\r
+        if( it->second.size()>=32 ){\r
+          fm->d_domain.erase( it->first );\r
+        }\r
+      }\r
+    }\r
+\r
+    Trace("ambqi-model") << std::endl << "Making function definitions..." << std::endl;\r
+    //construct the models for functions\r
+    for( std::map<Node, AbsDef * >::iterator it = fm->d_models.begin(); it != fm->d_models.end(); ++it ) {\r
+      Node f = it->first;\r
+      Trace("ambqi-model-debug") << "Building Model for " << f << std::endl;\r
+      //reset the model\r
+      //get all (non-redundant) f-applications\r
+      std::vector< TNode > fapps;\r
+      Trace("ambqi-model-debug") << "Initial terms: " << std::endl;\r
+      for( size_t i=0; i<fm->d_uf_terms[f].size(); i++ ){\r
+        Node n = fm->d_uf_terms[f][i];\r
+        if( !n.getAttribute(NoMatchAttribute()) ){\r
+          Trace("ambqi-model-debug") << "  " << n << " -> " << fm->getRepresentativeId( n ) << std::endl;\r
+          fapps.push_back( n );\r
+        }\r
+      }\r
+      if( fapps.empty() ){\r
+        //choose arbitrary value\r
+        Node mbt = d_qe->getTermDatabase()->getModelBasisOpTerm(f);\r
+        Trace("ambqi-model-debug") << "Initial terms empty, add " << mbt << std::endl;\r
+        fapps.push_back( mbt );\r
+      }\r
+      bool fValid = true;\r
+      for( unsigned i=0; i<fapps[0].getNumChildren(); i++ ){\r
+        if( fm->d_domain.find( fapps[0][i].getType() )==fm->d_domain.end() ){\r
+          Trace("ambqi-model") << "Interpretation of " << f << " is not valid.";\r
+          Trace("ambqi-model") << " (domain for " << fapps[0][i].getType() << " is too large)." << std::endl;\r
+          fValid = false;\r
+          break;\r
+        }\r
+      }\r
+      fm->d_models_valid[f] = fValid;\r
+      if( fValid ){\r
+        //construct the ambqi model\r
+        it->second->construct_func( fm, fapps );\r
+        Trace("ambqi-model-debug") << "Interpretation of " << f << " : " << std::endl;\r
+        it->second->debugPrint("ambqi-model-debug", fm, fapps[0] );\r
+\r
+        it->second->simplify( fm, Node::null() );\r
+        Trace("ambqi-model") << "(Simplified) interpretation of " << f << " : " << std::endl;\r
+        it->second->debugPrint("ambqi-model", fm, fapps[0] );\r
+\r
+/*\r
+        if( Debug.isOn("ambqi-model-debug") ){\r
+          for( size_t i=0; i<fm->d_uf_terms[f].size(); i++ ){\r
+            Node e = it->second->evaluate_n( fm, fm->d_uf_terms[f][i] );\r
+            Debug("ambqi-model-debug") << fm->d_uf_terms[f][i] << " evaluates to " << e << std::endl;\r
+            Assert( fm->areEqual( e, fm->d_uf_terms[f][i] ) );\r
+          }\r
+        }\r
+*/\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+\r
+//--------------------model checking---------------------------------------\r
+\r
+//do exhaustive instantiation\r
+bool AbsMbqiBuilder::doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort ) {\r
+  Trace("ambqi-check") << "exhaustive instantiation " << q << " " << effort << std::endl;\r
+  if (effort==0) {\r
+    FirstOrderModelAbs * fma = fm->asFirstOrderModelAbs();\r
+    bool quantValid = true;\r
+    for( unsigned i=0; i<q[0].getNumChildren(); i++ ){\r
+      if( !fma->isValidType( q[0][i].getType() ) ){\r
+        quantValid = false;\r
+        Trace("ambqi-inst") << "Interpretation of " << q << " is not valid because of type " << q[0][i].getType() << std::endl;\r
+        break;\r
+      }\r
+    }\r
+    if( quantValid ){\r
+      AbsDef ad;\r
+      doCheck( fma, q, ad, q[1] );\r
+      //now process entries\r
+      Trace("ambqi-inst") << "Interpretation of " << q << " is : " << std::endl;\r
+      ad.debugPrint( "ambqi-inst", fma, q );\r
+      Trace("ambqi-inst") << std::endl;\r
+      int lem = ad.addInstantiations( fma, d_qe, q );\r
+      Trace("ambqi-inst") << "...Added " << lem << " lemmas." << std::endl;\r
+      d_addedLemmas += lem;\r
+    }\r
+    return quantValid;\r
+  }\r
+  return true;\r
+}\r
+\r
+bool AbsMbqiBuilder::doCheck( FirstOrderModelAbs * m, TNode q, AbsDef & ad, TNode n ) {\r
+  Assert( n.getKind()!=FORALL );\r
+  std::map< unsigned, AbsDef > children;\r
+  std::map< unsigned, int > bchildren;\r
+  std::map< unsigned, int > vchildren;\r
+  bool incomplete = false;\r
+  int varChCount = 0;\r
+  for( unsigned i=0; i<n.getNumChildren(); i++ ){\r
+    if( n[i].getKind()==FORALL ){\r
+      bchildren[i] = -1;\r
+      incomplete = true;\r
+    }else if( n[i].getKind() == BOUND_VARIABLE ){\r
+      varChCount++;\r
+      vchildren[i] = m->getVariableId( q, n[i] );\r
+    }else if( m->hasTerm( n[i] ) ){\r
+      bchildren[i] = m->getRepresentativeId( n[i] );\r
+    }else{\r
+      if( !doCheck( m, q, children[i], n[i] ) ){\r
+        bchildren[i] = -1;\r
+        incomplete = true;\r
+      }\r
+    }\r
+  }\r
+  //convert to pointers\r
+  std::map< unsigned, AbsDef * > pchildren;\r
+  for( std::map< unsigned, AbsDef >::iterator it = children.begin(); it != children.end(); ++it ){\r
+    pchildren[it->first] = &it->second;\r
+  }\r
+  //construct the interpretation\r
+  Trace("ambqi-check-debug") << "Compute Interpretation of " << n << " " << n.getKind() << std::endl;\r
+  if( n.getKind() == APPLY_UF || n.getKind() == VARIABLE || n.getKind() == SKOLEM ){\r
+    Node op;\r
+    if( n.getKind() == APPLY_UF ){\r
+      op = n.getOperator();\r
+    }else{\r
+      op = n;\r
+    }\r
+    //uninterpreted compose\r
+    if( m->d_models_valid[op] ){\r
+      ad.construct( m, q, n, m->d_models[op], pchildren, bchildren, vchildren, varChCount, incomplete );\r
+    }else{\r
+      Trace("ambqi-check-debug") << "** Cannot produce interpretation for " << n << " (no function model)" << std::endl;\r
+      return false;\r
+    }\r
+  }else if( !ad.construct( m, q, n, NULL, pchildren, bchildren, vchildren, varChCount, incomplete ) ){\r
+    Trace("ambqi-check-debug") << "** Cannot produce interpretation for " << n << " (variables are children of interpreted symbol)" << std::endl;\r
+    return false;\r
+  }\r
+  Trace("ambqi-check-debug2") << "Interpretation for " << n << " is : " << std::endl;\r
+  ad.debugPrint("ambqi-check-debug2", m, q[0] );\r
+  ad.simplify( m, q );\r
+  Trace("ambqi-check-debug") << "(Simplified) Interpretation for " << n << " is : " << std::endl;\r
+  ad.debugPrint("ambqi-check-debug", m, q[0] );\r
+  Trace("ambqi-check-debug") << std::endl;\r
+  return true;\r
+}\r
diff --git a/src/theory/quantifiers/ambqi_builder.h b/src/theory/quantifiers/ambqi_builder.h
new file mode 100755 (executable)
index 0000000..d0818a7
--- /dev/null
@@ -0,0 +1,90 @@
+/*********************                                                        */\r
+/*! \file ambqi_builder.h\r
+ ** \verbatim\r
+ ** Original author: Andrew Reynolds\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 project.\r
+ ** Copyright (c) 2009-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 Abstract MBQI model builder class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef ABSTRACT_MBQI_BUILDER\r
+#define ABSTRACT_MBQI_BUILDER\r
+\r
+#include "theory/quantifiers/model_builder.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+class FirstOrderModelAbs;\r
+\r
+//representiation of function and term interpretations\r
+class AbsDef\r
+{\r
+private:\r
+  int addInstantiations( FirstOrderModelAbs * m, QuantifiersEngine * qe, Node q, std::vector< Node >& terms, unsigned depth );\r
+  void construct_compose( FirstOrderModelAbs * m, Node q, Node n, AbsDef * f,\r
+                          std::map< unsigned, AbsDef * >& children,\r
+                          std::map< unsigned, int >& bchildren, std::map< unsigned, int >& vchildren,\r
+                          std::vector< unsigned >& entry, std::vector< bool >& entry_def,\r
+                          bool incomplete );\r
+  void construct_entry( std::vector< unsigned >& entry, std::vector< bool >& entry_def, int v, unsigned depth = 0 );\r
+  void construct_def_entry( FirstOrderModelAbs * m, Node q, int v, unsigned depth = 0 );\r
+  void apply_ucompose( std::vector< unsigned >& entry, std::vector< bool >& entry_def, std::vector< int >& terms,\r
+                       std::map< unsigned, int >& vchildren, AbsDef * a, unsigned depth = 0 );\r
+  void construct_var_eq( FirstOrderModelAbs * m, Node q, unsigned v1, unsigned v2, int curr, int currv, unsigned depth = 0 );\r
+  void construct_var( FirstOrderModelAbs * m, Node q, unsigned v, int currv, unsigned depth = 0 );\r
+public:\r
+  AbsDef() : d_value( -1 ){}\r
+  std::map< unsigned, AbsDef > d_def;\r
+  unsigned d_default;\r
+  int d_value;\r
+\r
+  AbsDef * getDefault() { return &d_def[d_default]; }\r
+  void construct_func( FirstOrderModelAbs * m, std::vector< TNode >& fapps, unsigned depth = 0 );\r
+  void debugPrintUInt( const char * c, unsigned dSize, unsigned u );\r
+  void debugPrint( const char * c, FirstOrderModelAbs * m, Node f, unsigned depth = 0 );\r
+  void simplify( FirstOrderModelAbs * m, Node q, unsigned depth = 0 );\r
+  int addInstantiations( FirstOrderModelAbs * m, QuantifiersEngine * qe, Node q ){\r
+    std::vector< Node > terms;\r
+    return addInstantiations( m, qe, q, terms, 0 );\r
+  }\r
+  bool construct( FirstOrderModelAbs * m, Node q, Node n, AbsDef * f,\r
+                  std::map< unsigned, AbsDef * >& children,\r
+                  std::map< unsigned, int >& bchildren,\r
+                  std::map< unsigned, int >& vchildren,\r
+                  int varChCount, bool incomplete );\r
+  Node getFunctionValue( FirstOrderModelAbs * m, TNode op, std::vector< Node >& vars, unsigned depth = 0 );\r
+  static unsigned getId( unsigned n );\r
+  Node evaluate( FirstOrderModelAbs * m, TypeNode retType, std::vector< Node >& args );\r
+  Node evaluate( FirstOrderModelAbs * m, TypeNode retType, std::vector< unsigned >& iargs, unsigned depth = 0 );\r
+};\r
+\r
+class AbsMbqiBuilder : public QModelBuilder\r
+{\r
+  friend class AbsDef;\r
+private:\r
+  Node d_true;\r
+  Node d_false;\r
+  bool doCheck( FirstOrderModelAbs * m, TNode q, AbsDef & ad, TNode n );\r
+public:\r
+  AbsMbqiBuilder( context::Context* c, QuantifiersEngine* qe );\r
+  //process build model\r
+  void processBuildModel(TheoryModel* m, bool fullModel);\r
+  //do exhaustive instantiation\r
+  bool doExhaustiveInstantiation( FirstOrderModel * fm, Node q, int effort );\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
index 509c00bb60383d83f32f7578b69f86304c3f5c0e..0b2fae5d4291ac5cf975bacd1e32c680a88bb474 100644 (file)
@@ -18,6 +18,7 @@
 #include "theory/quantifiers/quantifiers_attributes.h"
 #include "theory/quantifiers/full_model_check.h"
 #include "theory/quantifiers/qinterval_builder.h"
+#include "theory/quantifiers/ambqi_builder.h"
 #include "theory/quantifiers/options.h"
 
 #define USE_INDEX_ORDERING
@@ -882,3 +883,101 @@ bool FirstOrderModelQInt::doMeet( Node l1, Node u1, Node l2, Node u2, Node& lr,
   //return lr==ur || lr.isNull() || isLessThan( lr, ur );
   return lr.isNull() || isLessThan( lr, ur );
 }
+
+
+
+
+FirstOrderModelAbs::FirstOrderModelAbs(QuantifiersEngine * qe, context::Context* c, std::string name) :
+FirstOrderModel(qe, c, name) {
+
+}
+
+void FirstOrderModelAbs::processInitialize( bool ispre ) {
+  if( !ispre ){
+    Trace("ambqi-debug") << "Process initialize" << std::endl;
+    for( std::map<Node, AbsDef * >::iterator it = d_models.begin(); it != d_models.end(); ++it ) {
+      Node op = it->first;
+      TypeNode tno = op.getType();
+      Trace("ambqi-debug") << "  Init " << op << " " << tno << std::endl;
+      for( unsigned i=0; i<tno.getNumChildren(); i++) {
+        //make sure a representative of the type exists
+        if( !d_rep_set.hasType( tno[i] ) ){
+          Node e = getSomeDomainElement( tno[i] );
+          Trace("ambqi-debug") << "  * Initialize type " << tno[i] << ", add ";
+          Trace("ambqi-debug") << e << " " << e.getType() << std::endl;
+          //d_rep_set.add( e );
+        }
+      }
+    }
+  }
+}
+
+unsigned FirstOrderModelAbs::getRepresentativeId( TNode n ) {
+  TNode r = getUsedRepresentative( n );
+  std::map< TNode, unsigned >::iterator it = d_rep_id.find( r );
+  if( it!=d_rep_id.end() ){
+    return it->second;
+  }else{
+    return 0;
+  }
+}
+
+TNode FirstOrderModelAbs::getUsedRepresentative( TNode n ) {
+  if( hasTerm( n ) ){
+    if( n.getType().isBoolean() ){
+      return areEqual(n, d_true) ? d_true : d_false;
+    }else{
+      return getRepresentative( n );
+    }
+  }else{
+    Trace("qint-debug") << "Get rep " << n << " " << n.getType() << std::endl;
+    Assert( d_rep_set.hasType( n.getType() ) && !d_rep_set.d_type_reps[n.getType()].empty() );
+    return d_rep_set.d_type_reps[n.getType()][0];
+  }
+}
+
+Node FirstOrderModelAbs::getFunctionValue(Node op, const char* argPrefix ) {
+  if( d_models_valid[op] ){
+    Trace("ambqi-debug") << "Get function value for " << op << std::endl;
+    TypeNode type = op.getType();
+    std::vector< Node > vars;
+    for( size_t i=0; i<type.getNumChildren()-1; i++ ){
+      std::stringstream ss;
+      ss << argPrefix << (i+1);
+      Node b = NodeManager::currentNM()->mkBoundVar( ss.str(), type[i] );
+      vars.push_back( b );
+    }
+    Node boundVarList = NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST, vars);
+    Node curr = d_models[op]->getFunctionValue( this, op, vars );
+    Node fv = NodeManager::currentNM()->mkNode(kind::LAMBDA, boundVarList, curr);
+    Trace("ambqi-debug") << "Return " << fv << std::endl;
+    return fv;
+  }else{
+
+  }
+  return Node::null();
+}
+
+Node FirstOrderModelAbs::getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial ) {
+  Debug("qint-debug") << "get curr uf value " << n << std::endl;
+  if( d_models_valid[n] ){
+    TypeNode tn = n.getType();
+    if( tn.getNumChildren()>0 ){
+      tn = tn[tn.getNumChildren()-1];
+    }
+    return d_models[n]->evaluate( this, tn, args );
+  }else{
+    return Node::null();
+  }
+}
+
+void FirstOrderModelAbs::processInitializeModelForTerm( Node n ) {
+  if( n.getKind()==APPLY_UF || n.getKind()==VARIABLE || n.getKind()==SKOLEM ){
+    Node op = n.getKind()==APPLY_UF ? n.getOperator() : n;
+    if( d_models.find(op)==d_models.end()) {
+      Trace("abmqi-debug") << "init model for " << op << std::endl;
+      d_models[op] = new AbsDef;
+      d_models_valid[op] = false;
+    }
+  }
+}
index 63d8ffcce23f6a600c8f25a580c4a5347ab60f0d..d799cfad301cb30c654051bb1ba3fc2a89be64a6 100644 (file)
@@ -37,6 +37,7 @@ namespace fmcheck {
 }/* CVC4::theory::quantifiers::fmcheck namespace */
 
 class FirstOrderModelQInt;
+class FirstOrderModelAbs;
 
 struct IsStarAttributeId {};
 typedef expr::Attribute<IsStarAttributeId, bool> IsStarAttribute;
@@ -75,6 +76,7 @@ public:
   virtual FirstOrderModelIG * asFirstOrderModelIG() { return NULL; }
   virtual fmcheck::FirstOrderModelFmc * asFirstOrderModelFmc() { return NULL; }
   virtual FirstOrderModelQInt * asFirstOrderModelQInt() { return NULL; }
+  virtual FirstOrderModelAbs * asFirstOrderModelAbs() { return NULL; }
   // initialize the model
   void initialize( bool considerAxioms = true );
   virtual void processInitialize( bool ispre ) = 0;
@@ -220,6 +222,27 @@ public:
   int getOrderedVarNumToVarNum( Node q, int i );
 };/* class FirstOrderModelQInt */
 
+class AbsDef;
+
+class FirstOrderModelAbs : public FirstOrderModel
+{
+public:
+  std::map< Node, AbsDef * > d_models;
+  std::map< Node, bool > d_models_valid;
+  std::map< TNode, unsigned > d_rep_id;
+  std::map< TypeNode, unsigned > d_domain;
+  /** get current model value */
+  Node getCurrentUfModelValue( Node n, std::vector< Node > & args, bool partial );
+  void processInitializeModelForTerm(Node n);
+public:
+  FirstOrderModelAbs(QuantifiersEngine * qe, context::Context* c, std::string name);
+  FirstOrderModelAbs * asFirstOrderModelAbs() { return this; }
+  void processInitialize( bool ispre );
+  unsigned getRepresentativeId( TNode n );
+  TNode getUsedRepresentative( TNode n );
+  bool isValidType( TypeNode tn ) { return d_domain.find( tn )!=d_domain.end(); }
+  Node getFunctionValue(Node op, const char* argPrefix );
+};
 
 }/* CVC4::theory::quantifiers namespace */
 }/* CVC4::theory namespace */
index 3a4879b427405387a180719df3bc1170843924dc..dfbc0141441403622a9271a99421884a15f6e564 100644 (file)
@@ -23,6 +23,7 @@
 #include "theory/quantifiers/quantifiers_attributes.h"
 #include "theory/quantifiers/full_model_check.h"
 #include "theory/quantifiers/qinterval_builder.h"
+#include "theory/quantifiers/ambqi_builder.h"
 
 using namespace std;
 using namespace CVC4;
@@ -44,6 +45,9 @@ QuantifiersModule( qe ){
   }else if( options::mbqiMode()==MBQI_INTERVAL ){
     Trace("model-engine-debug") << "...make interval builder." << std::endl;
     d_builder = new QIntervalBuilder( c, qe );
+  }else if( options::mbqiMode()==MBQI_ABS ){
+    Trace("model-engine-debug") << "...make abs mbqi builder." << std::endl;
+    d_builder = new AbsMbqiBuilder( c, qe );
   }else if( options::mbqiMode()==MBQI_INST_GEN ){
     Trace("model-engine-debug") << "...make inst-gen builder." << std::endl;
     d_builder = new QModelBuilderInstGen( c, qe );
index 8bd97a8a74805ad8e1f6677e99f4dd13e793f092..b247211703f9c7d5915234e3fd0af5f42981e90c 100644 (file)
@@ -94,6 +94,9 @@ std::ostream& operator<<(std::ostream& out, theory::quantifiers::MbqiMode mode)
   case theory::quantifiers::MBQI_INTERVAL:
     out << "MBQI_INTERVAL";
     break;
+  case theory::quantifiers::MBQI_ABS:
+    out << "MBQI_ABS";
+    break;
   case theory::quantifiers::MBQI_TRUST:
     out << "MBQI_TRUST";
     break;
index 80534c8b053960d9464b9aaa95bccdb9b7b9de2c..230495f1fcf209cb7d8f3e390aa020e1a8052b89 100644 (file)
@@ -70,6 +70,8 @@ typedef enum {
   MBQI_FMC_INTERVAL,
   /** mbqi with interval abstraction of uninterpreted sorts */
   MBQI_INTERVAL,
+  /** abstract mbqi algorithm */
+  MBQI_ABS,
   /** mbqi trust (produce no instantiations) */
   MBQI_TRUST,
 } MbqiMode;
index b7e624a66c4eb8bc61973bf806db62488aa89d69..c0b76bcec6d6a60ff735ba5d5af6f8e598bd3196 100644 (file)
@@ -101,6 +101,9 @@ fmc-interval \n\
 interval \n\
 + Use algorithm that abstracts domain elements as intervals. \n\
 \n\
+abs \n\
++ Use abstract MBQI algorithm (uses disjoint sets). \n\
+\n\
 ";
 static const std::string qcfWhenModeHelp = "\
 Quantifier conflict find modes currently supported by the --quant-cf-when option:\n\
@@ -226,6 +229,8 @@ inline MbqiMode stringToMbqiMode(std::string option, std::string optarg, SmtEngi
     return MBQI_FMC_INTERVAL;
   } else if(optarg == "interval") {
     return MBQI_INTERVAL;
+  } else if(optarg == "abs") {
+    return MBQI_ABS;
   } else if(optarg == "trust") {
     return MBQI_TRUST;
   } else if(optarg == "help") {
index b79c0da699eae17d6288818f38f4a59c9d7fa7db..929a638d7a57d53dc61eba789583770484b8cd49 100644 (file)
@@ -60,6 +60,8 @@ d_lemmas_produced_c(u){
     d_model = new quantifiers::fmcheck::FirstOrderModelFmc( this, c, "FirstOrderModelFmc" );
   }else if( options::mbqiMode()==quantifiers::MBQI_INTERVAL ){
     d_model = new quantifiers::FirstOrderModelQInt( this, c, "FirstOrderModelQInt" );
+  }else if( options::mbqiMode()==quantifiers::MBQI_ABS ){
+    d_model = new quantifiers::FirstOrderModelAbs( this, c, "FirstOrderModelAbs" );
   }else{
     d_model = new quantifiers::FirstOrderModelIG( this, c, "FirstOrderModelIG" );
   }