Example #1
0
Node RePairAssocCommutativeOperators::case_assoccomm(TNode n){
  Kind k = n.getKind();
  Assert(isAssociateCommutative(k));
  Assert(n.getMetaKind() != kind::metakind::PARAMETERIZED);
  unsigned N = n.getNumChildren();
  Assert(N >= 2);


  Node last = rePairAssocCommutativeOperators( n[N-1]);
  Node nextToLast = rePairAssocCommutativeOperators(n[N-2]);

  NodeManager* nm = NodeManager::currentNM();
  Node last2 = nm->mkNode(k, nextToLast, last);

  if(N <= 2){
    return last2;
  } else{
    Assert(N > 2);
    Node prevRound = last2;
    for(unsigned prevPos = N-2; prevPos > 0; --prevPos){
      unsigned currPos = prevPos-1;
      Node curr = rePairAssocCommutativeOperators(n[currPos]);
      Node round = nm->mkNode(k, curr, prevRound);
      prevRound = round;
    }
    return prevRound;
  }
}
Example #2
0
Node UfModelTreeNode::getFunctionValue(std::vector<Node>& args, int index, Node argDefaultValue, bool simplify) {
  if(!d_data.empty()) {
    Node defaultValue = argDefaultValue;
    if(d_data.find(Node::null()) != d_data.end()) {
      defaultValue = d_data[Node::null()].getFunctionValue(args, index + 1, argDefaultValue, simplify);
    }

    vector<Node> caseArgs;
    map<Node, Node> caseValues;

    for(map< Node, UfModelTreeNode>::iterator it = d_data.begin(); it != d_data.end(); ++it) {
      if(!it->first.isNull()) {
        Node val = it->second.getFunctionValue(args, index + 1, defaultValue, simplify);
        caseArgs.push_back(it->first);
        caseValues[it->first] = val;
      }
    }

    NodeManager* nm = NodeManager::currentNM();
    Node retNode = defaultValue;

    if(!simplify) {
      // "non-simplifying" mode - expand function values to things like:
      //   IF      (x=0 AND y=0 AND z=0) THEN value1
      //   ELSE IF (x=0 AND y=0 AND z=1) THEN value2
      //   [...etc...]
      for(int i = (int)caseArgs.size() - 1; i >= 0; --i) {
        Node val = caseValues[ caseArgs[ i ] ];
        if(val.getKind() == ITE) {
          // use a stack to reverse the order, since we're traversing outside-in
          stack<TNode> stk;
          do {
            stk.push(val);
            val = val[2];
          } while(val.getKind() == ITE);
          AlwaysAssert(val == defaultValue, "default values don't match when constructing function definition!");
          while(!stk.empty()) {
            val = stk.top();
            stk.pop();
            retNode = nm->mkNode(ITE, nm->mkNode(AND, args[index].eqNode(caseArgs[i]), val[0]), val[1], retNode);
          }
        } else {
          retNode = nm->mkNode(ITE, args[index].eqNode(caseArgs[i]), caseValues[caseArgs[i]], retNode);
        }
      }
    } else {
      // "simplifying" mode - condense function values
      for(int i = (int)caseArgs.size() - 1; i >= 0; --i) {
        retNode = nm->mkNode(ITE, args[index].eqNode(caseArgs[i]), caseValues[caseArgs[i]], retNode);
      }
    }
    return retNode;
  } else {
    Assert(!d_value.isNull());
    return d_value;
  }
}
Example #3
0
Node InequalityGraph::makeDiseqSplitLemma(TNode diseq)
{
  Assert(diseq.getKind() == kind::NOT && diseq[0].getKind() == kind::EQUAL);
  NodeManager* nm = NodeManager::currentNM();
  TNode a = diseq[0][0];
  TNode b = diseq[0][1];
  Node a_lt_b = nm->mkNode(kind::BITVECTOR_ULT, a, b);
  Node b_lt_a = nm->mkNode(kind::BITVECTOR_ULT, b, a);
  Node eq = diseq[0];
  Node lemma = nm->mkNode(kind::OR, a_lt_b, b_lt_a, eq);
  return lemma;
}
Example #4
0
bool DtInstantiator::processEqualTerms(CegInstantiator* ci,
                                       SolvedForm& sf,
                                       Node pv,
                                       std::vector<Node>& eqc,
                                       CegInstEffort effort)
{
  Trace("cegqi-dt-debug") << "try based on constructors in equivalence class."
                          << std::endl;
  // look in equivalence class for a constructor
  NodeManager* nm = NodeManager::currentNM();
  for (unsigned k = 0, size = eqc.size(); k < size; k++)
  {
    Node n = eqc[k];
    if (n.getKind() == APPLY_CONSTRUCTOR)
    {
      Trace("cegqi-dt-debug")
          << "...try based on constructor term " << n << std::endl;
      std::vector<Node> children;
      children.push_back(n.getOperator());
      const Datatype& dt =
          static_cast<DatatypeType>(d_type.toType()).getDatatype();
      unsigned cindex = Datatype::indexOf(n.getOperator().toExpr());
      // now must solve for selectors applied to pv
      for (unsigned j = 0, nargs = dt[cindex].getNumArgs(); j < nargs; j++)
      {
        Node c = nm->mkNode(
            APPLY_SELECTOR_TOTAL,
            Node::fromExpr(dt[cindex].getSelectorInternal(d_type.toType(), j)),
            pv);
        ci->pushStackVariable(c);
        children.push_back(c);
      }
      Node val = nm->mkNode(kind::APPLY_CONSTRUCTOR, children);
      TermProperties pv_prop_dt;
      if (ci->constructInstantiationInc(pv, val, pv_prop_dt, sf))
      {
        return true;
      }
      // cleanup
      for (unsigned j = 0, nargs = dt[cindex].getNumArgs(); j < nargs; j++)
      {
        ci->popStackVariable();
      }
      break;
    }
  }
  return false;
}
Example #5
0
void PseudoBooleanProcessor::learnGeqSub(Node geq)
{
  Assert(geq.getKind() == kind::GEQ);
  const bool negated = false;
  bool success = decomposeAssertion(geq, negated);
  if (!success)
  {
    Debug("pbs::rewrites") << "failed " << std::endl;
    return;
  }
  Assert(d_off.value().isIntegral());
  Integer off = d_off.value().ceiling();

  // \sum pos >= \sum neg + off

  // for now special case everything we want
  // target easy clauses
  if (d_pos.size() == 1 && d_neg.size() == 1 && off.isZero())
  {
    // x >= y
    // |- (y >= 1) => (x >= 1)
    Node x = d_pos.front();
    Node y = d_neg.front();

    Node xGeq1 = mkGeqOne(x);
    Node yGeq1 = mkGeqOne(y);
    Node imp = yGeq1.impNode(xGeq1);
    addSub(geq, imp);
  }
  else if (d_pos.size() == 0 && d_neg.size() == 2 && off.isNegativeOne())
  {
    // 0 >= (x + y -1)
    // |- 1 >= x + y
    // |- (or (not (x >= 1)) (not (y >= 1)))
    Node x = d_neg[0];
    Node y = d_neg[1];

    Node xGeq1 = mkGeqOne(x);
    Node yGeq1 = mkGeqOne(y);
    Node cases = (xGeq1.notNode()).orNode(yGeq1.notNode());
    addSub(geq, cases);
  }
  else if (d_pos.size() == 2 && d_neg.size() == 1 && off.isZero())
  {
    // (x + y) >= z
    // |- (z >= 1) => (or (x >= 1) (y >=1 ))
    Node x = d_pos[0];
    Node y = d_pos[1];
    Node z = d_neg[0];

    Node xGeq1 = mkGeqOne(x);
    Node yGeq1 = mkGeqOne(y);
    Node zGeq1 = mkGeqOne(z);
    NodeManager* nm = NodeManager::currentNM();
    Node dis = nm->mkNode(kind::OR, zGeq1.notNode(), xGeq1, yGeq1);
    addSub(geq, dis);
  }
}
Example #6
0
bool CoreSolver::decomposeFact(TNode fact) {
  Debug("bv-slicer") << "CoreSolver::decomposeFact fact=" << fact << endl;
  // FIXME: are this the right things to assert?
  // assert decompositions since the equality engine does not know the semantics of
  // concat:
  //   a == a_1 concat ... concat a_k
  //   b == b_1 concat ... concat b_k
  TNode eq = fact.getKind() == kind::NOT? fact[0] : fact;

  TNode a = eq[0];
  TNode b = eq[1];
  Node new_a = getBaseDecomposition(a);
  Node new_b = getBaseDecomposition(b);

  Assert (utils::getSize(new_a) == utils::getSize(new_b) &&
          utils::getSize(new_a) == utils::getSize(a));

  NodeManager* nm = NodeManager::currentNM();
  Node a_eq_new_a = nm->mkNode(kind::EQUAL, a, new_a);
  Node b_eq_new_b = nm->mkNode(kind::EQUAL, b, new_b);

  bool ok = true;
  ok = assertFactToEqualityEngine(a_eq_new_a, utils::mkTrue());
  if (!ok) return false;
  ok = assertFactToEqualityEngine(b_eq_new_b, utils::mkTrue());
  if (!ok) return false;
  ok = assertFactToEqualityEngine(fact, fact);
  if (!ok) return false;

  if (fact.getKind() == kind::EQUAL) {
    // assert the individual equalities as well
    //    a_i == b_i
    if (new_a.getKind() == kind::BITVECTOR_CONCAT &&
        new_b.getKind() == kind::BITVECTOR_CONCAT) {

      Assert (new_a.getNumChildren() == new_b.getNumChildren());
      for (unsigned i = 0; i < new_a.getNumChildren(); ++i) {
        Node eq_i = nm->mkNode(kind::EQUAL, new_a[i], new_b[i]);
        ok = assertFactToEqualityEngine(eq_i, fact);
        if (!ok) return false;
      }
    }
  }
  return true;
}
Example #7
0
void InequalityGraph::getAllValuesInModel(std::vector<Node>& assignments)
{
  NodeManager* nm = NodeManager::currentNM();
  for (ModelValues::const_iterator it = d_modelValues.begin();
       it != d_modelValues.end();
       ++it)
  {
    TermId id = (*it).first;
    BitVector value = (*it).second.value;
    TNode var = getTermNode(id);
    Node constant = utils::mkConst(value);
    Node assignment = nm->mkNode(kind::EQUAL, var, constant);
    assignments.push_back(assignment);
    Debug("bitvector-model") << "   " << var << " => " << constant << "\n";
  }
}
Example #8
0
Node InferBoundsResult::getLiteral() const{
  const Rational& q = getValue().getNoninfinitesimalPart();
  NodeManager* nm = NodeManager::currentNM();
  Node qnode = nm->mkConst(q);

  Kind k;
  if(d_upperBound){
    // x <= q + c*delta
    Assert(getValue().infinitesimalSgn() <= 0);
    k = boundIsRational() ? kind::LEQ : kind::LT;
  }else{
    // x >= q + c*delta
    Assert(getValue().infinitesimalSgn() >= 0);
    k = boundIsRational() ? kind::GEQ : kind::GT;
  }
  Node atom = nm->mkNode(k, getTerm(), qnode);
  Node lit = Rewriter::rewrite(atom);
  return lit;
}
Example #9
0
EqualityStatus InequalitySolver::getEqualityStatus(TNode a, TNode b)
{
  if (!isComplete()) return EQUALITY_UNKNOWN;

  NodeManager* nm = NodeManager::currentNM();
  Node a_lt_b = nm->mkNode(kind::BITVECTOR_ULT, a, b);
  Node b_lt_a = nm->mkNode(kind::BITVECTOR_ULT, b, a);

  // if an inequality containing the terms has been asserted then we know
  // the equality is false
  if (d_assertionSet.contains(a_lt_b) || d_assertionSet.contains(b_lt_a))
  {
    return EQUALITY_FALSE;
  }

  if (!d_inequalityGraph.hasValueInModel(a)
      || !d_inequalityGraph.hasValueInModel(b))
  {
    return EQUALITY_UNKNOWN;
  }

  // TODO: check if this disequality is entailed by inequalities via
  // transitivity

  BitVector a_val = d_inequalityGraph.getValueInModel(a);
  BitVector b_val = d_inequalityGraph.getValueInModel(b);

  if (a_val == b_val)
  {
    return EQUALITY_TRUE_IN_MODEL;
  }
  else
  {
    return EQUALITY_FALSE_IN_MODEL;
  }
}
Example #10
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 #11
0
Node SymmetryBreaker::generateSymBkConstraints(const vector<vector<Node>>& parts)
{
  vector<Node> constraints;
  NodeManager* nm = NodeManager::currentNM();

  for (const vector<Node>& part : parts)
  {
    if (part.size() >= 2)
    {
      Kind kd = getOrderKind(part[0]);
      if (kd == UNDEFINED_KIND)
      {
        // no symmetry breaking possible
        continue;
      }
      if (kd != EQUAL)
      {
        for (unsigned int i = 0; i < part.size() - 1; ++i)
        {
          // Generate less than or equal to constraints: part[i] <= part[i+1]
          Node constraint = nm->mkNode(kd, part[i], part[i + 1]);
          constraints.push_back(constraint);
          Trace("sym-bk")
              << "[sym-bk] Generate a symmetry breaking constraint: "
              << constraint << endl;
        }
      }
      else if (part.size() >= 3)
      {
        for (unsigned int i = 0; i < part.size(); ++i)
        {
          for (unsigned int j = i + 2; j < part.size(); ++j)
          {
            // Generate consecutive constraints v_i = v_j => v_i = v_{j-1},
            // for all 0 <= i < j-1 < j < part.size()
            Node constraint = nm->mkNode(IMPLIES,
                                         nm->mkNode(kd, part[i], part[j]),
                                         nm->mkNode(kd, part[i], part[j - 1]));
            constraints.push_back(constraint);
            Trace("sym-bk")
                << "[sym-bk] Generate a symmetry breaking constraint: "
                << constraint << endl;
          }
          if (i >= 1)
          {
            for (unsigned int j = i + 1; j < part.size(); ++j)
            {
              Node lhs = nm->mkNode(kd, part[i], part[j]);
              Node rhs = nm->mkNode(kd, part[i], part[i - 1]);
              int prev_seg_start_index = 2*i - j - 1;

              // Since prev_seg_len is always less than i - 1, we just need to make
              // sure prev_seg_len is greater than or equal to 0
              if(prev_seg_start_index >= 0)
              {
                rhs = nm->mkNode(
                    OR,
                    rhs,
                    nm->mkNode(kd, part[i - 1], part[prev_seg_start_index]));
              }
              // Generate length order constraints
              // v_i = v_j => (v_{i} = v_{i-1} OR v_{i-1} = x_{(i-1)-(j-i)})
              // for all 1 <= i < j < part.size() and (i-1)-(j-i) >= 0
              Node constraint = nm->mkNode(IMPLIES, lhs, rhs);
              constraints.push_back(constraint);
              Trace("sym-bk")
                  << "[sym-bk] Generate a symmetry breaking constraint: "
                  << constraint << endl;
            }
          }
        }
      }
    }
  }
  if(constraints.empty())
  {
    return d_trueNode;
  }
  else if(constraints.size() == 1)
  {
    return constraints[0];
  }
  return nm->mkNode(AND, constraints);
}
Example #12
0
void UnconstrainedSimplifier::processUnconstrained()
{
  TNodeSet::iterator it = d_unconstrained.begin(), iend = d_unconstrained.end();
  vector<TNode> workList;
  for ( ; it != iend; ++it) {
    workList.push_back(*it);
  }
  Node currentSub;
  TNode parent;
  bool swap;
  bool isSigned;
  bool strict;
  vector<TNode> delayQueueLeft;
  vector<Node> delayQueueRight;

  TNode current = workList.back();
  workList.pop_back();
  for (;;) {
    Assert(d_visitedOnce.find(current) != d_visitedOnce.end());
    parent = d_visitedOnce[current];
    if (!parent.isNull()) {
      swap = isSigned = strict = false;
      switch (parent.getKind()) {

        // If-then-else operator - any two unconstrained children makes the parent unconstrained
        case kind::ITE: {
          Assert(parent[0] == current || parent[1] == current || parent[2] == current);
          bool uCond = parent[0] == current || d_unconstrained.find(parent[0]) != d_unconstrained.end();
          bool uThen = parent[1] == current || d_unconstrained.find(parent[1]) != d_unconstrained.end();
          bool uElse = parent[2] == current || d_unconstrained.find(parent[2]) != d_unconstrained.end();
          if ((uCond && uThen) || (uCond && uElse) || (uThen && uElse)) {
            if (d_unconstrained.find(parent) == d_unconstrained.end() &&
                !d_substitutions.hasSubstitution(parent)) {
              ++d_numUnconstrainedElim;
              if (uThen) {
                if (parent[1] != current) {
                  if (parent[1].isVar()) {
                    currentSub = parent[1];
                  }
                  else {
                    Assert(d_substitutions.hasSubstitution(parent[1]));
                    currentSub = d_substitutions.apply(parent[1]);
                  }
                }
                else if (currentSub.isNull()) {
                  currentSub = current;
                }
              }
              else if (parent[2] != current) {
                if (parent[2].isVar()) {
                  currentSub = parent[2];
                }
                else {
                  Assert(d_substitutions.hasSubstitution(parent[2]));
                  currentSub = d_substitutions.apply(parent[2]);
                }
              }
              else if (currentSub.isNull()) {
                currentSub = current;
              }
              current = parent;
            }
            else {
              currentSub = Node();
            }
          }
          else if (uCond) {
            Cardinality card = parent.getType().getCardinality();
            if (card.isFinite() && !card.isLargeFinite() && card.getFiniteCardinality() == 2) {
              // Special case: condition is unconstrained, then and else are different, and total cardinality of the type is 2, then the result
              // is unconstrained
              Node test;
              if (parent.getType().isBoolean()) {
                test = Rewriter::rewrite(parent[1].iffNode(parent[2]));
              }
              else {
                test = Rewriter::rewrite(parent[1].eqNode(parent[2]));
              }
              if (test == NodeManager::currentNM()->mkConst<bool>(false)) {
                ++d_numUnconstrainedElim;
                if (currentSub.isNull()) {
                  currentSub = current;
                }
                currentSub = newUnconstrainedVar(parent.getType(), currentSub);
                current = parent;
              }
            }
          }
          break;
        }

        // Comparisons that return a different type - assuming domains are larger than 1, any
        // unconstrained child makes parent unconstrained as well
        case kind::EQUAL:
          if (parent[0].getType() != parent[1].getType()) {
            TNode other = (parent[0] == current) ? parent[1] : parent[0];
            if (current.getType().isSubtypeOf(other.getType())) {
              break;
            }
          }
          if( parent[0].getType().isDatatype() ){
            TypeNode tn = parent[0].getType();
            const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
            if( dt.isRecursiveSingleton( tn.toType() ) ){
              //domain size may be 1
              break;
            }
          }
        case kind::BITVECTOR_COMP:
        case kind::LT:
        case kind::LEQ:
        case kind::GT:
        case kind::GEQ:
        {
          if (d_unconstrained.find(parent) == d_unconstrained.end() &&
              !d_substitutions.hasSubstitution(parent)) {
            ++d_numUnconstrainedElim;
            Assert(parent[0] != parent[1] &&
                   (parent[0] == current || parent[1] == current));
            if (currentSub.isNull()) {
              currentSub = current;
            }
            currentSub = newUnconstrainedVar(parent.getType(), currentSub);
            current = parent;
          }
          else {
            currentSub = Node();
          }
          break;
        }

        // Unary operators that propagate unconstrainedness
        case kind::NOT:
        case kind::BITVECTOR_NOT:
        case kind::BITVECTOR_NEG:
        case kind::UMINUS:
          ++d_numUnconstrainedElim;
          Assert(parent[0] == current);
          if (currentSub.isNull()) {
            currentSub = current;
          }
          current = parent;
          break;

        // Unary operators that propagate unconstrainedness and return a different type
        case kind::BITVECTOR_EXTRACT:
          ++d_numUnconstrainedElim;
          Assert(parent[0] == current);
          if (currentSub.isNull()) {
            currentSub = current;
          }
          currentSub = newUnconstrainedVar(parent.getType(), currentSub);
          current = parent;
          break;

        // Operators returning same type requiring all children to be unconstrained
        case kind::AND:
        case kind::OR:
        case kind::IMPLIES:
        case kind::BITVECTOR_AND:
        case kind::BITVECTOR_OR:
        case kind::BITVECTOR_NAND:
        case kind::BITVECTOR_NOR:
        {
          bool allUnconstrained = true;
          for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) {
            if (d_unconstrained.find(*child_it) == d_unconstrained.end()) {
              allUnconstrained = false;
              break;
            }
          }
          if (allUnconstrained) {
            if (d_unconstrained.find(parent) == d_unconstrained.end() &&
                !d_substitutions.hasSubstitution(parent)) {
              ++d_numUnconstrainedElim;
              if (currentSub.isNull()) {
                currentSub = current;
              }
              current = parent;
            }
            else {
              currentSub = Node();
            }
          }
        }
        break;

        // Require all children to be unconstrained and different
        case kind::BITVECTOR_SHL:
        case kind::BITVECTOR_LSHR:
        case kind::BITVECTOR_ASHR:
        case kind::BITVECTOR_UDIV_TOTAL:
        case kind::BITVECTOR_UREM_TOTAL:
        case kind::BITVECTOR_SDIV:
        case kind::BITVECTOR_SREM:
        case kind::BITVECTOR_SMOD: {
          bool allUnconstrained = true;
          bool allDifferent = true;
          for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) {
            if (d_unconstrained.find(*child_it) == d_unconstrained.end()) {
              allUnconstrained = false;
              break;
            }
            for(TNode::iterator child_it2 = child_it + 1; child_it2 != parent.end(); ++child_it2) {
              if (*child_it == *child_it2) {
                allDifferent = false;
                break;
              }
            }
          }
          if (allUnconstrained && allDifferent) {
            if (d_unconstrained.find(parent) == d_unconstrained.end() &&
                !d_substitutions.hasSubstitution(parent)) {
              ++d_numUnconstrainedElim;
              if (currentSub.isNull()) {
                currentSub = current;
              }
              current = parent;
            }
            else {
              currentSub = Node();
            }
          }
          break;
        }

        // Requires all children to be unconstrained and different, and returns a different type
        case kind::BITVECTOR_CONCAT:
        {
          bool allUnconstrained = true;
          bool allDifferent = true;
          for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) {
            if (d_unconstrained.find(*child_it) == d_unconstrained.end()) {
              allUnconstrained = false;
              break;
            }
            for(TNode::iterator child_it2 = child_it + 1; child_it2 != parent.end(); ++child_it2) {
              if (*child_it == *child_it2) {
                allDifferent = false;
                break;
              }
            }
          }
          if (allUnconstrained && allDifferent) {
            if (d_unconstrained.find(parent) == d_unconstrained.end() &&
                !d_substitutions.hasSubstitution(parent)) {
              ++d_numUnconstrainedElim;
              if (currentSub.isNull()) {
                currentSub = current;
              }
              currentSub = newUnconstrainedVar(parent.getType(), currentSub);
              current = parent;
            }
            else {
              currentSub = Node();
            }
          }
        }
        break;

        // N-ary operators returning same type requiring at least one child to be unconstrained
        case kind::PLUS:
        case kind::MINUS:
          if (current.getType().isInteger() &&
              !parent.getType().isInteger()) {
            break;
          }
        case kind::IFF:
        case kind::XOR:
        case kind::BITVECTOR_XOR:
        case kind::BITVECTOR_XNOR:
        case kind::BITVECTOR_PLUS:
        case kind::BITVECTOR_SUB:
          if (d_unconstrained.find(parent) == d_unconstrained.end() &&
              !d_substitutions.hasSubstitution(parent)) {
            ++d_numUnconstrainedElim;
            if (currentSub.isNull()) {
              currentSub = current;
            }
            current = parent;
          }
          else {
            currentSub = Node();
          }
          break;

        // Multiplication/division: must be non-integer and other operand must be non-zero
        case kind::MULT: {
        case kind::DIVISION:
          Assert(parent.getNumChildren() == 2);
          TNode other;
          if (parent[0] == current) {
            other = parent[1];
          }
          else {
            Assert(parent[1] == current);
            other = parent[0];
          }
          if (d_unconstrained.find(other) != d_unconstrained.end()) {
            if (d_unconstrained.find(parent) == d_unconstrained.end() &&
                !d_substitutions.hasSubstitution(parent)) {
              if (current.getType().isInteger() && other.getType().isInteger()) {
                Assert(parent.getKind() == kind::DIVISION || parent.getType().isInteger());
                if (parent.getKind() == kind::DIVISION) {
                  break;
                }
              }
              ++d_numUnconstrainedElim;
              if (currentSub.isNull()) {
                currentSub = current;
              }
              current = parent;
            }
            else {
              currentSub = Node();
            }
          }
          else {
            // if only the denominator of a division is unconstrained, can't set it to 0 so the result is not unconstrained
            if (parent.getKind() == kind::DIVISION && current == parent[1]) {
              break;
            }
            NodeManager* nm = NodeManager::currentNM();
            // if we are an integer, the only way we are unconstrained is if we are a MULT by -1
            if (current.getType().isInteger()) {
              // div/mult by 1 should have been simplified
              Assert(other != nm->mkConst<Rational>(1));
              if (other == nm->mkConst<Rational>(-1)) {
                // div by -1 should have been simplified
                Assert(parent.getKind() == kind::MULT);
                Assert(parent.getType().isInteger());
              }
              else {
                break;
              }
            }
            else {
              // TODO: could build ITE here
              Node test = other.eqNode(nm->mkConst<Rational>(0));
              if (Rewriter::rewrite(test) != nm->mkConst<bool>(false)) {
                break;
              }
            }
            ++d_numUnconstrainedElim;
            if (currentSub.isNull()) {
              currentSub = current;
            }
            current = parent;
          }
          break;
        }

        // Bitvector MULT - current must only appear once in the children:
        // all other children must be unconstrained or odd
        case kind::BITVECTOR_MULT:
        {
          bool found = false;
          bool done = false;
          for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) {
            if ((*child_it) == current) {
              if (found) {
                done = true;
                break;
              }
              found = true;
              continue;
            }
            else if (d_unconstrained.find(*child_it) != d_unconstrained.end()) {
              continue;
            }
            else {
              NodeManager* nm = NodeManager::currentNM();
              Node extractOp = nm->mkConst<BitVectorExtract>(BitVectorExtract(0,0));
              vector<Node> children;
              children.push_back(*child_it);
              Node test = nm->mkNode(extractOp, children);
              BitVector one(1,unsigned(1));
              test = test.eqNode(nm->mkConst<BitVector>(one));
              if (Rewriter::rewrite(test) != nm->mkConst<bool>(true)) {
                done = true;
                break;
              }
            }
          }
          if (done) {
            break;
          }
          if (d_unconstrained.find(parent) == d_unconstrained.end() &&
              !d_substitutions.hasSubstitution(parent)) {
            ++d_numUnconstrainedElim;
            if (currentSub.isNull()) {
              currentSub = current;
            }
            current = parent;
          }
          else {
            currentSub = Node();
          }
          break;
        }

        // Uninterpreted function - if domain is infinite, no quantifiers are used, and any child is unconstrained, result is unconstrained
        case kind::APPLY_UF:
          if (d_logicInfo.isQuantified() || !current.getType().getCardinality().isInfinite()) {
            break;
          }
          if (d_unconstrained.find(parent) == d_unconstrained.end() &&
              !d_substitutions.hasSubstitution(parent)) {
            ++d_numUnconstrainedElim;
            if (currentSub.isNull()) {
              currentSub = current;
            }
            if (parent.getType() != current.getType()) {
              currentSub = newUnconstrainedVar(parent.getType(), currentSub);
            }
            current = parent;
          }
          else {
            currentSub = Node();
          }
          break;

        // Array select - if array is unconstrained, so is result
        case kind::SELECT:
          if (parent[0] == current) {
            ++d_numUnconstrainedElim;
            Assert(current.getType().isArray());
            if (currentSub.isNull()) {
              currentSub = current;
            }
            currentSub = newUnconstrainedVar(current.getType().getArrayConstituentType(), currentSub);
            current = parent;
          }
          break;

        // Array store - if both store and value are unconstrained, so is resulting store
        case kind::STORE:
          if (((parent[0] == current &&
                d_unconstrained.find(parent[2]) != d_unconstrained.end()) ||
               (parent[2] == current &&
                d_unconstrained.find(parent[0]) != d_unconstrained.end()))) {
            if (d_unconstrained.find(parent) == d_unconstrained.end() &&
                !d_substitutions.hasSubstitution(parent)) {
              ++d_numUnconstrainedElim;
              if (parent[0] != current) {
                if (parent[0].isVar()) {
                  currentSub = parent[0];
                }
                else {
                  Assert(d_substitutions.hasSubstitution(parent[0]));
                  currentSub = d_substitutions.apply(parent[0]);
                }
              }
              else if (currentSub.isNull()) {
                currentSub = current;
              }
              current = parent;
            }
            else {
              currentSub = Node();
            }
          }
          break;

        // Bit-vector comparisons: replace with new Boolean variable, but have
        // to also conjoin with a side condition as there is always one case
        // when the comparison is forced to be false
        case kind::BITVECTOR_ULT:
        case kind::BITVECTOR_UGE:
        case kind::BITVECTOR_UGT:
        case kind::BITVECTOR_ULE:
        case kind::BITVECTOR_SLT:
        case kind::BITVECTOR_SGE:
        case kind::BITVECTOR_SGT:
        case kind::BITVECTOR_SLE: {
          // Tuples over (signed, swap, strict).
          switch (parent.getKind()) {
            case kind::BITVECTOR_UGE:
              break;
            case kind::BITVECTOR_ULT:
              strict = true;
              break;
            case kind::BITVECTOR_ULE:
              swap = true;
              break;
            case kind::BITVECTOR_UGT:
              swap = true;
              strict = true;
              break;
            case kind::BITVECTOR_SGE:
              isSigned = true;
              break;
            case kind::BITVECTOR_SLT:
              isSigned = true;
              strict = true;
              break;
            case kind::BITVECTOR_SLE:
              isSigned = true;
              swap = true;
              break;
            case kind::BITVECTOR_SGT:
              isSigned = true;
              swap = true;
              strict = true;
              break;
            default:
              Unreachable();
          }
          TNode other;
          bool left = false;
          if (parent[0] == current) {
            other = parent[1];
            left = true;
          } else {
            Assert(parent[1] == current);
            other = parent[0];
          }
          if (d_unconstrained.find(other) != d_unconstrained.end()) {
            if (d_unconstrained.find(parent) == d_unconstrained.end() &&
                !d_substitutions.hasSubstitution(parent)) {
              ++d_numUnconstrainedElim;
              if (currentSub.isNull()) {
                currentSub = current;
              }
              currentSub = newUnconstrainedVar(parent.getType(), currentSub);
              current = parent;
            } else {
              currentSub = Node();
            }
          } else {
            unsigned size = current.getType().getBitVectorSize();
            BitVector bv =
                isSigned ? BitVector(size, Integer(1).multiplyByPow2(size - 1))
                         : BitVector(size, unsigned(0));
            if (swap == left) {
              bv = ~bv;
            }
            if (currentSub.isNull()) {
              currentSub = current;
            }
            currentSub = newUnconstrainedVar(parent.getType(), currentSub);
            current = parent;
            NodeManager* nm = NodeManager::currentNM();
            Node test =
                Rewriter::rewrite(other.eqNode(nm->mkConst<BitVector>(bv)));
            if (test == nm->mkConst<bool>(false)) {
              break;
            }
            if (strict) {
              currentSub = currentSub.andNode(test.notNode());
            } else {
              currentSub = currentSub.orNode(test);
            }
            // Delay adding this substitution - see comment at end of function
            delayQueueLeft.push_back(current);
            delayQueueRight.push_back(currentSub);
            currentSub = Node();
            parent = TNode();
          }
          break;
        }

        // Do nothing 
        case kind::BITVECTOR_SIGN_EXTEND:
        case kind::BITVECTOR_ZERO_EXTEND:
        case kind::BITVECTOR_REPEAT:
        case kind::BITVECTOR_ROTATE_LEFT:
        case kind::BITVECTOR_ROTATE_RIGHT:

        default:
          break;
      }
      if (current == parent && d_visited[parent] == 1) {
        d_unconstrained.insert(parent);
        continue;
      }
    }
    if (!currentSub.isNull()) {
      Assert(currentSub.isVar());
      d_substitutions.addSubstitution(current, currentSub, false);
    }
    if (workList.empty()) {
      break;
    }
    current = workList.back();
    currentSub = Node();
    workList.pop_back();
  }
  TNode left;
  Node right;
  // All substitutions except those arising from bitvector comparisons are
  // substitutions t -> x where x is a variable.  This allows us to build the
  // substitution very quickly (never invalidating the substitution cache).
  // Bitvector comparisons are more complicated and may require
  // back-substitution and cache-invalidation.  So we do these last.
  while (!delayQueueLeft.empty()) {
    left = delayQueueLeft.back();
    if (!d_substitutions.hasSubstitution(left)) {
      right = d_substitutions.apply(delayQueueRight.back());
      d_substitutions.addSubstitution(delayQueueLeft.back(), right);
    }
    delayQueueLeft.pop_back();
    delayQueueRight.pop_back();
  }
}
Example #13
0
Node DtInstantiator::solve_dt(Node v, Node a, Node b, Node sa, Node sb)
{
  Trace("cegqi-arith-debug2") << "Solve dt : " << v << " " << a << " " << b
                              << " " << sa << " " << sb << std::endl;
  Node ret;
  if (!a.isNull() && a == v)
  {
    ret = sb;
  }
  else if (!b.isNull() && b == v)
  {
    ret = sa;
  }
  else if (!a.isNull() && a.getKind() == APPLY_CONSTRUCTOR)
  {
    if (!b.isNull() && b.getKind() == APPLY_CONSTRUCTOR)
    {
      if (a.getOperator() == b.getOperator())
      {
        for (unsigned i = 0, nchild = a.getNumChildren(); i < nchild; i++)
        {
          Node s = solve_dt(v, a[i], b[i], sa[i], sb[i]);
          if (!s.isNull())
          {
            return s;
          }
        }
      }
    }
    else
    {
      NodeManager* nm = NodeManager::currentNM();
      unsigned cindex = Datatype::indexOf(a.getOperator().toExpr());
      TypeNode tn = a.getType();
      const Datatype& dt = static_cast<DatatypeType>(tn.toType()).getDatatype();
      for (unsigned i = 0, nchild = a.getNumChildren(); i < nchild; i++)
      {
        Node nn = nm->mkNode(
            APPLY_SELECTOR_TOTAL,
            Node::fromExpr(dt[cindex].getSelectorInternal(tn.toType(), i)),
            sb);
        Node s = solve_dt(v, a[i], Node::null(), sa[i], nn);
        if (!s.isNull())
        {
          return s;
        }
      }
    }
  }
  else if (!b.isNull() && b.getKind() == APPLY_CONSTRUCTOR)
  {
    // flip sides
    return solve_dt(v, b, a, sb, sa);
  }
  if (!ret.isNull())
  {
    // ensure does not contain v
    if (expr::hasSubterm(ret, v))
    {
      ret = Node::null();
    }
  }
  return ret;
}
Example #14
0
Node RemoveITE::run(TNode node, std::vector<Node>& output,
                    IteSkolemMap& iteSkolemMap) {
  // Current node
  Debug("ite") << "removeITEs(" << node << ")" << endl;

  // The result may be cached already
  NodeManager *nodeManager = NodeManager::currentNM();
  ITECache::iterator i = d_iteCache.find(node);
  if(i != d_iteCache.end()) {
    Node cachedRewrite = (*i).second;
    Debug("ite") << "removeITEs: in-cache: " << cachedRewrite << endl;
    return cachedRewrite.isNull() ? Node(node) : cachedRewrite;
  }

  // If an ITE replace it
  if(node.getKind() == kind::ITE) {
    TypeNode nodeType = node.getType();
    if(!nodeType.isBoolean()) {
      // Make the skolem to represent the ITE
      Node skolem = nodeManager->mkSkolem("termITE_$$", nodeType, "a variable introduced due to term-level ITE removal");

      // The new assertion
      Node newAssertion =
        nodeManager->mkNode(kind::ITE, node[0], skolem.eqNode(node[1]),
                            skolem.eqNode(node[2]));
      Debug("ite") << "removeITEs(" << node << ") => " << newAssertion << endl;

      // Attach the skolem
      d_iteCache[node] = skolem;

      // Remove ITEs from the new assertion, rewrite it and push it to the output
      newAssertion = run(newAssertion, output, iteSkolemMap);
      iteSkolemMap[skolem] = output.size();
      output.push_back(newAssertion);

      // The representation is now the skolem
      return skolem;
    }
  }

  // If not an ITE, go deep
  if( node.getKind() != kind::FORALL &&
      node.getKind() != kind::EXISTS &&
      node.getKind() != kind::REWRITE_RULE ) {
    vector<Node> newChildren;
    bool somethingChanged = false;
    if(node.getMetaKind() == kind::metakind::PARAMETERIZED) {
      newChildren.push_back(node.getOperator());
    }
    // Remove the ITEs from the children
    for(TNode::const_iterator it = node.begin(), end = node.end(); it != end; ++it) {
      Node newChild = run(*it, output, iteSkolemMap);
      somethingChanged |= (newChild != *it);
      newChildren.push_back(newChild);
    }

    // If changes, we rewrite
    if(somethingChanged) {
      Node cachedRewrite = nodeManager->mkNode(node.getKind(), newChildren);
      d_iteCache[node] = cachedRewrite;
      return cachedRewrite;
    } else {
      d_iteCache[node] = Node::null();
      return node;
    }
  } else {
    d_iteCache[node] = Node::null();
    return node;
  }
}
Example #15
0
PreprocessingPassResult SygusAbduct::applyInternal(
    AssertionPipeline* assertionsToPreprocess)
{
  NodeManager* nm = NodeManager::currentNM();
  Trace("sygus-abduct") << "Run sygus abduct..." << std::endl;

  Trace("sygus-abduct-debug") << "Collect symbols..." << std::endl;
  std::unordered_set<Node, NodeHashFunction> symset;
  std::vector<Node>& asserts = assertionsToPreprocess->ref();
  // do we have any assumptions, e.g. via check-sat-assuming?
  bool usingAssumptions = (assertionsToPreprocess->getNumAssumptions() > 0);
  // The following is our set of "axioms". We construct this set only when the
  // usingAssumptions (above) is true. In this case, our input formula is
  // partitioned into Fa ^ Fc as described in the header of this class, where:
  // - The conjunction of assertions marked as assumptions are the negated
  // conjecture Fc, and
  // - The conjunction of all other assertions are the axioms Fa.
  std::vector<Node> axioms;
  for (size_t i = 0, size = asserts.size(); i < size; i++)
  {
    expr::getSymbols(asserts[i], symset);
    // if we are not an assumption, add it to the set of axioms
    if (usingAssumptions && i < assertionsToPreprocess->getAssumptionsStart())
    {
      axioms.push_back(asserts[i]);
    }
  }
  Trace("sygus-abduct-debug")
      << "...finish, got " << symset.size() << " symbols." << std::endl;

  Trace("sygus-abduct-debug") << "Setup symbols..." << std::endl;
  std::vector<Node> syms;
  std::vector<Node> vars;
  std::vector<Node> varlist;
  std::vector<TypeNode> varlistTypes;
  for (const Node& s : symset)
  {
    TypeNode tn = s.getType();
    if (tn.isFirstClass())
    {
      std::stringstream ss;
      ss << s;
      Node var = nm->mkBoundVar(tn);
      syms.push_back(s);
      vars.push_back(var);
      Node vlv = nm->mkBoundVar(ss.str(), tn);
      varlist.push_back(vlv);
      varlistTypes.push_back(tn);
    }
  }
  Trace("sygus-abduct-debug") << "...finish" << std::endl;

  Trace("sygus-abduct-debug") << "Make abduction predicate..." << std::endl;
  // make the abduction predicate to synthesize
  TypeNode abdType = varlistTypes.empty() ? nm->booleanType()
                                          : nm->mkPredicateType(varlistTypes);
  Node abd = nm->mkBoundVar("A", abdType);
  Trace("sygus-abduct-debug") << "...finish" << std::endl;

  Trace("sygus-abduct-debug") << "Make abduction predicate app..." << std::endl;
  std::vector<Node> achildren;
  achildren.push_back(abd);
  achildren.insert(achildren.end(), vars.begin(), vars.end());
  Node abdApp = vars.empty() ? abd : nm->mkNode(APPLY_UF, achildren);
  Trace("sygus-abduct-debug") << "...finish" << std::endl;

  Trace("sygus-abduct-debug") << "Set attributes..." << std::endl;
  // set the sygus bound variable list
  Node abvl = nm->mkNode(BOUND_VAR_LIST, varlist);
  abd.setAttribute(theory::SygusSynthFunVarListAttribute(), abvl);
  Trace("sygus-abduct-debug") << "...finish" << std::endl;

  Trace("sygus-abduct-debug") << "Make conjecture body..." << std::endl;
  Node input = asserts.size() == 1 ? asserts[0] : nm->mkNode(AND, asserts);
  input = input.substitute(syms.begin(), syms.end(), vars.begin(), vars.end());
  // A(x) => ~input( x )
  input = nm->mkNode(OR, abdApp.negate(), input.negate());
  Trace("sygus-abduct-debug") << "...finish" << std::endl;

  Trace("sygus-abduct-debug") << "Make conjecture..." << std::endl;
  Node res = input.negate();
  if (!vars.empty())
  {
    Node bvl = nm->mkNode(BOUND_VAR_LIST, vars);
    // exists x. ~( A( x ) => ~input( x ) )
    res = nm->mkNode(EXISTS, bvl, res);
  }
  // sygus attribute
  Node sygusVar = nm->mkSkolem("sygus", nm->booleanType());
  theory::SygusAttribute ca;
  sygusVar.setAttribute(ca, true);
  Node instAttr = nm->mkNode(INST_ATTRIBUTE, sygusVar);
  std::vector<Node> iplc;
  iplc.push_back(instAttr);
  if (!axioms.empty())
  {
    Node aconj = axioms.size() == 1 ? axioms[0] : nm->mkNode(AND, axioms);
    aconj =
        aconj.substitute(syms.begin(), syms.end(), vars.begin(), vars.end());
    Trace("sygus-abduct") << "---> Assumptions: " << aconj << std::endl;
    Node sc = nm->mkNode(AND, aconj, abdApp);
    Node vbvl = nm->mkNode(BOUND_VAR_LIST, vars);
    sc = nm->mkNode(EXISTS, vbvl, sc);
    Node sygusScVar = nm->mkSkolem("sygus_sc", nm->booleanType());
    sygusScVar.setAttribute(theory::SygusSideConditionAttribute(), sc);
    instAttr = nm->mkNode(INST_ATTRIBUTE, sygusScVar);
    // build in the side condition
    //   exists x. A( x ) ^ input_axioms( x )
    // as an additional annotation on the sygus conjecture. In other words,
    // the abducts A we procedure must be consistent with our axioms.
    iplc.push_back(instAttr);
  }
  Node instAttrList = nm->mkNode(INST_PATTERN_LIST, iplc);

  Node fbvl = nm->mkNode(BOUND_VAR_LIST, abd);

  // forall A. exists x. ~( A( x ) => ~input( x ) )
  res = nm->mkNode(FORALL, fbvl, res, instAttrList);
  Trace("sygus-abduct-debug") << "...finish" << std::endl;

  res = theory::Rewriter::rewrite(res);

  Trace("sygus-abduct") << "Generate: " << res << std::endl;

  Node trueNode = nm->mkConst(true);

  assertionsToPreprocess->replace(0, res);
  for (size_t i = 1, size = assertionsToPreprocess->size(); i < size; ++i)
  {
    assertionsToPreprocess->replace(i, trueNode);
  }

  return PreprocessingPassResult::NO_CONFLICT;
}
Example #16
0
Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const
{
  Assert(n.getKind() != kind::FORALL && n.getKind() != kind::EXISTS);
  if(n.getKind() == kind::LAMBDA) {
    NodeManager* nm = NodeManager::currentNM();
    Node body = getModelValue(n[1], true);
    // This is a bit ugly, but cache inside simplifier can change, so can't be const
    // The ite simplifier is needed to get rid of artifacts created by Boolean terms
    body = const_cast<ITESimplifier*>(&d_iteSimp)->simpITE(body);
    body = Rewriter::rewrite(body);
    return nm->mkNode(kind::LAMBDA, n[0], body);
  }
  if(n.isConst() || (hasBoundVars && n.getKind() == kind::BOUND_VARIABLE)) {
    return n;
  }

  TypeNode t = n.getType();
  if (t.isFunction() || t.isPredicate()) {
    if (d_enableFuncModels) {
      std::map< Node, Node >::const_iterator it = d_uf_models.find(n);
      if (it != d_uf_models.end()) {
        // Existing function
        return it->second;
      }
      // Unknown function symbol: return LAMBDA x. c, where c is the first constant in the enumeration of the range type
      vector<TypeNode> argTypes = t.getArgTypes();
      vector<Node> args;
      NodeManager* nm = NodeManager::currentNM();
      for (unsigned i = 0; i < argTypes.size(); ++i) {
        args.push_back(nm->mkBoundVar(argTypes[i]));
      }
      Node boundVarList = nm->mkNode(kind::BOUND_VAR_LIST, args);
      TypeEnumerator te(t.getRangeType());
      return nm->mkNode(kind::LAMBDA, boundVarList, *te);
    }
    // TODO: if func models not enabled, throw an error?
    Unreachable();
  }

  if (n.getNumChildren() > 0) {
    std::vector<Node> children;
    if (n.getKind() == APPLY_UF) {
      Node op = getModelValue(n.getOperator(), hasBoundVars);
      children.push_back(op);
    }
    else if (n.getMetaKind() == kind::metakind::PARAMETERIZED) {
      children.push_back(n.getOperator());
    }
    //evaluate the children
    for (unsigned i = 0; i < n.getNumChildren(); ++i) {
      Node val = getModelValue(n[i], hasBoundVars);
      children.push_back(val);
    }
    Node val = Rewriter::rewrite(NodeManager::currentNM()->mkNode(n.getKind(), children));
    Assert(hasBoundVars || val.isConst());
    return val;
  }

  if (!d_equalityEngine.hasTerm(n)) {
    // Unknown term - return first enumerated value for this type
    TypeEnumerator te(n.getType());
    return *te;
  }
  Node val = d_equalityEngine.getRepresentative(n);
  Assert(d_reps.find(val) != d_reps.end());
  std::map< Node, Node >::const_iterator it = d_reps.find( val );
  if( it!=d_reps.end() ){
    return it->second;
  }else{
    return Node::null();
  }
}
Example #17
0
Node NaryBuilder::mkAssoc(Kind kind, const std::vector<Node>& children){
  if(children.size() == 0){
    return zeroArity(kind);
  }else if(children.size() == 1){
    return children[0];
  }else{
    const unsigned int max = kind::metakind::getUpperBoundForKind(kind);
    const unsigned int min = kind::metakind::getLowerBoundForKind(kind);

    Assert(min <= children.size());

    unsigned int numChildren = children.size();
    NodeManager* nm = NodeManager::currentNM();
    if( numChildren <= max ) {
      return nm->mkNode(kind,children);
    }

    typedef std::vector<Node>::const_iterator const_iterator;
    const_iterator it = children.begin() ;
    const_iterator end = children.end() ;

    /* The new top-level children and the children of each sub node */
    std::vector<Node> newChildren;
    std::vector<Node> subChildren;

    while( it != end && numChildren > max ) {
      /* Grab the next max children and make a node for them. */
      for(const_iterator next = it + max; it != next; ++it, --numChildren ) {
        subChildren.push_back(*it);
      }
      Node subNode = nm->mkNode(kind,subChildren);
      newChildren.push_back(subNode);
      subChildren.clear();
    }

    /* If there's children left, "top off" the Expr. */
    if(numChildren > 0) {
      /* If the leftovers are too few, just copy them into newChildren;
       * otherwise make a new sub-node  */
      if(numChildren < min) {
        for(; it != end; ++it) {
          newChildren.push_back(*it);
        }
      } else {
        for(; it != end; ++it) {
          subChildren.push_back(*it);
        }
        Node subNode = nm->mkNode(kind, subChildren);
        newChildren.push_back(subNode);
      }
    }

    /* It's inconceivable we could have enough children for this to fail
     * (more than 2^32, in most cases?). */
    AlwaysAssert( newChildren.size() <= max,
                  "Too many new children in mkAssociative" );

    /* It would be really weird if this happened (it would require
     * min > 2, for one thing), but let's make sure. */
    AlwaysAssert( newChildren.size() >= min,
                  "Too few new children in mkAssociative" );

    return nm->mkNode(kind,newChildren);
  }
}
Example #18
0
Node PseudoBooleanProcessor::mkGeqOne(Node v)
{
  NodeManager* nm = NodeManager::currentNM();
  return nm->mkNode(kind::GEQ, v, mkRationalNode(Rational(1)));
}
Example #19
0
Node BVToBool::convertBvTerm(TNode node)
{
  Assert(node.getType().isBitVector()
         && node.getType().getBitVectorSize() == 1);

  if (hasBoolCache(node)) return getBoolCache(node);

  NodeManager* nm = NodeManager::currentNM();

  if (!isConvertibleBvTerm(node))
  {
    ++(d_statistics.d_numTermsForcedLifted);
    Node result = nm->mkNode(kind::EQUAL, node, d_one);
    addToBoolCache(node, result);
    Debug("bv-to-bool") << "BVToBool::convertBvTerm " << node << " => "
                        << result << "\n";
    return result;
  }

  if (node.getNumChildren() == 0)
  {
    Assert(node.getKind() == kind::CONST_BITVECTOR);
    Node result = node == d_one ? bv::utils::mkTrue() : bv::utils::mkFalse();
    // addToCache(node, result);
    Debug("bv-to-bool") << "BVToBool::convertBvTerm " << node << " => "
                        << result << "\n";
    return result;
  }

  ++(d_statistics.d_numTermsLifted);

  Kind kind = node.getKind();
  if (kind == kind::ITE)
  {
    Node cond = liftNode(node[0]);
    Node true_branch = convertBvTerm(node[1]);
    Node false_branch = convertBvTerm(node[2]);
    Node result = nm->mkNode(kind::ITE, cond, true_branch, false_branch);
    addToBoolCache(node, result);
    Debug("bv-to-bool") << "BVToBool::convertBvTerm " << node << " => "
                        << result << "\n";
    return result;
  }

  Kind new_kind;
  // special case for XOR as it has to be binary
  // while BITVECTOR_XOR can be n-ary
  if (kind == kind::BITVECTOR_XOR)
  {
    new_kind = kind::XOR;
    Node result = convertBvTerm(node[0]);
    for (unsigned i = 1; i < node.getNumChildren(); ++i)
    {
      Node converted = convertBvTerm(node[i]);
      result = nm->mkNode(kind::XOR, result, converted);
    }
    Debug("bv-to-bool") << "BVToBool::convertBvTerm " << node << " => "
                        << result << "\n";
    return result;
  }

  if (kind == kind::BITVECTOR_COMP)
  {
    Node result = nm->mkNode(kind::EQUAL, node[0], node[1]);
    addToBoolCache(node, result);
    Debug("bv-to-bool") << "BVToBool::convertBvTerm " << node << " => "
                        << result << "\n";
    return result;
  }

  switch (kind)
  {
    case kind::BITVECTOR_OR: new_kind = kind::OR; break;
    case kind::BITVECTOR_AND: new_kind = kind::AND; break;
    case kind::BITVECTOR_NOT: new_kind = kind::NOT; break;
    default: Unhandled();
  }

  NodeBuilder<> builder(new_kind);
  for (unsigned i = 0; i < node.getNumChildren(); ++i)
  {
    builder << convertBvTerm(node[i]);
  }

  Node result = builder;
  addToBoolCache(node, result);
  Debug("bv-to-bool") << "BVToBool::convertBvTerm " << node << " => " << result
                      << "\n";
  return result;
}
Example #20
0
// static
RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
  NodeManager* nm = NodeManager::currentNM();

  switch(node.getKind()) {

  case kind::IN: {
    if(!node[0].isConst() || !node[1].isConst())
      break;

    // both are constants
    bool isMember = checkConstantMembership(node[0], node[1]);
    return RewriteResponse(REWRITE_DONE, nm->mkConst(isMember));
  }

  case kind::SUBSET: {
    // rewrite (A subset-or-equal B) as (A union B = B)
    TNode A = node[0];
    TNode B = node[1];
    return RewriteResponse(REWRITE_AGAIN,
                           nm->mkNode(kind::EQUAL,
                                      nm->mkNode(kind::UNION, A, B),
                                      B) );
  }//kind::SUBSET

  case kind::EQUAL:
  case kind::IFF: {
    //rewrite: t = t with true (t term)
    //rewrite: c = c' with c different from c' false (c, c' constants)
    //otherwise: sort them
    if(node[0] == node[1]) {
      Trace("sets-postrewrite") << "Sets::postRewrite returning true" << std::endl;
      return RewriteResponse(REWRITE_DONE, nm->mkConst(true));
    }
    else if (node[0].isConst() && node[1].isConst()) {
      Trace("sets-postrewrite") << "Sets::postRewrite returning false" << std::endl;
      return RewriteResponse(REWRITE_DONE, nm->mkConst(false));
    }
    else if (node[0] > node[1]) {
      Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
      Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
      return RewriteResponse(REWRITE_DONE, newNode);
    }
    break;
  }

  case kind::UNION:
  case kind::INTERSECTION: {
    if(node[0] == node[1]) {
      Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
      return RewriteResponse(REWRITE_DONE, node[0]);
    } else if (node[0] > node[1]) {
      Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
      Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
      return RewriteResponse(REWRITE_DONE, newNode);
    }
    break;
  }

  default:
    break;

  }//switch(node.getKind())

  // This default implementation
  return RewriteResponse(REWRITE_DONE, node);
}