示例#1
0
  // Does some simple caching of prior results.
  void
  Cpp_interface::checkSat(const ASTVec & assertionsSMT2)
  {
    if (ignoreCheckSatRequest)
      return;

    bm.GetRunTimes()->stop(RunTimes::Parsing);

    checkInvariant();
    assert(assertionsSMT2.size() == cache.size());

    Entry& last_run = cache.back();
    if ((last_run.node_number != assertionsSMT2.back().GetNodeNum()) && (last_run.result == SOLVER_SATISFIABLE))
      {
        // extra asserts might have been added to it,
        // flipping from sat to unsat. But never from unsat to sat.
        last_run.result =  SOLVER_UNDECIDED;
      }

    // We might have run this query before, or it might already be shown to be unsat. If it was sat,
    // we've stored the result (but not the model), so we can shortcut and return what we know.
    if (!((last_run.result == SOLVER_SATISFIABLE) || last_run.result == SOLVER_UNSATISFIABLE))
        {
          resetSolver();

          ASTNode query;

          if (assertionsSMT2.size() > 1)
            query = nf->CreateNode(AND, assertionsSMT2);
          else if (assertionsSMT2.size() == 1)
            query = assertionsSMT2[0];
          else
            query = bm.ASTTrue;

          SOLVER_RETURN_TYPE last_result = GlobalSTP->TopLevelSTP(query, bm.ASTFalse);

          // Store away the answer. Might be timeout, or error though..
          last_run = Entry(last_result);
          last_run.node_number = assertionsSMT2.back().GetNodeNum();

          // It's satisfiable, so everything beneath it is satisfiable too.
          if (last_result == SOLVER_SATISFIABLE)
            {
              for (int i = 0; i < cache.size(); i++)
                {
                  assert(cache[i].result != SOLVER_UNSATISFIABLE);
                  cache[i].result = SOLVER_SATISFIABLE;
                }
            }
        }

    if (bm.UserFlags.quick_statistics_flag)
      {
        bm.GetRunTimes()->print();
      }

    (GlobalSTP->tosat)->PrintOutput(last_run.result);
    bm.GetRunTimes()->start(RunTimes::Parsing);
  }
