Example #1
0
 ASTNode STPMgr::CreateSimpXor(const ASTNode& form1, const ASTNode& form2)
 {
   ASTVec children;
   children.push_back(form1);
   children.push_back(form2);
   return CreateSimpXor(children);
 }
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;
}
Example #3
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);
  }
Example #4
0
 ASTNode STPMgr::CreateSimpAndOr(bool IsAnd, 
                                 const ASTNode& form1, const ASTNode& form2)
 {
   ASTVec children;
   children.push_back(form1);
   children.push_back(form2);
   return CreateSimpAndOr(IsAnd, children);
 }
Example #5
0
 ASTNode STPMgr::CreateSimpForm(Kind kind, const ASTNode& child0)
 {
   ASTVec children;
   //child_stack.clear();      // could just reset top pointer.
   children.push_back(child0);
   //child_stack.push_back(child0);
   return CreateSimpForm(kind, children);
   //return CreateSimpForm(kind, child_stack);
 }
  void checkChildrenAreBV(const ASTVec& v, const ASTNode&n) {
	for (ASTVec::const_iterator it = v.begin(), itend = v.end(); it != itend; it++)
		if (BITVECTOR_TYPE != it->GetType()) {
			cerr << "The type is: " << it->GetType() << endl;
			FatalError(
					"BVTypeCheck:ChildNodes of bitvector-terms must be bitvectors\n",
					n);
		}
}
Example #7
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);
}
Example #8
0
void STPMgr::printAssertsToStream(ostream& os)
{
  ASTVec v = GetAsserts();
  for (ASTVec::iterator i = v.begin(), iend = v.end(); i != iend; i++)
  {
    ASTNode q = *i;
    os << "ASSERT( ";
    q.PL_Print(os, this);
    os << ");" << endl;
  }
}
Example #9
0
 void STPMgr::printAssertsToStream(ostream &os, int simplify_print) {
   ASTVec v = GetAsserts();
   for(ASTVec::iterator i=v.begin(),iend=v.end();i!=iend;i++) {
     //Begin_RemoveWrites = true; ASTNode q = (simplify_print == 1) ?
     //SimplifyFormula_TopLevel(*i,false) : *i; q = (simplify_print
     //== 1) ? SimplifyFormula_TopLevel(q,false) : q;
     ASTNode q = *i;
     //Begin_RemoveWrites = false;
     os << "ASSERT( ";
     q.PL_Print(os);
     os << ");" << endl;
   }
 }
Example #10
0
void CNFMgr::convertFormulaToCNFPosPred(const ASTNode& varphi,
                                        ClauseList* defs)
{
    ASTVec psis;

    ASTVec::const_iterator it = varphi.GetChildren().begin();
    for (; it != varphi.GetChildren().end(); it++)
    {
        convertTermForCNF(*it, defs);
        psis.push_back(*(info[*it]->termforcnf));
    }

    info[varphi]->clausespos =
        SINGLETON(bm->CreateNode(varphi.GetKind(), psis));
} //End of convertFormulaToCNFPosPred()
Example #11
0
ASTNode NodeFactory::CreateArrayTerm(Kind kind, unsigned int index, unsigned int width,
                                     const ASTNode& child0, const ASTNode& child1, const ASTNode& child2,
                                     const ASTVec &children)
{
    ASTVec child;
    child.reserve(children.size() + 3);
    child.push_back(child0);
    child.push_back(child1);
    child.push_back(child2);
    child.insert(child.end(), children.begin(), children.end());
    return CreateArrayTerm(kind, index, width, child);
}
 void FlattenKind(const Kind k, const ASTVec &children, ASTVec & flat_children)
 {
   ASTVec::const_iterator ch_end = children.end();
   for (ASTVec::const_iterator it = children.begin(); it != ch_end; it++)
     {
       Kind ck = it->GetKind();
       if (k == ck)
         {
           FlattenKind(k,it->GetChildren(), flat_children);
         }
       else
         {
           flat_children.push_back(*it);
         }
     }
 }
