예제 #1
0
/** pre register quantifier */
void QuantDSplit::preRegisterQuantifier( Node q ) {
  int max_index = -1;
  int max_score = -1;
  if( q.getNumChildren()==3 ){
    return;
  }
  Trace("quant-dsplit-debug") << "Check split quantified formula : " << q << std::endl;
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
    TypeNode tn = q[0][i].getType();
    if( tn.isDatatype() ){
      const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
      if( dt.isRecursiveSingleton() ){
        Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is recursive singleton." << std::endl;
      }else{
        int score = -1;
        if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_AGG ){
          score = dt.isUFinite() ? 1 : -1;
        }else if( options::quantDynamicSplit()==quantifiers::QUANT_DSPLIT_MODE_DEFAULT ){
          score = dt.isUFinite() ? 1 : -1;
        }
        Trace("quant-dsplit-debug") << "Datatype " << dt.getName() << " is score " << score << " (" << dt.isUFinite() << " " << dt.isFinite() << ")" << std::endl;
        if( score>max_score ){
          max_index = i;
          max_score = score;
        }
      }
    }
  }

  if( max_index!=-1 ){
    Trace("quant-dsplit-debug") << "Will split at index " << max_index << "." << std::endl;
    d_quant_to_reduce[q] = max_index;
    d_quantEngine->setOwner( q, this );
  }
}
예제 #2
0
/* Call during quantifier engine's check */
void QuantDSplit::check( Theory::Effort e, unsigned quant_e ) {
  //add lemmas ASAP (they are a reduction)
  if( quant_e==QuantifiersEngine::QEFFORT_CONFLICT ){
    std::vector< Node > lemmas;
    for(std::map< Node, int >::iterator it = d_quant_to_reduce.begin(); it != d_quant_to_reduce.end(); ++it) {
      Node q = it->first;
      if( d_added_split.find( q )==d_added_split.end() ){
        d_added_split.insert( q );
        std::vector< Node > bvs;
        for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
          if( (int)i!=it->second ){
            bvs.push_back( q[0][i] );
          }
        }
        std::vector< Node > disj;
        disj.push_back( q.negate() );
        TNode svar = q[0][it->second];
        TypeNode tn = svar.getType();
        if( tn.isDatatype() ){
          std::vector< Node > cons;
          const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
          for( unsigned j=0; j<dt.getNumConstructors(); j++ ){
            std::vector< Node > vars;
            for( unsigned k=0; k<dt[j].getNumArgs(); k++ ){
              TypeNode tns = TypeNode::fromType( dt[j][k].getRangeType() );
              Node v = NodeManager::currentNM()->mkBoundVar( tns );
              vars.push_back( v );
            }
            std::vector< Node > bvs_cmb;
            bvs_cmb.insert( bvs_cmb.end(), bvs.begin(), bvs.end() );
            bvs_cmb.insert( bvs_cmb.end(), vars.begin(), vars.end() );
            vars.insert( vars.begin(), Node::fromExpr( dt[j].getConstructor() ) );
            Node c = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, vars );
            TNode ct = c;
            Node body = q[1].substitute( svar, ct );
            if( !bvs_cmb.empty() ){
              body = NodeManager::currentNM()->mkNode( kind::FORALL, NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST, bvs_cmb ), body );
            }
            cons.push_back( body );
          }
          Node conc = cons.size()==1 ? cons[0] : NodeManager::currentNM()->mkNode( kind::AND, cons );
          disj.push_back( conc );
        }else{
          Assert( false );
        }
        lemmas.push_back( disj.size()==1 ? disj[0] : NodeManager::currentNM()->mkNode( kind::OR, disj ) );
      }
    }

    //add lemmas to quantifiers engine
    for( unsigned i=0; i<lemmas.size(); i++ ){
      Trace("quant-dsplit") << "QuantDSplit lemma : " << lemmas[i] << std::endl;
      d_quantEngine->addLemma( lemmas[i], false );
    }
    d_quant_to_reduce.clear();
  }
}
예제 #3
0
Node ModelPostprocessor::rewriteAs(TNode n, TypeNode asType) {
  if(n.getType().isSubtypeOf(asType)) {
    // good to go, we have the right type
    return n;
  }
  if(!n.isConst()) {
    // we don't handle non-const right now
    return n;
  }
  if(asType.isBoolean()) {
    if(n.getType().isBitVector(1u)) {
      // type mismatch: should only happen for Boolean-term conversion under
      // datatype constructor applications; rewrite from BV(1) back to Boolean
      bool tf = (n.getConst<BitVector>().getValue() == 1);
      return NodeManager::currentNM()->mkConst(tf);
    }
    if(n.getType().isDatatype() && n.getType().hasAttribute(BooleanTermAttr())) {
      // type mismatch: should only happen for Boolean-term conversion under
      // datatype constructor applications; rewrite from datatype back to Boolean
      Assert(n.getKind() == kind::APPLY_CONSTRUCTOR);
      Assert(n.getNumChildren() == 0);
      // we assume (by construction) false is first; see boolean_terms.cpp
      bool tf = (Datatype::indexOf(n.getOperator().toExpr()) == 1);
      Debug("boolean-terms") << "+++ rewriteAs " << n << " : " << asType << " ==> " << tf << endl;
      return NodeManager::currentNM()->mkConst(tf);
    }
  }
  if(n.getType().isBoolean()) {
    bool tf = n.getConst<bool>();
    if(asType.isBitVector(1u)) {
      return NodeManager::currentNM()->mkConst(BitVector(1u, tf ? 1u : 0u));
    }
    if(asType.isDatatype() && asType.hasAttribute(BooleanTermAttr())) {
      const Datatype& asDatatype = asType.getConst<Datatype>();
      return NodeManager::currentNM()->mkNode(kind::APPLY_CONSTRUCTOR, (tf ? asDatatype[0] : asDatatype[1]).getConstructor());
    }
  }
  if(n.getType().isRecord() && asType.isRecord()) {
    Debug("boolean-terms") << "+++ got a record - rewriteAs " << n << " : " << asType << endl;
    const Record& rec CVC4_UNUSED = n.getType().getConst<Record>();
    const Record& asRec = asType.getConst<Record>();
    Assert(rec.getNumFields() == asRec.getNumFields());
    Assert(n.getNumChildren() == asRec.getNumFields());
    NodeBuilder<> b(n.getKind());
    b << asType;
    for(size_t i = 0; i < n.getNumChildren(); ++i) {
      b << rewriteAs(n[i], TypeNode::fromType(asRec[i].second));
    }
    Node out = b;
    Debug("boolean-terms") << "+++ returning record " << out << endl;
    return out;
  }
예제 #4
0
void SygusRedundantCons::initialize(QuantifiersEngine* qe, TypeNode tn)
{
  Assert(qe != nullptr);
  Trace("sygus-red") << "Compute redundant cons for " << tn << std::endl;
  d_type = tn;
  Assert(tn.isDatatype());
  TermDbSygus* tds = qe->getTermDatabaseSygus();
  tds->registerSygusType(tn);
  const Datatype& dt = static_cast<DatatypeType>(tn.toType()).getDatatype();
  Assert(dt.isSygus());
  TypeNode btn = TypeNode::fromType(dt.getSygusType());
  for (unsigned i = 0, ncons = dt.getNumConstructors(); i < ncons; i++)
  {
    Trace("sygus-red") << "  Is " << dt[i].getName() << " a redundant operator?"
                       << std::endl;
    std::map<int, Node> pre;
    Node g = tds->mkGeneric(dt, i, pre);
    Trace("sygus-red-debug") << "  ...pre-rewrite : " << g << std::endl;
    Assert(g.getNumChildren() == dt[i].getNumArgs());
    d_gen_terms[i] = g;
    for (unsigned j = 0, nargs = dt[i].getNumArgs(); j < nargs; j++)
    {
      pre[j] = g[j];
    }
    std::vector<Node> glist;
    getGenericList(tds, dt, i, 0, pre, glist);
    // call the extended rewriter
    bool red = false;
    for (const Node& gr : glist)
    {
      Trace("sygus-red-debug") << "  ...variant : " << gr << std::endl;
      std::map<Node, unsigned>::iterator itg = d_gen_cons.find(gr);
      if (itg != d_gen_cons.end() && itg->second != i)
      {
        red = true;
        Trace("sygus-red") << "  ......redundant, since a variant of " << g
                           << " and " << d_gen_terms[itg->second]
                           << " both rewrite to " << gr << std::endl;
        break;
      }
      else
      {
        d_gen_cons[gr] = i;
        Trace("sygus-red") << "  ......not redundant." << std::endl;
      }
    }
    d_sygus_red_status.push_back(red ? 1 : 0);
  }
}
예제 #5
0
bool InstStrategyCbqi::hasNonCbqiVariable( Node q ){
  for( unsigned i=0; i<q[0].getNumChildren(); i++ ){
    TypeNode tn = q[0][i].getType();
    if( !tn.isInteger() && !tn.isReal() && !tn.isBoolean() ){
      if( options::cbqiSplx() ){
        return true;
      }else{
        //datatypes supported in new implementation
        if( !tn.isDatatype() ){
          return true;
        }
      }
    }
  }
  return false;
}
예제 #6
0
bool TermEnumeration::isClosedEnumerableType(TypeNode tn)
{
  std::unordered_map<TypeNode, bool, TypeNodeHashFunction>::iterator it =
      d_typ_closed_enum.find(tn);
  if (it == d_typ_closed_enum.end())
  {
    d_typ_closed_enum[tn] = true;
    bool ret = true;
    if (tn.isArray() || tn.isSort() || tn.isCodatatype() || tn.isFunction())
    {
      ret = false;
    }
    else if (tn.isSet())
    {
      ret = isClosedEnumerableType(tn.getSetElementType());
    }
    else if (tn.isDatatype())
    {
      const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
      for (unsigned i = 0; i < dt.getNumConstructors(); i++)
      {
        for (unsigned j = 0; j < dt[i].getNumArgs(); j++)
        {
          TypeNode ctn = TypeNode::fromType(dt[i][j].getRangeType());
          if (tn != ctn && !isClosedEnumerableType(ctn))
          {
            ret = false;
            break;
          }
        }
        if (!ret)
        {
          break;
        }
      }
    }
    
    // other parametric sorts go here
    
    d_typ_closed_enum[tn] = ret;
    return ret;
  }
  else
  {
    return it->second;
  }
}
예제 #7
0
Node DatatypesEnumerator::getTermEnum( TypeNode tn, unsigned i ){
   Node ret;
   if( i<d_terms[tn].size() ){
     ret = d_terms[tn][i];
   }else{
     Debug("dt-enum-debug") << "get term enum " << tn << " " << i << std::endl;
     std::map< TypeNode, unsigned >::iterator it = d_te_index.find( tn );
     unsigned tei;
     if( it==d_te_index.end() ){
       //initialize child enumerator for type
       tei = d_children.size();
       d_te_index[tn] = tei;
       if( tn.isDatatype() && d_has_debruijn ){
         //must indicate that this is a child enumerator (do not normalize constants for it)
         DatatypesEnumerator * dte = new DatatypesEnumerator( tn, true );
         d_children.push_back( TypeEnumerator( dte ) );
       }else{
         d_children.push_back( TypeEnumerator( tn ) );
       }
       d_terms[tn].push_back( *d_children[tei] );
     }else{
       tei = it->second;
     }
     //enumerate terms until index is reached
     while( i>=d_terms[tn].size() ){
       ++d_children[tei];
       if( d_children[tei].isFinished() ){
         Debug("dt-enum-debug") << "...fail term enum " << tn << " " << i << std::endl;
         return Node::null();
       }
       d_terms[tn].push_back( *d_children[tei] );
     }
     Debug("dt-enum-debug") << "...return term enum " << tn << " " << i << " : " << d_terms[tn][i] << std::endl;
     ret = d_terms[tn][i];
   }
   return ret;
 }