bool PropagateEqualities::searchTerm(const ASTNode& lhs, const ASTNode& rhs)
{
  const unsigned width = lhs.GetValueWidth();

  if (lhs == rhs)
    return true;

  if (lhs.GetKind() == SYMBOL)
    return simp->UpdateSubstitutionMap(lhs, rhs); // checks whether it's been
                                                  // solved for, or if the RHS
                                                  // contains the LHS.

  if (lhs.GetKind() == BVUMINUS)
    return searchTerm(lhs[0], nf->CreateTerm(BVUMINUS, width, rhs));

  if (lhs.GetKind() == BVNEG)
    return searchTerm(lhs[0], nf->CreateTerm(BVNEG, width, rhs));

  if (lhs.GetKind() == BVXOR || lhs.GetKind() == BVPLUS)
    for (size_t i = 0; i < lhs.Degree(); i++)
    {
      ASTVec others;
      for (size_t j = 0; j < lhs.Degree(); j++)
        if (j != i)
          others.push_back(lhs[j]);

      ASTNode new_rhs;
      if (lhs.GetKind() == BVXOR)
      {
        others.push_back(rhs);
        assert(others.size() > 1);
        new_rhs = nf->CreateTerm(lhs.GetKind(), width, others);
      }
      else if (lhs.GetKind() == BVPLUS)
      {
        if (others.size() > 1)
          new_rhs = nf->CreateTerm(BVPLUS, width, others);
        else
          new_rhs = others[0];

        new_rhs = nf->CreateTerm(BVUMINUS, width, new_rhs);
        new_rhs = nf->CreateTerm(BVPLUS, width, new_rhs, rhs);
      }
      else
        FatalError("sdafasfsdf2q3234423");

      bool result = searchTerm(lhs[i], new_rhs);
      if (result)
        return true;
    }

  if (lhs.Degree() == 2 && lhs.GetKind() == BVMULT && lhs[0].isConstant() &&
      simp->BVConstIsOdd(lhs[0]))
    return searchTerm(lhs[1],
                      nf->CreateTerm(BVMULT, width,
                                     simp->MultiplicativeInverse(lhs[0]), rhs));

  return false;
}
示例#3
0
ASTNode NodeFactory::CreateTerm(Kind kind, unsigned int width,
                                const ASTNode& child0, const ASTVec &children)
{
    ASTVec child;
    child.reserve(children.size() + 1);
    child.push_back(child0);
    child.insert(child.end(), children.begin(), children.end());
    return CreateTerm(kind, width, child);
}
示例#4
0
ASTNode NodeFactory::CreateNode(Kind kind, const ASTNode& child0,
                                const ASTVec & back_children)
{
    ASTVec front_children;
    front_children.reserve(1 + back_children.size());
    front_children.push_back(child0);
    front_children.insert(front_children.end(), back_children.begin(),
                          back_children.end());
    return CreateNode(kind, front_children);
}
bool PropagateEqualities::searchXOR(const ASTNode& lhs, const ASTNode& rhs)
{
  Kind k = lhs.GetKind();

  if (lhs == rhs)
    return true;

  if (k == SYMBOL)
    return simp->UpdateSubstitutionMap(
        lhs, rhs); // checks whether it's been solved for or loops.

  if (k == NOT)
    return searchXOR(lhs[0], nf->CreateNode(NOT, rhs));

  bool result = false;
  if (k == XOR)
    for (size_t i = 0; i < lhs.Degree(); i++)
    {
      ASTVec others;
      for (size_t j = 0; j < lhs.Degree(); j++)
        if (j != i)
          others.push_back(lhs[j]);

      others.push_back(rhs);
      assert(others.size() > 1);
      ASTNode new_rhs = nf->CreateNode(XOR, others);

      result = searchXOR(lhs[i], new_rhs);
      if (result)
        return result;
    }

  if (k == EQ && lhs[0].GetValueWidth() == 1)
  {
    bool result =
        searchTerm(lhs[0], nf->CreateTerm(ITE, 1, rhs, lhs[1],
                                          nf->CreateTerm(BVNEG, 1, lhs[1])));

    if (!result)
      result =
          searchTerm(lhs[1], nf->CreateTerm(ITE, 1, rhs, lhs[0],
                                            nf->CreateTerm(BVNEG, 1, lhs[0])));
  }

  return result;
}
示例#6
0
  /* The most complicated handling is for EXTRACTS. If a variable has parents that
 * are all extracts and each of those extracts is disjoint (i.e. reads different bits)
 * Then each of the extracts are replaced by a fresh variable. This is the only case
 * where a variable with multiple distinct parents is replaced by a fresh variable.
 * + We perform this check upfront, so will miss any extra cases the the unconstrained
 *   variable elimination introduces.
 * + It's all or nothing. So even if there's an extract of [0:2] [1:2] and [3:5], we wont
 *   replace the [3:5] (even though it could be).
 */
  void
  RemoveUnconstrained::splitExtractOnly(vector<MutableASTNode*> extracts)
  {
    assert(extracts.size() >0);

    // Going to be rebuilt later anyway, so discard.
    vector<MutableASTNode*> variables;

    for (int i =0; i <extracts.size(); i++)
      {
        ASTNode& var = extracts[i]->n;
        assert(var.GetKind() == SYMBOL);
        const int size = var.GetValueWidth();
        std::vector<ASTNode> toVar(size);

        // Create a mutable copy that we can iterate over.
        vector <MutableASTNode*> mut;
        mut.insert(mut.end(), extracts[i]->parents.begin(), extracts[i]->parents.end());

        for (vector<MutableASTNode*>::iterator it = mut.begin(); it != mut.end(); it++)
          {
            ASTNode parent_node = (*it)->n;
            assert(((**it)).children[0] == extracts[i]);
            assert(!parent_node.IsNull());
            assert(parent_node.GetKind() == BVEXTRACT);

            int lb = parent_node[2].GetUnsignedConst();
            // Replace each parent with a fresh.
            toVar[lb] = replaceParentWithFresh(**it,variables);
          }

      ASTVec concatVec;
      int empty =0;
      for (int j=0; j < size;j++)
      {
          if (toVar[j].IsNull())
            {
              empty++;
              continue;
            }

          if (empty > 0)
            {
              concatVec.push_back(bm.CreateFreshVariable(0, empty, "extract_unc"));
              empty = 0;
            }

          concatVec.push_back(toVar[j]);
          //cout << toVar[j];
          assert(toVar[j].GetValueWidth() > 0);
          j+=toVar[j].GetValueWidth()-1;
        }

      if (empty> 0)
        {
          concatVec.push_back(bm.CreateFreshVariable(0, empty, "extract_unc"));
        }

    ASTNode concat = concatVec[0];
    for (int i=1; i < concatVec.size();i++)
      {
          assert(!concat.IsNull());
          concat = bm.CreateTerm(BVCONCAT, concat.GetValueWidth() + concatVec[i].GetValueWidth(),concatVec[i], concat);
      }

    replace(var,concat);
        }
  }