Example #13
0
  void print_STPInput_Back(const ASTNode& query) {

	  // Determine the symbols in the query and asserts.
	  ASTNodeSet visited;
	  ASTNodeSet symbols;
	  buildListOfSymbols(query,  visited, symbols);
      ASTVec v = (BEEV::GlobalSTP->bm)->GetAsserts();
      for(ASTVec::iterator i=v.begin(),iend=v.end();i!=iend;i++)
    	buildListOfSymbols(*i,  visited, symbols);

	(BEEV::GlobalSTP->bm)->printVarDeclsToStream(cout, symbols);
    (BEEV::GlobalSTP->bm)->printAssertsToStream(cout,0);
    cout << "QUERY(";
    query.PL_Print(cout);
    cout << ");\n";
  } //end of print_STPInput_Back()
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;
}
Example #15
0
  void Dot_Print1(ostream &os, const ASTNode n, hash_set<int> *alreadyOutput)
  {

    // check if this node has already been printed. If so return.
    if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end())
      return;

    alreadyOutput->insert(n.GetNodeNum());

    os << "n" << n.GetNodeNum() << "[label =\"";
    switch (n.GetKind())
      {
      case SYMBOL:
        n.nodeprint(os);
        break;

      case BITVECTOR:
      case BVCONST:
        outputBitVec(n, os);
        break;

      default:
        os << _kind_names[n.GetKind()];
      }

    os << "\"];" << endl;

    // print the edges to each child.
    ASTVec ch = n.GetChildren();
    ASTVec::iterator itend = ch.end();
    int i = 0;
    for (ASTVec::iterator it = ch.begin(); it < itend; it++)
      {
        os << "n" << n.GetNodeNum() 
           << " -> " << "n" 
           << it->GetNodeNum() 
           << "[label=" << i++ 
           << "];" << endl;
      }

    // print each of the children.
    for (ASTVec::iterator it = ch.begin(); it < itend; it++)
      {
        Dot_Print1(os, *it, alreadyOutput);
      }
  }
Example #16
0
void CNFMgr::convertTermForCNF(const ASTNode& varphi, ClauseList* defs)
{
    CNFInfo* x = info[varphi];

    //########################################
    // step 1, done if we've already visited
    //########################################

    if (x->termforcnf != NULL)
    {
        return;
    }

    //########################################
    // step 2, ITE's always get renamed
    //########################################

    if (varphi.isITE())
    {
        x->termforcnf = doRenameITE(varphi, defs);
        reduceMemoryFootprintPos(varphi[0]);
        reduceMemoryFootprintNeg(varphi[0]);

    }
    else if (varphi.isAtom())
    {
        x->termforcnf = ASTNodeToASTNodePtr(varphi);
    }
    else
    {
        ASTVec psis;
        ASTVec::const_iterator it = varphi.GetChildren().begin();
        for (; it != varphi.GetChildren().end(); it++)
        {
            convertTermForCNF(*it, defs);
            psis.push_back(*(info[*it]->termforcnf));
        }

        ASTNode psi = bm->CreateNode(varphi.GetKind(), psis);
        psi.SetValueWidth(varphi.GetValueWidth());
        psi.SetIndexWidth(varphi.GetIndexWidth());
        x->termforcnf = ASTNodeToASTNodePtr(psi);
    }
} //End of convertTermForCNF()
Example #17
0
/* Maintains a set of nodes that have already been seen. So that deeply shared
 * AND,OR operations are not
 * flattened multiple times.
 */
void FlattenKindNoDuplicates(const Kind k, const ASTVec& children,
                             ASTVec& flat_children,
                             ASTNodeSet& alreadyFlattened)
{
  const ASTVec::const_iterator ch_end = children.end();
  for (ASTVec::const_iterator it = children.begin(); it != ch_end; it++)
  {
    const Kind ck = it->GetKind();
    if (k == ck)
    {
      if (alreadyFlattened.find(*it) == alreadyFlattened.end())
      {
        alreadyFlattened.insert(*it);
        FlattenKindNoDuplicates(k, it->GetChildren(), flat_children,
                                alreadyFlattened);
      }
    }
    else
    {
      flat_children.push_back(*it);
    }
  }
}
Example #18
0
  // Flatten (k ... (k ci cj) ...) to (k ... ci cj ...)
  // This is local to this file.
  ASTVec FlattenKind(Kind k, const ASTVec &children)
  {
    ASTVec flat_children;

    ASTVec::const_iterator ch_end = children.end();
    for (ASTVec::const_iterator it = children.begin(); it != ch_end; it++)
      {
        Kind ck = it->GetKind();
        const ASTVec &gchildren = it->GetChildren();
        if (k == ck)
          {
            // append grandchildren to children
            flat_children.insert(flat_children.end(),
                                 gchildren.begin(), gchildren.end());
          }
        else
          {
            flat_children.push_back(*it);
          }
      }

    return flat_children;
  }
