Example #1
0
void collectAtoms(TNode node, CVC4::NodeSet& seen) {
    if (seen.find(node) != seen.end())
        return;
    if (theory::Theory::theoryOf(node) != theory::THEORY_BOOL || node.isVar()) {
        seen.insert(node);
        return;
    }

    for (unsigned i = 0; i < node.getNumChildren(); ++i) {
        collectAtoms(node[i], seen);
    }
}
Example #2
0
void EagerBitblaster::collectModelInfo(TheoryModel* m, bool fullModel) {
  TNodeSet::iterator it = d_variables.begin();
  for (; it!= d_variables.end(); ++it) {
    TNode var = *it;
    if (d_bv->isLeaf(var) || isSharedTerm(var) ||
        (var.isVar() && var.getType().isBoolean()))  {
      // only shared terms could not have been bit-blasted
      Assert (hasBBTerm(var) || isSharedTerm(var));
      
      Node const_value = getModelFromSatSolver(var, fullModel);
      
      if(const_value != Node()) {
        Debug("bitvector-model") << "EagerBitblaster::collectModelInfo (assert (= "
                                 << var << " "
                                 << const_value << "))\n";
        m->assertEquality(var, const_value, true);
      }
    }
  }
}
Example #3
0
Node RePairAssocCommutativeOperators::case_other(TNode n){
  if(n.isConst() || n.isVar()){
    return n;
  }

  NodeBuilder<> nb(n.getKind());

  if(n.getMetaKind() == kind::metakind::PARAMETERIZED) {
    nb << n.getOperator();
  }

  // Remove the ITEs from the children
  for(TNode::const_iterator i = n.begin(), end = n.end(); i != end; ++i) {
    Node newChild = rePairAssocCommutativeOperators(*i);
    nb << newChild;
  }

  Node result = (Node)nb;
  return result;
}
Example #4
0
void UnconstrainedSimplifier::visitAll(TNode assertion)
{
  // Do a topological sort of the subexpressions and substitute them
  vector<unc_preprocess_stack_element> toVisit;
  toVisit.push_back(assertion);

  while (!toVisit.empty())
  {
    // The current node we are processing
    TNode current = toVisit.back().node;
    TNode parent = toVisit.back().parent;
    toVisit.pop_back();

    TNodeCountMap::iterator find = d_visited.find(current);
    if (find != d_visited.end()) {
      if (find->second == 1) {
        d_visitedOnce.erase(current);
        if (current.isVar()) {
          d_unconstrained.erase(current);
        }
      }
      ++find->second;
      continue;
    }

    d_visited[current] = 1;
    d_visitedOnce[current] = parent;

    if (current.getNumChildren() == 0) {
      if (current.getKind()==kind::VARIABLE || current.getKind()==kind::SKOLEM) {
        d_unconstrained.insert(current);
      }
    }
    else {
      for(TNode::iterator child_it = current.begin(); child_it != current.end(); ++ child_it) {
        TNode childNode = *child_it;
        toVisit.push_back(unc_preprocess_stack_element(childNode, current));
      }
    }
  }
}
Example #5
0
bool TheoryEngineModelBuilder::isAssignable(TNode n)
{
  return (n.isVar() || n.getKind() == kind::APPLY_UF || n.getKind() == kind::SELECT || n.getKind() == kind::APPLY_SELECTOR);
}
Example #6
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 #7
0
bool AlgebraicSolver::solve(TNode fact, TNode reason, SubstitutionEx& subst) {
  if (fact.getKind() != kind::EQUAL) return false;

  TNode left = fact[0];
  TNode right = fact[1];

  
  if (left.isVar() && !right.hasSubterm(left)) {
    bool changed  = subst.addSubstitution(left, right, reason);
    return changed;
  }
  if (right.isVar() && !left.hasSubterm(right)) {
    bool changed = subst.addSubstitution(right, left, reason);
    return changed;
  }

  // xor simplification
  if (right.getKind() == kind::BITVECTOR_XOR &&
      left.getKind() == kind::BITVECTOR_XOR) {
    TNode var = left[0];
    if (var.getMetaKind() != kind::metakind::VARIABLE)
      return false; 

    // simplify xor with same variable on both sides
    if (right.hasSubterm(var)) {
      std::vector<Node> right_children;
      for (unsigned i = 0; i < right.getNumChildren(); ++i) {
        if (right[i] != var)
          right_children.push_back(right[i]); 
      }
      Assert (right_children.size());
      Node new_right = right_children.size() > 1 ? utils::mkNode(kind::BITVECTOR_XOR, right_children)
                                                 : right_children[0];
      std::vector<Node> left_children;
      for (unsigned i = 1; i < left.getNumChildren(); ++i) {
        left_children.push_back(left[i]);
      }
      Node new_left = left_children.size() > 1 ? utils::mkNode(kind::BITVECTOR_XOR, left_children)
                                               : left_children[0];
      Node new_fact = utils::mkNode(kind::EQUAL, new_left, new_right);
      bool changed = subst.addSubstitution(fact, new_fact, reason);
      return changed;
    }
    
    NodeBuilder<> nb(kind::BITVECTOR_XOR);
    for (unsigned i = 1; i < left.getNumChildren(); ++i) {
      nb << left[i];
    }
    Node inverse = left.getNumChildren() == 2? (Node)left[1] : (Node)nb;
    Node new_right = utils::mkNode(kind::BITVECTOR_XOR, right, inverse);
    bool changed = subst.addSubstitution(var, new_right, reason);

    if (Dump.isOn("bv-algebraic")) {
      Node query = utils::mkNot(utils::mkNode(kind::IFF, fact, utils::mkNode(kind::EQUAL, var, new_right)));
      Dump("bv-algebraic") << EchoCommand("ThoeryBV::AlgebraicSolver::substitution explanation"); 
      Dump("bv-algebraic") << PushCommand(); 
      Dump("bv-algebraic") << AssertCommand(query.toExpr());
      Dump("bv-algebraic") << CheckSatCommand();
      Dump("bv-algebraic") << PopCommand(); 
    }

    
    return changed;
  }

  // (a xor t = a) <=> (t = 0)
  if (left.getKind() == kind::BITVECTOR_XOR &&
      right.getMetaKind() == kind::metakind::VARIABLE &&
      left.hasSubterm(right)) {
    TNode var = right;
    Node new_left = utils::mkNode(kind::BITVECTOR_XOR, var, left);
    Node zero = utils::mkConst(utils::getSize(var), 0u);
    Node new_fact = utils::mkNode(kind::EQUAL, zero, new_left);
    bool changed = subst.addSubstitution(fact, new_fact, reason);
    return changed; 
  }
  
  if (right.getKind() == kind::BITVECTOR_XOR &&
      left.getMetaKind() == kind::metakind::VARIABLE &&
      right.hasSubterm(left)) {
    TNode var = left;
    Node new_right = utils::mkNode(kind::BITVECTOR_XOR, var, right);
    Node zero = utils::mkConst(utils::getSize(var), 0u);
    Node new_fact = utils::mkNode(kind::EQUAL, zero, new_right);
    bool changed = subst.addSubstitution(fact, new_fact, reason);
    return changed; 
  }

  // (a xor b = 0) <=> (a = b)
  if (left.getKind() == kind::BITVECTOR_XOR &&
      left.getNumChildren() == 2 &&
      right.getKind() == kind::CONST_BITVECTOR &&
      right.getConst<BitVector>() == BitVector(utils::getSize(left), 0u)) {
    Node new_fact = utils::mkNode(kind::EQUAL, left[0], left[1]);
    bool changed = subst.addSubstitution(fact, new_fact, reason);
    return changed; 
  }
  

  return false;
} 
Example #8
0
void CoreSolver::buildModel()
{
  Debug("bv-core") << "CoreSolver::buildModel() \n";
  NodeManager* nm = NodeManager::currentNM();
  d_modelValues.clear();
  TNodeSet constants;
  TNodeSet constants_in_eq_engine;
  // collect constants in equality engine
  eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(&d_equalityEngine);
  while (!eqcs_i.isFinished())
  {
    TNode repr = *eqcs_i;
    if (repr.getKind() == kind::CONST_BITVECTOR)
    {
      // must check if it's just the constant
      eq::EqClassIterator it(repr, &d_equalityEngine);
      if (!(++it).isFinished() || true)
      {
        constants.insert(repr);
        constants_in_eq_engine.insert(repr);
      }
    }
    ++eqcs_i;
  }

  // build repr to value map

  eqcs_i = eq::EqClassesIterator(&d_equalityEngine);
  while (!eqcs_i.isFinished())
  {
    TNode repr = *eqcs_i;
    ++eqcs_i;

    if (!repr.isVar() && repr.getKind() != kind::CONST_BITVECTOR
        && !d_bv->isSharedTerm(repr))
    {
      continue;
    }

    TypeNode type = repr.getType();
    if (type.isBitVector() && repr.getKind() != kind::CONST_BITVECTOR)
    {
      Debug("bv-core-model") << "   processing " << repr << "\n";
      // we need to assign a value for it
      TypeEnumerator te(type);
      Node val;
      do
      {
        val = *te;
        ++te;
        // Debug("bv-core-model") << "  trying value " << val << "\n";
        // Debug("bv-core-model") << "  is in set? " << constants.count(val) <<
        // "\n"; Debug("bv-core-model") << "  enumerator done? " <<
        // te.isFinished() << "\n";
      } while (constants.count(val) != 0 && !(te.isFinished()));

      if (te.isFinished() && constants.count(val) != 0)
      {
        // if we cannot enumerate anymore values we just return the lemma
        // stating that at least two of the representatives are equal.
        std::vector<TNode> representatives;
        representatives.push_back(repr);

        for (TNodeSet::const_iterator it = constants_in_eq_engine.begin();
             it != constants_in_eq_engine.end();
             ++it)
        {
          TNode constant = *it;
          if (utils::getSize(constant) == utils::getSize(repr))
          {
            representatives.push_back(constant);
          }
        }
        for (ModelValue::const_iterator it = d_modelValues.begin();
             it != d_modelValues.end();
             ++it)
        {
          representatives.push_back(it->first);
        }
        std::vector<Node> equalities;
        for (unsigned i = 0; i < representatives.size(); ++i)
        {
          for (unsigned j = i + 1; j < representatives.size(); ++j)
          {
            TNode a = representatives[i];
            TNode b = representatives[j];
            if (a.getKind() == kind::CONST_BITVECTOR
                && b.getKind() == kind::CONST_BITVECTOR)
            {
              Assert(a != b);
              continue;
            }
            if (utils::getSize(a) == utils::getSize(b))
            {
              equalities.push_back(nm->mkNode(kind::EQUAL, a, b));
            }
          }
        }
        // better off letting the SAT solver split on values
        if (equalities.size() > d_lemmaThreshold)
        {
          d_isComplete = false;
          return;
        }

        if (equalities.size() == 0)
        {
          Debug("bv-core") << "  lemma: true (no equalities)" << std::endl;
        }
        else
        {
          Node lemma = utils::mkOr(equalities);
          d_bv->lemma(lemma);
          Debug("bv-core") << "  lemma: " << lemma << std::endl;
        }
        return;
      }

      Debug("bv-core-model") << "   " << repr << " => " << val << "\n";
      constants.insert(val);
      d_modelValues[repr] = val;
    }
  }
}
Example #9
0
TheoryId Theory::theoryOf(TheoryOfMode mode, TNode node) {
  TheoryId tid = THEORY_BUILTIN;
  switch(mode) {
  case THEORY_OF_TYPE_BASED:
    // Constants, variables, 0-ary constructors
    if (node.isVar() || node.isConst()) {
      tid = Theory::theoryOf(node.getType());
    } else if (node.getKind() == kind::EQUAL) {
      // Equality is owned by the theory that owns the domain
      tid = Theory::theoryOf(node[0].getType());
    } else {
      // Regular nodes are owned by the kind
      tid = kindToTheoryId(node.getKind());
    }
    break;
  case THEORY_OF_TERM_BASED:
    // Variables
    if (node.isVar()) {
      if (Theory::theoryOf(node.getType()) != theory::THEORY_BOOL) {
        // We treat the variables as uninterpreted
        tid = s_uninterpretedSortOwner;
      } else {
        // Except for the Boolean ones, which we just ignore anyhow
        tid = theory::THEORY_BOOL;
      }
    } else if (node.isConst()) {
      // Constants go to the theory of the type
      tid = Theory::theoryOf(node.getType());
    } else if (node.getKind() == kind::EQUAL) { // Equality
      // If one of them is an ITE, it's irelevant, since they will get replaced out anyhow
      if (node[0].getKind() == kind::ITE) {
        tid = Theory::theoryOf(node[0].getType());
      } else if (node[1].getKind() == kind::ITE) {
        tid = Theory::theoryOf(node[1].getType());
      } else {
        TNode l = node[0];
        TNode r = node[1];
        TypeNode ltype = l.getType();
        TypeNode rtype = r.getType();
        if( ltype != rtype ){
          tid = Theory::theoryOf(l.getType());
        }else {
          // If both sides belong to the same theory the choice is easy
          TheoryId T1 = Theory::theoryOf(l);
          TheoryId T2 = Theory::theoryOf(r);
          if (T1 == T2) {
            tid = T1;
          } else {
            TheoryId T3 = Theory::theoryOf(ltype);
            // This is a case of
            // * x*y = f(z) -> UF
            // * x = c      -> UF
            // * f(x) = read(a, y) -> either UF or ARRAY
            // at least one of the theories has to be parametric, i.e. theory of the type is different
            // from the theory of the term
            if (T1 == T3) {
              tid = T2;
            } else if (T2 == T3) {
              tid = T1;
            } else {
              // If both are parametric, we take the smaller one (arbitrary)
              tid = T1 < T2 ? T1 : T2;
            }
          }
        }
      }
    } else {
      // Regular nodes are owned by the kind
      tid = kindToTheoryId(node.getKind());
    }
    break;
  default:
    Unreachable();
  }
  Trace("theory::internal") << "theoryOf(" << mode << ", " << node << ") -> " << tid << std::endl;
  return tid;
}