示例#7
0
  ASTNode
  RemoveUnconstrained::topLevel_other(const ASTNode &n, Simplifier *simplifier)
  {
    if (n.GetKind() == SYMBOL)
      return n; // top level is an unconstrained symbol/.

    simplifier_convenient = simplifier;

    ASTNodeSet noCheck; // We don't want to check some expensive nodes over and over again.

    vector<MutableASTNode*> variable_array;

    MutableASTNode* topMutable = MutableASTNode::build(n);

    vector<MutableASTNode*> extracts;
    topMutable->getDisjointExtractVariables(extracts);
    if (extracts.size() > 0)
      {
          splitExtractOnly(extracts);
      }

    topMutable->getAllUnconstrainedVariables(variable_array);

    for (int i =0; i < variable_array.size() ; i++)
      {
        // Don't make this is a reference. If the vector gets resized, it will point to
        // memory that no longer contains the object.
        MutableASTNode& muteNode = *variable_array[i];

        const ASTNode var = muteNode.n;
        assert(var.GetKind() == SYMBOL);

        if (!muteNode.isUnconstrained())
          continue;

        MutableASTNode& muteParent = muteNode.getParent();

        if (noCheck.find(muteParent.n) != noCheck.end())
          {
            continue;
          }

        vector <MutableASTNode*> mutable_children = muteParent.children;

        //nb. The children might be dirty. i.e. not have substitutions written through them yet.
        ASTVec children;
        children.reserve(mutable_children.size());
        for (int j = 0; j <mutable_children.size(); j++ )
          children.push_back(mutable_children[j]->n);

        const size_t numberOfChildren = children.size();
        const Kind kind = muteNode.getParent().n.GetKind();
        unsigned width = muteNode.getParent().n.GetValueWidth();
        unsigned indexWidth = muteNode.getParent().n.GetIndexWidth();

        ASTNode other;
        MutableASTNode* muteOther;

          if(numberOfChildren == 2)
          {
            if (children[0] != var)
              {
                other = children[0];
                muteOther = mutable_children[0];
              }
            else
              {
                other = children[1];
                muteOther = mutable_children[1];
              }

            if (kind != AND && kind != OR && kind != BVOR && kind != BVAND)
              if (other == var)
                continue; // Most rules don't like duplicate variables.
          }
        else
          {
            if (kind != AND && kind != OR && kind != BVOR && kind != BVAND)
              {
                  int found = 0;

                  for (int i = 0; i < numberOfChildren; i++)
                    {
                      if (children[i] == var)
                        found++;
                   }

                    if (found != 1)
                      continue; // Most rules don't like duplicate variables.
              }
          }

          /*
          cout << i << " " << kind << " " << variable_array.size() <<  " " << mutable_children.size() << endl;
          cout << "children[0]" << children[0] << endl;
          cout << "children[1]" << children[1] << endl;
          cout << muteParent.n << endl;

           */

        switch (kind)
          {
        case BVCONCAT:
          assert(numberOfChildren == 2);
          if (mutable_children[0]->isUnconstrained() && (mutable_children[1]->isUnconstrained()))
            {
              ASTNode v =replaceParentWithFresh(muteParent, variable_array);

              ASTNode top_lhs = bm.CreateBVConst(32, width - 1);
              ASTNode bottom_lhs = bm.CreateBVConst(32, children[1].GetValueWidth());

              ASTNode top_rhs = bm.CreateBVConst(32, children[1].GetValueWidth()- 1);
              ASTNode bottom_rhs = bm.CreateBVConst(32, 0);

              ASTNode lhs = nf->CreateTerm(BVEXTRACT, children[0].GetValueWidth(), v,top_lhs, bottom_lhs);
              ASTNode rhs = nf->CreateTerm(BVEXTRACT, children[1].GetValueWidth(), v,top_rhs, bottom_rhs);

              replace(children[0],lhs);
              replace(children[1],rhs);
            }
          break;
        case NOT:
          {
            ASTNode v =replaceParentWithFresh(muteParent, variable_array);
            replace(children[0], nf->CreateNode(NOT, v));
          }
          break;

        case BVUMINUS:
        case BVNEG:
          {
            assert(numberOfChildren ==1);
            ASTNode v =replaceParentWithFresh(muteParent, variable_array);
            replace(var, nf->CreateTerm(kind, width,v));
          }
          break;

        case BVSGT:
        case BVSGE:
        case BVGT:
        case BVGE:
          {
            width = var.GetValueWidth();
            if (width ==1)
              continue; // Hard to get right, not used often.

            ASTNode biggestNumber, smallestNumber;

            if (kind == BVSGT || kind == BVSGE)
              {
                // 011111111 (most positive number.)
                CBV max = CONSTANTBV::BitVector_Create(width, false);
                CONSTANTBV::BitVector_Fill(max);
                CONSTANTBV::BitVector_Bit_Off(max, width - 1);
                biggestNumber = bm.CreateBVConst(max, width);

                // 1000000000 (most negative number.)
                max = CONSTANTBV::BitVector_Create(width, true);
                CONSTANTBV::BitVector_Bit_On(max, width - 1);
                smallestNumber = bm.CreateBVConst(max, width);
              }
            else if (kind == BVGT || kind == BVGE)
              {
                biggestNumber = bm.CreateMaxConst(width);
                smallestNumber =  bm.CreateZeroConst(width);
              }
            else
              FatalError("SDFA!@S");


            ASTNode c1,c2;
            if (kind == BVSGT || kind == BVGT)
              {
                c1= biggestNumber;
                c2 = smallestNumber;
              }
            else if (kind == BVSGE || kind == BVGE)
              {
                c1= smallestNumber;
                c2 = biggestNumber;
              }
            else
              FatalError("SDFA!@S");

            if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode lhs = nf->CreateTerm(ITE, width, v, bm.CreateOneConst(width), bm.CreateZeroConst(width));
                ASTNode rhs = nf->CreateTerm(ITE, width, v, bm.CreateZeroConst(width), bm.CreateOneConst(width));
                replace(children[0], lhs);
                replace(children[1], rhs);
              }
            else if (children[0] == var && children[1].isConstant())
              {
                if (children[1] == c1)
                  continue; // always false. Or always false.

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateTerm(ITE, width, v,biggestNumber, smallestNumber);
                replace(var, rhs);
              }
            else if (children[1] == var && children[0].isConstant())
              {
                if (children[0] == c2)
                  continue;  // always false. Or always false.

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber);
                replace(var, rhs);
              }
            else // One side is a variable. The other is anything.
              {
            	 bool varOnLHS = (var == children[0]);

                // All the ASTNode vars need to map to their existing MutableASTNodes. So we collect all the variables
                vector<MutableASTNode*> vars;
                set<MutableASTNode*> visited;
                muteOther->getAllVariablesRecursively(vars, visited);
                visited.clear();

                map<ASTNode, MutableASTNode *> create;
                for (vector<MutableASTNode*>::iterator it = vars.begin(); it != vars.end();it++)
                  create.insert(make_pair((*it)->n, *it));
                vars.clear();

                ASTNode v= bm.CreateFreshVariable(0, 0, "STP_INTERNAL_comparison");

                ASTNode rhs;
                ASTNode n;
                if (varOnLHS)
                  {
                    rhs = nf->CreateTerm(ITE, width, v, biggestNumber, smallestNumber);

                    if (kind == BVSGE || kind == BVGE)
                      n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1));
                    else
                      n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[1]->toASTNode(nf), c1)));
                  }
                else
                  {
                    rhs = nf->CreateTerm(ITE, width, v, smallestNumber, biggestNumber);

                    if (kind == BVSGE || kind == BVGE)
                      n= nf->CreateNode(OR, v, nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2));
                    else
                      n= nf->CreateNode(AND, v, nf->CreateNode(NOT,nf->CreateNode(EQ, mutable_children[0]->toASTNode(nf), c2)));
                  }
                replace(var, rhs);
                MutableASTNode *newN = MutableASTNode::build(n,create);
                muteParent.replaceWithAnotherNode(newN);
                //assert(muteParent.checkInvariant());
              }
          }
          break;


        case AND:
        case OR:
        case BVOR:
        case BVAND:
          {
            if (allChildrenAreUnconstrained(mutable_children))
              {
                ASTNodeSet already;
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                for (int i =0; i < numberOfChildren;i++)
                  {
                    /* to avoid problems with:
                    734:(AND
                    732:unconstrained_4
                    716:unconstrained_2
                    732:unconstrained_4)
                    */
                    if (already.find(children[i]) == already.end())
                      {
                        replace(children[i], v);
                        already.insert(children[i]);
                      }
                  }
              }
            else
              {
                // Hack. ff.stp has a 325k node conjunction
                // So we check if all the children are unconstrained each time
                // we find a new unconstrained conjunct. This means that if
                // eventually all the nodes become unconstrained we will miss it
                // and not rewrite the AND to a fresh unconstrained variable.

                if (mutable_children.size() > 200)
                  noCheck.insert(muteParent.n);
              }
          }
          break;

        case XOR:
        case BVXOR:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTVec others;
                for (int i = 0; i < numberOfChildren; i++)
                {
                    if (children[i] !=var)
                        others.push_back(mutable_children[i]->toASTNode(nf));
                }
                assert(others.size() +1 == numberOfChildren);
                assert(others.size() >=1);

                if (kind == XOR)
              {
                ASTNode xorNode = nf->CreateNode(XOR, others);
                replace(var, nf->CreateNode(XOR, v, xorNode));
              }
            else
              {
                ASTNode xorNode ;
                if (others.size() > 1 )
                  xorNode = nf->CreateTerm(BVXOR, width, others);
                else
                  xorNode = others[0];

                replace(var, nf->CreateTerm(BVXOR, width, v, xorNode));
              }
              }
           break;

        case ITE:
              {
                if (indexWidth > 0)
                  continue; // don't do arrays.

                if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && children[0] != children[1])
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.ASTTrue);
                    replace(children[1], v);

                  }
                else if (mutable_children[0]->isUnconstrained() && mutable_children[2]->isUnconstrained() && children[0] != children[2])
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.ASTFalse);
                    replace(children[2], v);
                  }
                else if (mutable_children[1]->isUnconstrained() && mutable_children[2]->isUnconstrained())
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[1], v);
                    if (children[1] != children[2])
                      replace(children[2], v);
                  }
              }
              break;
        case BVLEFTSHIFT:
        case BVRIGHTSHIFT:
        case BVSRSHIFT:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
                  {
                     assert(children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateZeroConst(width));
                     replace(children[0], v);
                  }
              }
             break;

        case BVMOD:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained() && bm.UserFlags.isSet("unconstrained-bvmod", "0") )
                  {
                     assert (children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateZeroConst(width));
                     replace(children[0], v);
                  }
              }
             break;


        case BVDIV:
             {
                 assert(numberOfChildren == 2);
                 if (mutable_children[0]->isUnconstrained() && mutable_children[1]->isUnconstrained())
                  {
                     assert (children[0] != children[1]);
                     ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                     replace(children[1], bm.CreateOneConst(width));
                     replace(children[0], v);
                  }
              }
             break;
        case BVMULT:
              {
                 assert(numberOfChildren == 2);

                if (mutable_children[1]->isUnconstrained() && mutable_children[0]->isUnconstrained()) // both are unconstrained
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    replace(children[0], bm.CreateOneConst(width));
                    replace(children[1], v);
                  }

                if (other.isConstant() && simplifier->BVConstIsOdd(other))
                  {
                    ASTNode v =replaceParentWithFresh(muteParent, variable_array);
                    ASTNode inverse = simplifier->MultiplicativeInverse(other);
                    ASTNode rhs = nf->CreateTerm(BVMULT, width, inverse, v);
                    replace(var, rhs);
                  }

                break;
        case IFF:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs = nf->CreateNode(ITE, v, muteOther->toASTNode(nf), nf->CreateNode(NOT, muteOther->toASTNode(nf)));
                replace(var, rhs);
              }
          break;
        case EQ:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                width = var.GetValueWidth();
                ASTNode rhs = nf->CreateTerm(ITE, width, v, muteOther->toASTNode(nf), nf->CreateTerm(BVPLUS, width, muteOther->toASTNode(nf),
                    bm.CreateOneConst(width)));

                replace(var, rhs);
              }
          break;
        case BVSUB:
          {
            assert(numberOfChildren == 2);

            ASTNode v =replaceParentWithFresh(muteParent, variable_array);

            ASTNode rhs;

            if (children[0] == var)
              rhs= nf->CreateTerm(BVPLUS, width, v, muteOther->toASTNode(nf));
            if (children[1] == var)
              rhs= nf->CreateTerm(BVSUB, width, muteOther->toASTNode(nf), v);

            replace(var, rhs);
          }
          break;

        case BVPLUS:
              {
                ASTVec other;
                for (int i = 0; i < children.size(); i++)
                  if (children[i] != var)
                    other.push_back(mutable_children[i]->toASTNode(nf));

                assert(other.size() == children.size()-1);
                assert(other.size() >=1);

                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                ASTNode rhs;
                if (other.size() > 1)
                  rhs = nf->CreateTerm(BVSUB, width, v, nf->CreateTerm(BVPLUS, width, other));
                else
                  rhs = nf->CreateTerm(BVSUB, width, v, other[0]);

                replace(var, rhs);
              }
           break;
        case BVEXTRACT:
              {
                ASTNode v =replaceParentWithFresh(muteParent, variable_array);

                const unsigned resultWidth = width;
                const unsigned operandWidth = var.GetValueWidth();
                assert(children[0] == var); // It can't be anywhere else.

                // Create Fresh variables to pad the LHS and RHS.
                const unsigned high = children[1].GetUnsignedConst();
                const unsigned low = children[2].GetUnsignedConst();
                assert(high >=low);

                const int rhsSize = low;
                const int lhsSize = operandWidth - high - 1;

                ASTNode current = v;
                int newWidth = v.GetValueWidth();

                if (lhsSize > 0)
                  {
                    ASTNode lhsFresh = bm.CreateFreshVariable(0, lhsSize, "lhs_padding");
                    current = nf->CreateTerm(BVCONCAT, newWidth + lhsSize, lhsFresh, current);
                    newWidth += lhsSize;
                  }

                if (rhsSize > 0)
                  {
                    ASTNode rhsFresh = bm.CreateFreshVariable(0, rhsSize, "rhs_padding");
                    current = nf->CreateTerm(BVCONCAT, newWidth + rhsSize, current, rhsFresh);
                    newWidth += rhsSize;
                  }

                assert(newWidth == operandWidth);
                replace(var, current);
              }
        break;
        default:
          {
            //cerr << "!!!!" << kind << endl;
          }

            //        cerr << var;
              //      cerr << parent;

              }
          }
      }

    ASTNode result = topMutable->toASTNode(nf);
    topMutable->cleanup();
    //cout << result;
    return result;
  }
