Example #1
0
bool InequalitySolver::isInequalityOnly(TNode node) {
  if (node.getKind() == kind::NOT) {
    node = node[0];
  }

  if (node.getAttribute(IneqOnlyComputedAttribute())) {
    return node.getAttribute(IneqOnlyAttribute());
  }

  if (node.getKind() != kind::EQUAL &&
      node.getKind() != kind::BITVECTOR_ULT &&
      node.getKind() != kind::BITVECTOR_ULE &&
      node.getKind() != kind::CONST_BITVECTOR &&
      node.getKind() != kind::SELECT &&
      node.getKind() != kind::STORE &&
      node.getMetaKind() != kind::metakind::VARIABLE) {
    // not worth caching
    return false;
  }
  bool res = true;
  for (unsigned i = 0; res && i < node.getNumChildren(); ++i) {
    res = res && isInequalityOnly(node[i]);
  }
  node.setAttribute(IneqOnlyComputedAttribute(), true);
  node.setAttribute(IneqOnlyAttribute(), res);
  return res;
}
RewriteResponse QuantifiersRewriter::postRewrite(TNode in) {
  Trace("quantifiers-rewrite-debug") << "post-rewriting " << in << " " << in.hasAttribute(NestedQuantAttribute()) << std::endl;
  if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){
    RewriteStatus status = REWRITE_DONE;
    Node ret = in;
    //get the arguments
    std::vector< Node > args;
    for( int i=0; i<(int)in[0].getNumChildren(); i++ ){
      args.push_back( in[0][i] );
    }
    //get the instantiation pattern list
    Node ipl;
    if( in.getNumChildren()==3 ){
      ipl = in[2];
    }
    //get the body
    if( in.getKind()==EXISTS ){
      std::vector< Node > children;
      children.push_back( in[0] );
      children.push_back( in[1].negate() );
      if( in.getNumChildren()==3 ){
        children.push_back( in[2] );
      }
      ret = NodeManager::currentNM()->mkNode( FORALL, children );
      ret = ret.negate();
      status = REWRITE_AGAIN_FULL;
    }else{
      bool isNested = in.hasAttribute(NestedQuantAttribute());
      for( int op=0; op<COMPUTE_LAST; op++ ){
        if( doOperation( in, isNested, op ) ){
          ret = computeOperation( in, op );
          if( ret!=in ){
            status = REWRITE_AGAIN_FULL;
            break;
          }
        }
      }
    }
    //print if changed
    if( in!=ret ){
      if( in.hasAttribute(NestedQuantAttribute()) ){
        setNestedQuantifiers( ret, in.getAttribute(NestedQuantAttribute()) );
      }
      Trace("quantifiers-rewrite") << "*** rewrite " << in << std::endl;
      Trace("quantifiers-rewrite") << " to " << std::endl;
      Trace("quantifiers-rewrite") << ret << std::endl;
    }
    return RewriteResponse( status, ret );
  }
  return RewriteResponse(REWRITE_DONE, in);
}
Example #3
0
void TheoryUFTim::merge() {
  while(d_currentPendingIdx < d_pending.size() ) {
    Node assertion = d_pending[d_currentPendingIdx];
    d_currentPendingIdx = d_currentPendingIdx + 1;

    TNode x = assertion[0];
    TNode y = assertion[1];

    ECData* tmpX = x.getAttribute(ECAttr());
    ECData* tmpY = y.getAttribute(ECAttr());

    ECData* ecX = ccFind(tmpX);
    ECData* ecY = ccFind(tmpY);
    if(ecX == ecY)
      continue;

    Debug("uf") << "merging equivalence classes for " << std::endl;
    Debug("uf") << "left equivalence class :" << (ecX->getRep()) << std::endl;
    Debug("uf") << "right equivalence class :" << (ecY->getRep()) << std::endl;
    Debug("uf") << std::endl;

    ccUnion(ecX, ecY);
  }
}
RewriteResponse QuantifiersRewriter::preRewrite(TNode in) {
  Trace("quantifiers-rewrite-debug") << "pre-rewriting " << in << " " << in.hasAttribute(NestedQuantAttribute()) << std::endl;
  if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){
    if( !in.hasAttribute(NestedQuantAttribute()) ){
      setNestedQuantifiers( in[ 1 ], in );
    }
    std::vector< Node > args;
    for( int i=0; i<(int)in[0].getNumChildren(); i++ ){
      args.push_back( in[0][i] );
    }
    Node body = in[1];
    bool doRewrite = false;
    while( body.getNumChildren()>=2 && body.getKind()==in.getKind() ){
      for( int i=0; i<(int)body[0].getNumChildren(); i++ ){
        args.push_back( body[0][i] );
      }
      body = body[1];
      doRewrite = true;
    }
    if( doRewrite ){
      std::vector< Node > children;
      children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) );
      children.push_back( body );
      if( in.getNumChildren()==3 ){
        children.push_back( in[2] );
      }
      Node n = NodeManager::currentNM()->mkNode( in.getKind(), children );
      if( in!=n ){
        if( in.hasAttribute(NestedQuantAttribute()) ){
          setNestedQuantifiers( n, in.getAttribute(NestedQuantAttribute()) );
        }
        Trace("quantifiers-pre-rewrite") << "*** pre-rewrite " << in << std::endl;
        Trace("quantifiers-pre-rewrite") << " to " << std::endl;
        Trace("quantifiers-pre-rewrite") << n << std::endl;
      }
      return RewriteResponse(REWRITE_DONE, n);
    }
  }
  return RewriteResponse(REWRITE_DONE, in);
}
Example #5
0
void TheoryUFTim::registerTerm(TNode n) {

  Debug("uf") << "uf: begin registerTerm(" << n << ")" << std::endl;

  d_registered.push_back(n);

  ECData* ecN;

  if(n.getAttribute(ECAttr(), ecN)) {
    /* registerTerm(n) is only called when a node has not been seen in the
     * current context.  ECAttr() is not a context-dependent attribute.
     * When n.hasAttribute(ECAttr(),...) is true on a registerTerm(n) call,
     * then it must be the case that this attribute was created in a previous
     * and no longer valid context. Because of this we have to reregister the
     * predecessors lists.
     * Also we do not have to worry about duplicates because all of the Link*
     * setup before are removed when the context n was setup in was popped out
     * of. All we are going to do here are sanity checks.
     */

    /*
     * Consider the following chain of events:
     * 1) registerTerm(n) is called on node n where n : f(m) in context level X,
     * 2) A new ECData is created on the heap, ecN,
     * 3) n is added to the predessecor list of m in context level X,
     * 4) We pop out of X,
     * 5) n is removed from the predessecor list of m because this is context
     *    dependent, the Link* will be destroyed and pointers to the Link
     *    structs in the ECData objects will be updated.
     * 6) registerTerm(n) is called on node n in context level Y,
     * 7) If n.hasAttribute(ECAttr(), &ecN), then ecN is still around,
     *    but the predecessor list is not
     *
     * The above assumes that the code is working correctly.
     */
    Assert(ecN->getFirst() == NULL,
           "Equivalence class data exists for the node being registered.  "
           "Expected getFirst() == NULL.  "
           "This data is either already in use or was not properly maintained "
           "during backtracking");
    /*Assert(ecN->getLast() == NULL,
           "Equivalence class data exists for the node being registered.  "
           "Expected getLast() == NULL.  "
           "This data is either already in use or was not properly maintained "
           "during backtracking.");*/
    Assert(ecN->isClassRep(),
           "Equivalence class data exists for the node being registered.  "
           "Expected isClassRep() to be true.  "
           "This data is either already in use or was not properly maintained "
           "during backtracking");
    Assert(ecN->getWatchListSize() == 0,
           "Equivalence class data exists for the node being registered.  "
           "Expected getWatchListSize() == 0.  "
           "This data is either already in use or was not properly maintained "
           "during backtracking");
  } else {
    //The attribute does not exist, so it is created and set
    ecN = new (true) ECData(getContext(), n);
    n.setAttribute(ECAttr(), ecN);
  }

  /* If the node is an APPLY_UF, we need to add it to the predecessor list
   * of its children.
   */
  if(n.getKind() == APPLY_UF) {
    TNode::iterator cIter = n.begin();

    for(; cIter != n.end(); ++cIter) {
      TNode child = *cIter;

      /* Because this can be called after nodes have been merged, we need
       * to lookup the representative in the UnionFind datastructure.
       */
      ECData* ecChild = ccFind(child.getAttribute(ECAttr()));

      /* Because this can be called after nodes have been merged we may need
       * to be merged with other predecessors of the equivalence class.
       */
      for(Link* Px = ecChild->getFirst(); Px != NULL; Px = Px->d_next ) {
        if(equiv(n, Px->d_data)) {
          Node pend = n.eqNode(Px->d_data);
          d_pending.push_back(pend);
        }
      }

      ecChild->addPredecessor(n);
    }
  }
  Debug("uf") << "uf: end registerTerm(" << n << ")" << std::endl;

}
Example #6
0
bool TheoryUFTim::sameCongruenceClass(TNode x, TNode y) {
  return
    ccFind(x.getAttribute(ECAttr())) ==
    ccFind(y.getAttribute(ECAttr()));
}
Example #7
0
PreprocessingPassResult SynthRewRulesPass::applyInternal(
    AssertionPipeline* assertionsToPreprocess)
{
  Trace("synth-rr-pass") << "Synthesize rewrite rules from assertions..."
                         << std::endl;
  std::vector<Node>& assertions = assertionsToPreprocess->ref();

  // compute the variables we will be sampling
  std::vector<Node> vars;
  unsigned nsamples = options::sygusSamples();

  Options& nodeManagerOptions = NodeManager::currentNM()->getOptions();

  // attribute to mark processed terms
  SynthRrComputedAttribute srrca;

  // initialize the candidate rewrite
  std::unique_ptr<theory::quantifiers::CandidateRewriteDatabaseGen> crdg;
  std::unordered_map<TNode, bool, TNodeHashFunction> visited;
  std::unordered_map<TNode, bool, TNodeHashFunction>::iterator it;
  std::vector<TNode> visit;
  // two passes: the first collects the variables, the second registers the
  // terms
  for (unsigned r = 0; r < 2; r++)
  {
    visited.clear();
    visit.clear();
    TNode cur;
    for (const Node& a : assertions)
    {
      visit.push_back(a);
      do
      {
        cur = visit.back();
        visit.pop_back();
        it = visited.find(cur);
        // if already processed, ignore
        if (cur.getAttribute(SynthRrComputedAttribute()))
        {
          Trace("synth-rr-pass-debug")
              << "...already processed " << cur << std::endl;
        }
        else if (it == visited.end())
        {
          Trace("synth-rr-pass-debug") << "...preprocess " << cur << std::endl;
          visited[cur] = false;
          Kind k = cur.getKind();
          bool isQuant = k == kind::FORALL || k == kind::EXISTS
                         || k == kind::LAMBDA || k == kind::CHOICE;
          // we recurse on this node if it is not a quantified formula
          if (!isQuant)
          {
            visit.push_back(cur);
            for (const Node& cc : cur)
            {
              visit.push_back(cc);
            }
          }
        }
        else if (!it->second)
        {
          Trace("synth-rr-pass-debug") << "...postprocess " << cur << std::endl;
          // check if all of the children are valid
          // this ensures we do not register terms that have e.g. quantified
          // formulas as subterms
          bool childrenValid = true;
          for (const Node& cc : cur)
          {
            Assert(visited.find(cc) != visited.end());
            if (!visited[cc])
            {
              childrenValid = false;
            }
          }
          if (childrenValid)
          {
            Trace("synth-rr-pass-debug")
                << "...children are valid, check rewrites..." << std::endl;
            if (r == 0)
            {
              if (cur.isVar())
              {
                vars.push_back(cur);
              }
            }
            else
            {
              Trace("synth-rr-pass-debug") << "Add term " << cur << std::endl;
              // mark as processed
              cur.setAttribute(srrca, true);
              bool ret = crdg->addTerm(cur, *nodeManagerOptions.getOut());
              Trace("synth-rr-pass-debug") << "...return " << ret << std::endl;
              // if we want only rewrites of minimal size terms, we would set
              // childrenValid to false if ret is false here.
            }
          }
          visited[cur] = childrenValid;
        }
      } while (!visit.empty());
    }
    if (r == 0)
    {
      Trace("synth-rr-pass-debug")
          << "Initialize with " << nsamples
          << " samples and variables : " << vars << std::endl;
      crdg = std::unique_ptr<theory::quantifiers::CandidateRewriteDatabaseGen>(
          new theory::quantifiers::CandidateRewriteDatabaseGen(vars, nsamples));
    }
  }

  Trace("synth-rr-pass") << "...finished " << std::endl;
  return PreprocessingPassResult::NO_CONFLICT;
}
Example #8
0
uint64_t getMostFrequentValueCount(TNode store) {
  return store.getAttribute(ArrayConstantMostFrequentValueCountAttr());
}
Example #9
0
Node getMostFrequentValue(TNode store) {
  return store.getAttribute(ArrayConstantMostFrequentValueAttr());
}