Example #19
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);
        }
  }
Example #20
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;
  }
Example #21
0
ASTNode ArrayTransformer::TransformTerm(const ASTNode& term)
{
  assert(TransformMap != NULL);

  const Kind k = term.GetKind();
  if (!is_Term_kind(k))
    FatalError("TransformTerm: Illegal kind: You have input a nonterm:", term,
               k);
  ASTNodeMap::const_iterator iter;
  if ((iter = TransformMap->find(term)) != TransformMap->end())
    return iter->second;

  ASTNode result;
  switch (k)
  {
    case SYMBOL:
    case BVCONST:
    {
      result = term;
      break;
    }
    case WRITE:
      FatalError("TransformTerm: this kind is not supported", term);
      break;
    case READ:
      result = TransformArrayRead(term);
      break;
    case ITE:
    {
      ASTNode cond = term[0];
      ASTNode thn = term[1];
      ASTNode els = term[2];
      cond = TransformFormula(cond);
      if (ASTTrue == cond)
        result = TransformTerm(thn);
      else if (ASTFalse == cond)
        result = TransformTerm(els);
      else
      {
        thn = TransformTerm(thn);
        els = TransformTerm(els);
        if (bm->UserFlags.optimize_flag)
          result = simp->CreateSimplifiedTermITE(cond, thn, els);
        else
          result = nf->CreateTerm(ITE, thn.GetValueWidth(), cond, thn, els);
      }
      assert(result.GetIndexWidth() == term.GetIndexWidth());
      break;
    }
    default:
    {
      const ASTVec& c = term.GetChildren();
      ASTVec::const_iterator it = c.begin();
      ASTVec::const_iterator itend = c.end();
      const unsigned width = term.GetValueWidth();
      const unsigned indexwidth = term.GetIndexWidth();
      ASTVec o;
      o.reserve(c.size());
      for (; it != itend; it++)
      {
        o.push_back(TransformTerm(*it));
      }

      if (c != o)
      {
        result = nf->CreateArrayTerm(k, indexwidth, width, o);
      }
      else
        result = term;
    }
    break;
  }

  if (term.Degree() > 0)
    (*TransformMap)[term] = result;
  if (term.GetValueWidth() != result.GetValueWidth())
    FatalError("TransformTerm: "
               "result and input terms are of different length",
               result);
  if (term.GetIndexWidth() != result.GetIndexWidth())
  {
    std::cerr << "TransformTerm: input term is : " << term << std::endl;
    FatalError("TransformTerm: "
               "result & input terms have different index length",
               result);
  }
  return result;
} 
Example #22
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;
}
Example #23
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()
Example #24
0
  // FIXME:  How do I know whether ITE is a formula or not?
  ASTNode STPMgr::CreateSimpFormITE(const ASTNode& child0, 
                                    const ASTNode& child1, 
                                    const ASTNode& child2)
  {

    ASTNode retval;

    if (_trace_simpbool)
      {
        cout << "========" << endl 
             << "CreateSimpFormITE " 
             << child0 << child1 << child2 << endl;
      }

    if (ASTTrue == child0)
      {
        retval = child1;
      }
    else if (ASTFalse == child0)
      {
        retval = child2;
      }
    else if (child1 == child2)
      {
        retval = child1;
      }
    // ITE(x, TRUE, y ) == x OR y
    else if (ASTTrue == child1)
      {
        retval = CreateSimpAndOr(0, child0, child2);
      }
    // ITE(x, FALSE, y ) == (!x AND y)
    else if (ASTFalse == child1)
      {
        retval = CreateSimpAndOr(1, CreateSimpNot(child0), child2);
      }
    // ITE(x, y, TRUE ) == (!x OR y)
    else if (ASTTrue == child2)
      {
        retval = CreateSimpAndOr(0, CreateSimpNot(child0), child1);
      }
    // ITE(x, y, FALSE ) == (x AND y)
    else if (ASTFalse == child2)
      {
        retval = CreateSimpAndOr(1, child0, child1);
      }
    else
      {
	ASTNode left  = CreateNode(AND, child0, child1);
	ASTNode right = CreateNode(AND, CreateNode(NOT,child0), child2);
	ASTVec c;
	c.push_back(left);
	c.push_back(right);
        retval = CreateSimpXor(c);
      }

    if (_trace_simpbool)
      {
        cout << "returns " << retval << endl;
      }

    return retval;
  }