示例#8
0
  //UserGuided abstraction refinement
  SOLVER_RETURN_TYPE
  STP::
  UserGuided_AbsRefine(SATSolver& NewSolver,
		       const ASTNode& original_input)
  {
    ASTVec v = bm->GetAsserts_WithKey(0);
    if(v.empty())
      {
	FatalError("UserGuided_AbsRefine: Something is seriously wrong."\
		   "The input set is empty");
      }
    ASTNode sureAddInput = 
      (v.size() == 1) ? v[0] : bm->CreateNode(AND, v); 

    SOLVER_RETURN_TYPE res = SOLVER_UNDECIDED;
    res = TopLevelSTPAux(NewSolver, sureAddInput, original_input);
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }
    
    //Do refinement here
    if(AND != original_input.GetKind())
      {
	FatalError("UserGuided_AbsRefine: The input must be an AND");
      }

    ASTVec RefineFormulasVec;
    ASTVec RemainingFormulasVec;
    ASTNode asttrue = bm->CreateNode(TRUE);
    ASTNode astfalse = bm->CreateNode(FALSE);
    for(int count=0; count < bm->UserFlags.num_absrefine; count++)
      {
	RemainingFormulasVec.clear();
	RemainingFormulasVec.push_back(asttrue);
	RefineFormulasVec.clear();	
	RefineFormulasVec.push_back(asttrue);
	ASTVec InputKids = original_input.GetChildren();
	for(ASTVec::iterator it = InputKids.begin(), itend = InputKids.end();
	    it!=itend;it++)
	  {
	    Ctr_Example->ClearComputeFormulaMap();
	    if(astfalse == Ctr_Example->ComputeFormulaUsingModel(*it))
	      {
		RefineFormulasVec.push_back(*it);
	      }
	    else
	      {
		RemainingFormulasVec.push_back(*it);
	      }
	  }
	ASTNode RefineFormulas =
	  (RefineFormulasVec.size() == 1) ?
	  RefineFormulasVec[0] : bm->CreateNode(AND, RefineFormulasVec);
	res = TopLevelSTPAux(NewSolver, RefineFormulas, original_input);
	if(SOLVER_UNDECIDED != res)
	  {
	    return res;
	  }
      }

    ASTNode RemainingFormulas = 
      (RemainingFormulasVec.size() == 1) ?
      RemainingFormulasVec[0] : bm->CreateNode(AND, RemainingFormulasVec);
    res = TopLevelSTPAux(NewSolver, RemainingFormulas, original_input);
    
    if(SOLVER_UNDECIDED != res)
      {
	return res;
      }
    
    FatalError("TopLevelSTPAux: reached the end without proper conclusion:"
	       "either a divide by zero in the input or a bug in STP");    
    return SOLVER_ERROR;
  } //End of UserGuided_AbsRefine()
示例#9
0
int main(int argc, char** argv)
{
    extern int smt2parse();
    extern int smt2lex_destroy(void);
    extern FILE* smt2in;

    STPMgr stp;
    STPMgr* mgr = &stp;

    Cpp_interface interface(*mgr, mgr->defaultNodeFactory);
    interface.startup();
    interface.ignoreCheckSat();
    stp::GlobalParserInterface = &interface;

    Simplifier* simp = new Simplifier(mgr);
    ArrayTransformer* at = new ArrayTransformer(mgr, simp);
    AbsRefine_CounterExample* abs = new AbsRefine_CounterExample(mgr, simp, at);
    ToSATAIG* tosat = new ToSATAIG(mgr, at);

    GlobalSTP = new STP(mgr, simp, at, tosat, abs);

    srand(time(NULL));
    stp::GlobalParserBM = &stp;

    stp.UserFlags.disableSimplifications();
    stp.UserFlags.bitConstantProp_flag = true;

    // Parse SMTLIB2-----------------------------------------
    mgr->GetRunTimes()->start(RunTimes::Parsing);
    if (argc > 1)
    {
        smt2in = fopen(argv[1], "r");
        smt2parse();
    }
    else
    {
        smt2in = NULL; // from stdin.
        smt2parse();
    }
    smt2lex_destroy();
    //-----------------------------------------------------

    ASTNode n;

    ASTVec v = interface.GetAsserts();
    if (v.size() > 1)
        n = interface.CreateNode(AND, v);
    else
        n = v[0];

    // Apply cbitp ----------------------------------------
    simplifier::constantBitP::ConstantBitPropagation cb(
        simp, mgr->defaultNodeFactory, n);
    if (cb.isUnsatisfiable())
        n = mgr->ASTFalse;
    else
        n = cb.topLevelBothWays(n, true, true);

    if (simp->hasUnappliedSubstitutions())
    {
        n = simp->applySubstitutionMap(n);
        simp->haveAppliedSubstitutionMap();
    }

    // Print back out.
    printer::SMTLIB2_PrintBack(cout, n);
    cout << "(check-sat)\n";
    cout << "(exit)\n";
    return 0;
}
// This doesn't rewrite changes through properly so needs to have a substitution
// applied to its output.
ASTNode PropagateEqualities::propagate(const ASTNode& a, ArrayTransformer* at)
{
  ASTNode output;
  // if the variable has been solved for, then simply return it
  if (simp->InsideSubstitutionMap(a, output))
    return output;

  if (!alreadyVisited.insert(a.GetNodeNum()).second)
  {
    return a;
  }

  output = a;

  // traverse a and populate the SubstitutionMap
  const Kind k = a.GetKind();
  if (SYMBOL == k && BOOLEAN_TYPE == a.GetType())
  {
    bool updated = simp->UpdateSubstitutionMap(a, ASTTrue);
    output = updated ? ASTTrue : a;
  }
  else if (NOT == k)
  {
    bool updated = searchXOR(a[0], ASTFalse);
    output = updated ? ASTTrue : a;
  }
  else if (IFF == k || EQ == k)
  {
    const ASTVec& c = a.GetChildren();

    if (c[0] == c[1])
      return ASTTrue;

    bool updated = simp->UpdateSubstitutionMap(c[0], c[1]);

    if (updated)
    {
      // fill the arrayname readindices vector if e0 is a
      // READ(Arr,index) and index is a BVCONST
      int to;
      if ((to = TermOrder(c[0], c[1])) == 1 && c[0].GetKind() == READ)
        at->FillUp_ArrReadIndex_Vec(c[0], c[1]);
      else if (to == -1 && c[1].GetKind() == READ)
        at->FillUp_ArrReadIndex_Vec(c[1], c[0]);
    }

    if (!updated)
      updated = searchTerm(c[0], c[1]);

    if (!updated)
      updated = searchTerm(c[1], c[0]);

    output = updated ? ASTTrue : a;
  }
  else if (XOR == k)
  {
    bool updated = searchXOR(a, ASTTrue);
    output = updated ? ASTTrue : a;

    if (updated)
      return output;

// The below block should be subsumed by the searchXOR function which
// generalises it.
// So the below block should never do anything..
#ifndef NDEBUG
    if (a.Degree() != 2)
      return output;

    int to = TermOrder(a[0], a[1]);
    if (0 == to)
    {
      if (a[0].GetKind() == NOT && a[0][0].GetKind() == EQ &&
          a[0][0][0].GetValueWidth() == 1 && a[0][0][1].GetKind() == SYMBOL)
      {
        // (XOR (NOT(= (1 v)))  ... )
        const ASTNode& symbol = a[0][0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[1], a[0][0][0], nf->CreateTerm(BVNEG, 1, a[0][0][0]));

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[1].GetKind() == NOT && a[1][0].GetKind() == EQ &&
               a[1][0][0].GetValueWidth() == 1 &&
               a[1][0][1].GetKind() == SYMBOL)
      {
        const ASTNode& symbol = a[1][0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[0], a[1][0][0], nf->CreateTerm(BVNEG, 1, a[1][0][0]));

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[0].GetKind() == EQ && a[0][0].GetValueWidth() == 1 &&
               a[0][1].GetKind() == SYMBOL)
      {
        // XOR ((= 1 v) ... )

        const ASTNode& symbol = a[0][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[1], nf->CreateTerm(BVNEG, 1, a[0][0]), a[0][0]);

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else if (a[1].GetKind() == EQ && a[1][0].GetValueWidth() == 1 &&
               a[1][1].GetKind() == SYMBOL)
      {
        const ASTNode& symbol = a[1][1];
        const ASTNode newN = nf->CreateTerm(
            ITE, 1, a[0], nf->CreateTerm(BVNEG, 1, a[1][0]), a[1][0]);

        if (simp->UpdateSolverMap(symbol, newN))
        {
          assert(false);
          output = ASTTrue;
        }
      }
      else
        return output;
    }
    else
    {
      ASTNode symbol, rhs;
      if (to == 1)
      {
        symbol = a[0];
        rhs = a[1];
      }
      else
      {
        symbol = a[1];
        rhs = a[0];
      }

      assert(symbol.GetKind() == SYMBOL);

      if (simp->UpdateSolverMap(symbol, nf->CreateNode(NOT, rhs)))
      {
        assert(false);
        output = ASTTrue;
      }
    }
#endif
  }
  else if (AND == k)
  {
    const ASTVec& c = a.GetChildren();
    ASTVec o;
    o.reserve(c.size());

    for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend;
         it++)
    {
      if (always_true)
        simp->UpdateAlwaysTrueFormSet(*it);
      ASTNode aaa = propagate(*it, at);

      if (ASTTrue != aaa)
      {
        if (ASTFalse == aaa)
          return ASTFalse;
        else
          o.push_back(aaa);
      }
    }
    if (o.size() == 0)
      output = ASTTrue;
    else if (o.size() == 1)
      output = o[0];
    else if (o != c)
      output = nf->CreateNode(AND, o);
    else
      output = a;
  }

  return output;
}
示例#11
0
文件: main_common.cpp 项目: stp/stp
int Main::main(int argc, char** argv)
{
  unique_ptr<SimplifyingNodeFactory> simplifyingNF(
      new SimplifyingNodeFactory(*bm->hashingNodeFactory, *bm));
  bm->defaultNodeFactory = simplifyingNF.get();

  unique_ptr<Simplifier> simp(new Simplifier(bm));
  unique_ptr<ArrayTransformer> arrayTransformer(
      new ArrayTransformer(bm, simp.get()));
  unique_ptr<ToSAT> tosat(new ToSAT(bm));

  unique_ptr<AbsRefine_CounterExample> Ctr_Example(
      new AbsRefine_CounterExample(bm, simp.get(), arrayTransformer.get()));

  int ret = create_and_parse_options(argc, argv);
  if (ret != 0)
  {
    return ret;
  }

  STP* stp = new STP(bm, simp.get(), arrayTransformer.get(), tosat.get(),
                     Ctr_Example.get());

  GlobalSTP = stp;
  // If we're not reading the file from stdin.
  if (!infile.empty())
    read_file();

  // want to print the output always from the commandline.
  bm->UserFlags.print_output_flag = true;
  ASTVec* AssertsQuery = new ASTVec;

  bm->GetRunTimes()->start(RunTimes::Parsing);
  parse_file(AssertsQuery);
  bm->GetRunTimes()->stop(RunTimes::Parsing);

  GlobalSTP = NULL;

  /*  The SMTLIB2 has a command language. The parser calls all the functions,
   *  so when we get to here the parser has already called "exit". i.e. if the
   *  language is smt2 then all the work has already been done, and all we need
   *  to do is cleanup...
   *    */
  if (!bm->UserFlags.smtlib2_parser_flag)
  {
    if (AssertsQuery->empty())
      FatalError("Input is Empty. Please enter some asserts and query\n");

    if (AssertsQuery->size() != 2)
      FatalError("Input must contain a query\n");

    ASTNode asserts = (*AssertsQuery)[0];
    ASTNode query = (*AssertsQuery)[1];

    if (onePrintBack)
    {
      print_back(query, asserts);
    }
    else
    {
      SOLVER_RETURN_TYPE ret = stp->TopLevelSTP(asserts, query);

      if (bm->UserFlags.quick_statistics_flag)
      {
        bm->GetRunTimes()->print();
      }
      stp->tosat->PrintOutput(ret);
    }

    asserts = ASTNode();
    query = ASTNode();
  }

  // Previously we used fast-exit to avoid destroying lots of objects, for example in the node manager.
  // We use unique_ptr now on lots of stuff, so there seems little difference in the time it takes to
  // exit normally vs. not.
  //if (bm->UserFlags.isSet("fast-exit", "0"))
  //  exit(0);

  //Cleanup
  AssertsQuery->clear();
  delete AssertsQuery;
  _empty_ASTVec.clear();
  delete stp;
  CNFClearMemory();

  return 0;
}
示例#12
0
    // NB: This expects that the constructor was called with teh same node. Sorry.
    ASTNode
    ConstantBitPropagation::topLevelBothWays(const ASTNode& top)
    {
      assert(top.GetSTPMgr()->UserFlags.bitConstantProp_flag);
      assert (BOOLEAN_TYPE == top.GetType());

      propagate();
      status = NO_CHANGE;

      //Determine what must always be true.
      ASTNodeMap fromTo = getAllFixed();

      if (debug_cBitProp_messages)
        {
          cerr << "Number removed by bottom UP:" << fromTo.size() << endl;
        }

      setNodeToTrue(top);

      if (debug_cBitProp_messages)
        {
          cerr << "starting propagation" << endl;
          printNodeWithFixings();
          cerr << "Initial Tree:" << endl;
          cerr << top;
        }

      propagate();

      if (debug_cBitProp_messages)
        {
          cerr << "status:" << status <<endl;
          cerr << "ended propagation" << endl;
          printNodeWithFixings();
        }

      // propagate may have stopped with a conflict.
      if (CONFLICT == status)
          return top.GetSTPMgr()->CreateNode(FALSE);

      ASTVec toConjoin;

      // go through the fixedBits. If a node is entirely fixed.
      // "and" it onto the top. Creates redundancy. Check that the
      // node doesn't already depend on "top" directly.

      for (NodeToFixedBitsMap::NodeToFixedBitsMapType::iterator it = fixedMap->map->begin(); it != fixedMap->map->end(); it++) // iterates through all the pairs of node->fixedBits.
        {
          const FixedBits& bits = *it->second;

          if (!bits.isTotallyFixed())
            continue;

          const ASTNode& node = (it->first);

          // Don't constrain nodes we already know all about.
          if (node.isConstant())
            continue;

          // other nodes will contain the same information (the extract doesn't change the fixings).
          if (BVEXTRACT == node.GetKind() || BVCONCAT == node.GetKind())
            continue;

          // toAssign: conjoin it with the top level.
          // toReplace: replace all references to it (except the one conjoined to the top) with this.
          ASTNode propositionToAssert;
          ASTNode constantToReplaceWith;
          // skip the assigning and replacing.
          bool doAssign = true;

            {
              // If it is already contained in the fromTo map, then it's one of the values
              // that have fully been determined (previously). Not conjoined.
              if (fromTo.find(node) != fromTo.end())
                continue;

              ASTNode constNode = bitsToNode(node,bits);

              if (node.GetType() == BOOLEAN_TYPE)
                {
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else if (bits.getValue(0))
                    {
                      propositionToAssert = node;
                      constantToReplaceWith = constNode;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(NOT, node);
                      constantToReplaceWith = constNode;
                    }
                }
              else if (node.GetType() == BITVECTOR_TYPE)
                {
                  assert(((unsigned)bits.getWidth()) == node.GetValueWidth());
                  if (SYMBOL == node.GetKind())
                    {
                      bool r = simplifier->UpdateSubstitutionMap(node, constNode);
                      assert(r);
                      doAssign = false;
                    }
                  else
                    {
                      propositionToAssert = nf->CreateNode(EQ, node, constNode);
                      constantToReplaceWith = constNode;
                    }
                }
              else
                FatalError("sadf234s");
            }

          if (doAssign && top != propositionToAssert
              && !dependents->nodeDependsOn(top, propositionToAssert))
            {
              assert(!constantToReplaceWith.IsNull());
              assert(constantToReplaceWith.isConstant());
              assert(propositionToAssert.GetType() == BOOLEAN_TYPE);
              assert(node.GetValueWidth() == constantToReplaceWith.GetValueWidth());

              fromTo.insert(make_pair(node, constantToReplaceWith));
              toConjoin.push_back(propositionToAssert);
            }
        }

     // Write the constants into the main graph.
      ASTNodeMap cache;
      ASTNode result = SubstitutionMap::replace(top, fromTo, cache,nf);

      if (0 != toConjoin.size())
        {
          // It doesn't happen very often. But the "toConjoin" might contain a variable
          // that was added to the substitution map (because the value was determined just now
          // during propagation.
          ASTNode conjunct = (1 == toConjoin.size())? toConjoin[0]: nf->CreateNode(AND,toConjoin);
          conjunct = simplifier->applySubstitutionMap(conjunct);

          result = nf->CreateNode(AND, result, conjunct); // conjoin the new conditions.
        }


  	if (debug_print_graph_after)
		{
			ofstream file;
			file.open("afterCbitp.gdl");
			PrintingHackfixedMap = fixedMap;
			printer::GDL_Print(file,top,&toString);
			file.close();
		}


      assert(BVTypeCheck(result));
      assert(status != CONFLICT); // conflict should have been seen earlier.
      return result;
    }