Example #25
0
  // Constant children are accumulated in "accumconst".
  ASTNode STPMgr::CreateSimpXor(ASTVec &children)
  {

    if (_trace_simpbool)
      {
        cout << "========" << endl << "CreateSimpXor ";
        lpvec(children);
        cout << endl;
      }

    ASTVec flat_children; // empty vector
    ASTVec::const_iterator it_end = children.end();

    if (UserFlags.xor_flatten_flag)
      {
        flat_children = FlattenKind(XOR, children);
      }
    else
      {
        flat_children = children;
      }

    // sort so that identical nodes occur in sequential runs, followed by
    // their negations.
    SortByExprNum(flat_children);

    ASTNode retval;

    // This is the C Boolean value of all constant args seen.  It is initially
    // 0.  TRUE children cause it to change value.
    bool accumconst = 0;

    ASTVec new_children;

    it_end = flat_children.end();
    ASTVec::iterator next_it;
    for (ASTVec::iterator it = flat_children.begin(); it != it_end; it++)
      {
        next_it = it + 1;
        bool nextexists = (next_it < it_end);

        if (ASTTrue == *it)
          {
            accumconst = !accumconst;
          }
        else if (ASTFalse == *it)
          {
            // Ignore it
          }
        else if (nextexists && (*next_it == *it))
          {
            // x XOR x = FALSE.  Skip current, write "false" into next_it
            // so that it gets tossed, too.
            *next_it = ASTFalse;
          }
        else if (nextexists && (next_it->GetKind() == NOT) 
                 && ((*next_it)[0] == *it))
          {
            // x XOR NOT x = TRUE.  Skip current, write "true" into next_it
            // so that it gets tossed, too.
            *next_it = ASTTrue;
          }
        else if (NOT == it->GetKind())
          {
            // If child is (NOT alpha), we can flip accumconst and use alpha.
            // This is ok because (NOT alpha) == TRUE XOR alpha
            accumconst = !accumconst;
            // CreateSimpNot just takes child of not.
            new_children.push_back(CreateSimpNot(*it));
          }
        else
          {
            new_children.push_back(*it);
          }
      }

    // Children should be non-constant.
    if (new_children.size() < 2)
      {
        if (0 == new_children.size())
          {
            // XOR(TRUE, FALSE) -- accumconst will be 1.
            if (accumconst)
              {
                retval = ASTTrue;
              }
            else
              {
                retval = ASTFalse;
              }
          }
        else
          {
            // there is just one child
            // XOR(x, TRUE) -- accumconst will be 1.
            if (accumconst)
              {
                retval = CreateSimpNot(new_children[0]);
              }
            else
              {
                retval = new_children[0];
              }
          }
      }
    else
      {
        // negate first child if accumconst == 1
        if (accumconst)
          {
            new_children[0] = CreateSimpNot(new_children[0]);
          }
        retval = CreateNode(XOR, new_children);
      }

    if (_trace_simpbool)
      {
        cout << "returns " << retval << endl;
      }
    return retval;
  }
 void SortByArith(ASTVec& v)
 {
   sort(v.begin(), v.end(), arithless);
 }
 void SortByExprNum(ASTVec& v)
 {
   sort(v.begin(), v.end(), exprless);
 }
Example #28
0
int main(int argc, char** argv)
{
    // Register the error handler
    vc_error_hdlr = errorHandler;

#if  !defined(__MINGW32__) && !defined(__MINGW64__) && !defined( _MSC_VER)
    // Grab some memory from the OS upfront to reduce system time when
    // individual hash tables are being allocated
    if (sbrk(INITIAL_MEMORY_PREALLOCATION_SIZE) == ((void*) - 1)) {
        FatalError("Initial allocation of memory failed.");
    }
#endif /* !defined(__MINGW32__) && !defined(__MINGW64__) && !defined( _MSC_VER) */


    bm = new STPMgr();
    toClose = NULL;

    auto_ptr<SimplifyingNodeFactory> simplifyingNF( new SimplifyingNodeFactory(*bm->hashingNodeFactory, *bm));
    bm->defaultNodeFactory = simplifyingNF.get();

    // The simplified keeps a pointer to whatever is set as the default node factory.
    Simplifier* simp  = new Simplifier(bm);
    auto_ptr<Simplifier> simpCleaner(simp);

    ArrayTransformer* arrayTransformer = new ArrayTransformer(bm, simp);
    auto_ptr<ArrayTransformer> atClearner(arrayTransformer);

    ToSAT* tosat = new ToSAT(bm);
    auto_ptr<ToSAT> tosatCleaner(tosat);

    AbsRefine_CounterExample* Ctr_Example = new AbsRefine_CounterExample(bm, simp, arrayTransformer);
    auto_ptr<AbsRefine_CounterExample> ctrCleaner(Ctr_Example);

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

    GlobalSTP = new STP(bm, simp, arrayTransformer, tosat, Ctr_Example);

    // 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);

    /*  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 (((ASTVec*) AssertsQuery)->empty()) {
            FatalError("Input is Empty. Please enter some asserts and query\n");
        }

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

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

        if (onePrintBack) {
            print_back(query, asserts);
            return 0;
        }

        SOLVER_RETURN_TYPE ret = GlobalSTP->TopLevelSTP(asserts, query);
        if (bm->UserFlags.quick_statistics_flag) {
            bm->GetRunTimes()->print();
        }
        (GlobalSTP->tosat)->PrintOutput(ret);

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

    //Without cleanup
    if (bm->UserFlags.isSet("fast-exit", "1")) {
        exit(0);
    }

    //Propery tidy up
    AssertsQuery->clear();
    delete AssertsQuery;

    _empty_ASTVec.clear();

    simpCleaner.release();
    atClearner.release();
    tosatCleaner.release();
    ctrCleaner.release();

    delete GlobalSTP;
    delete ParserBM;

    Cnf_ClearMemory();

    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;
}
Example #30
0
void GDL_Print1(ostream& os, const ASTNode& n, hash_set<int>* alreadyOutput,
                string (*annotate)(const ASTNode&))
{
  // check if this node has already been printed. If so return.
  if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end())
    return;

  alreadyOutput->insert(n.GetNodeNum());

  os << "node: { title:\"n" << n.GetNodeNum() << "\" label: \"";
  switch (n.GetKind())
  {
    case SYMBOL:
      n.nodeprint(os);
      break;

    case BITVECTOR:
    case BVCONST:
      outputBitVec(n, os);
      break;

    default:
      os << _kind_names[n.GetKind()];
  }

  os << annotate(n);
  os << "\"}" << endl;

  // print the edges to each child.
  const ASTVec ch = n.GetChildren();
  const ASTVec::const_iterator itend = ch.end();

  // If a node has the child 'TRUE' twice, we only want to output one TRUE node.
  ASTNodeSet constantOutput;

  int i = 0;
  for (ASTVec::const_iterator it = ch.begin(); it < itend; it++)
  {
    std::stringstream label;

    if (!isCommutative(n.GetKind()))
      label << " label:\"" << i << "\"";

    if (it->isConstant())
    {
      std::stringstream ss;
      ss << n.GetNodeNum() << "_" << it->GetNodeNum();

      if (constantOutput.end() == constantOutput.find(*it))
      {
        os << "node: { title:\"n";

        os << ss.str() << "\" label: \"";
        if (it->GetType() == BEEV::BOOLEAN_TYPE)
          os << _kind_names[it->GetKind()];
        else
          outputBitVec(*it, os);
        os << "\"}" << endl;
        constantOutput.insert(*it);
      }

      os << "edge: { source:\"n" << n.GetNodeNum() << "\" target: \""
         << "n" << ss.str() << "\"" << label.str() << "}" << endl;
    }
    else
      os << "edge: { source:\"n" << n.GetNodeNum() << "\" target: \""
         << "n" << it->GetNodeNum() << "\"" << label.str() << "}" << endl;
    i++;
  }

  // print each of the children.
  for (ASTVec::const_iterator it = ch.begin(); it < itend; it++)
  {
    if (!it->isConstant())
      GDL_Print1(os, *it, alreadyOutput, annotate);
  }
}