about summary refs log tree commit diff homepage
path: root/stp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-05-21 04:36:41 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-05-21 04:36:41 +0000
commit6f290d8f9e9d7faac295cb51fc96884a18f4ded4 (patch)
tree46e7d426abc0c9f06ac472ac6f7f9e661b5d78cb /stp
parenta55960edd4dcd7535526de8d2277642522aa0209 (diff)
downloadklee-6f290d8f9e9d7faac295cb51fc96884a18f4ded4.tar.gz
Initial KLEE checkin.
 - Lots more tweaks, documentation, and web page content is needed,
   but this should compile & work on OS X & Linux.


git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@72205 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'stp')
-rw-r--r--stp/AST/AST.cpp1587
-rw-r--r--stp/AST/AST.h1805
-rw-r--r--stp/AST/ASTKind.kinds71
-rw-r--r--stp/AST/ASTUtil.cpp45
-rw-r--r--stp/AST/ASTUtil.h107
-rw-r--r--stp/AST/BitBlast.cpp812
-rw-r--r--stp/AST/Makefile54
-rw-r--r--stp/AST/STLport_config.h20
-rw-r--r--stp/AST/SimpBool.cpp408
-rw-r--r--stp/AST/ToCNF.cpp506
-rw-r--r--stp/AST/ToSAT.cpp1385
-rw-r--r--stp/AST/Transform.cpp492
-rw-r--r--stp/AST/asttest.cpp29
-rw-r--r--stp/AST/bbtest.cpp96
-rw-r--r--stp/AST/cnftest.cpp47
-rwxr-xr-xstp/AST/genkinds.pl123
-rw-r--r--stp/INSTALL10
-rw-r--r--stp/LICENSE17
-rw-r--r--stp/Makefile64
-rw-r--r--stp/Makefile.common.in16
-rw-r--r--stp/README26
-rw-r--r--stp/bitvec/Makefile11
-rw-r--r--stp/bitvec/consteval.cpp1044
-rw-r--r--stp/c_interface/Makefile13
-rw-r--r--stp/c_interface/c_interface.cpp1548
-rw-r--r--stp/c_interface/c_interface.h401
-rw-r--r--stp/c_interface/fdstream.h186
-rw-r--r--stp/constantbv/Makefile13
-rw-r--r--stp/constantbv/constantbv.cpp3571
-rw-r--r--stp/constantbv/constantbv.h316
-rw-r--r--stp/parser/Makefile27
-rw-r--r--stp/parser/PL.lex128
-rw-r--r--stp/parser/PL.y1006
-rw-r--r--stp/parser/let-funcs.cpp85
-rw-r--r--stp/parser/main.cpp181
-rw-r--r--stp/parser/smtlib.lex232
-rw-r--r--stp/parser/smtlib.y1036
-rw-r--r--stp/sat/Global.h255
-rw-r--r--stp/sat/Heap.h151
-rw-r--r--stp/sat/LICENSE20
-rw-r--r--stp/sat/Makefile16
-rw-r--r--stp/sat/Simplifier.C542
-rw-r--r--stp/sat/Solver.C811
-rw-r--r--stp/sat/Solver.h359
-rw-r--r--stp/sat/SolverTypes.h127
-rw-r--r--stp/sat/Sort.h133
-rw-r--r--stp/sat/VarOrder.h146
-rw-r--r--stp/simplifier/Makefile11
-rw-r--r--stp/simplifier/bvsolver.cpp714
-rw-r--r--stp/simplifier/bvsolver.h134
-rw-r--r--stp/simplifier/simplifier.cpp2495
51 files changed, 23432 insertions, 0 deletions
diff --git a/stp/AST/AST.cpp b/stp/AST/AST.cpp
new file mode 100644
index 00000000..ab290395
--- /dev/null
+++ b/stp/AST/AST.cpp
@@ -0,0 +1,1587 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "AST.h"
+namespace BEEV {
+  //some global variables that are set through commandline options. it
+  //is best that these variables remain global. Default values set
+  //here
+  //
+  //collect statistics on certain functions
+  bool stats = false;
+  //print DAG nodes
+  bool print_nodes = false;
+  //tentative global var to allow for variable activity optimization
+  //in the SAT solver. deprecated.
+  bool variable_activity_optimize = false;
+  //run STP in optimized mode
+  bool optimize = true;
+  //do sat refinement, i.e. underconstraint the problem, and feed to
+  //SAT. if this works, great. else, add a set of suitable constraints
+  //to re-constraint the problem correctly, and call SAT again, until
+  //all constraints have been added.
+  bool arrayread_refinement = true;
+  //flag to control write refinement
+  bool arraywrite_refinement = true;
+  //check the counterexample against the original input to STP
+  bool check_counterexample = false;
+  //construct the counterexample in terms of original variable based
+  //on the counterexample returned by SAT solver
+  bool construct_counterexample = true;
+  bool print_counterexample = false;
+  //if this option is true then print the way dawson wants using a
+  //different printer. do not use this printer.
+  bool print_arrayval_declaredorder = false;
+  //flag to decide whether to print "valid/invalid" or not
+  bool print_output = false;
+  //do linear search in the array values of an input array. experimental
+  bool linear_search = false;
+  //print the variable order chosen by the sat solver while it is
+  //solving.
+  bool print_sat_varorder = false; 
+  //turn on word level bitvector solver
+  bool wordlevel_solve = true;
+  //turn off XOR flattening
+  bool xor_flatten = false;
+
+  //the smtlib parser has been turned on
+  bool smtlib_parser_enable = false;
+  //print the input back
+  bool print_STPinput_back = false;
+  
+  //global BEEVMGR for the parser
+  BeevMgr * globalBeevMgr_for_parser;
+
+  void (*vc_error_hdlr)(const char* err_msg) = NULL;
+  /** This is reusable empty vector, for representing empty children arrays */
+  ASTVec _empty_ASTVec;  
+  ////////////////////////////////////////////////////////////////
+  //  ASTInternal members
+  ////////////////////////////////////////////////////////////////  
+  /** Trivial but virtual destructor */
+  ASTInternal::~ASTInternal() { }
+
+  ////////////////////////////////////////////////////////////////
+  //  ASTInterior members
+  ////////////////////////////////////////////////////////////////
+  /** Copy constructor */
+  // ASTInterior::ASTInterior(const ASTInterior &int_node)
+  // {
+  //   _kind = int_node._kind;
+  //   _children = int_node._children;
+  // }
+  
+  /** Trivial but virtual destructor */
+  ASTInterior::~ASTInterior() { }
+  
+  // FIXME: Darn it! I think this ends up copying the children twice!
+  /** Either return an old node or create it if it doesn't exist. 
+      Note that nodes are physically allocated in the hash table. */
+  
+  // There is  an inelegance here that  I don't know how  to solve.  I'd
+  // like to heap allocate and do some other initialization on keys only
+  // if  they aren't  in  the hash  table.   It would  be  great if  the
+  // "insert"  method took a  "creator" class  so that  I could  do that
+  // between  when it  notices that  the key  is not  there and  when it
+  // inserts it.  Alternatively, it would be great if I could insert the
+  // temporary key and replace it  if it actually got inserted.  But STL
+  // hash_set  doesn't have  the creator  feature  and paternalistically
+  // declares that keys are immutable, even though (it seems to me) that
+  // they  could be  mutated if  the hash  value and  eq values  did not
+  // change.
+  
+  ASTInterior *BeevMgr::LookupOrCreateInterior(ASTInterior *n_ptr) {
+    ASTInteriorSet::iterator it;
+    
+    if ((it = _interior_unique_table.find(n_ptr)) == _interior_unique_table.end()) {
+      // Make a new ASTInterior node
+      // We want (NOT alpha) always to have alpha.nodenum + 1.
+      if (n_ptr->GetKind() == NOT) {
+	n_ptr->SetNodeNum(n_ptr->GetChildren()[0].GetNodeNum()+1);
+      }
+      else {
+	n_ptr->SetNodeNum(NewNodeNum());
+      }
+      pair<ASTInteriorSet::const_iterator, bool> p = _interior_unique_table.insert(n_ptr);
+      return *(p.first);
+    }
+    else
+      // Delete the temporary node, and return the found node.
+      delete n_ptr;
+      return *it;
+  }
+  
+  size_t ASTInterior::ASTInteriorHasher::operator() (const ASTInterior *int_node_ptr) const {
+    //size_t hashval = 0;
+    size_t hashval = ((size_t) int_node_ptr->GetKind());
+    const ASTVec &ch = int_node_ptr->GetChildren();
+    ASTVec::const_iterator iend = ch.end();
+    for (ASTVec::const_iterator i = ch.begin(); i != iend; i++) {
+      //Using "One at a time hash" by Bob Jenkins
+      hashval += i->Hash();
+      hashval += (hashval << 10);
+      hashval ^= (hashval >> 6);
+    }
+
+    hashval += (hashval << 3);
+    hashval ^= (hashval >> 11);
+    hashval += (hashval << 15);
+    return hashval;
+    //return hashval += ((size_t) int_node_ptr->GetKind());
+  }
+  
+
+  void ASTInterior::CleanUp() {
+    // cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._interior_unique_table.erase(this);
+    delete this;
+  }
+
+  ////////////////////////////////////////////////////////////////
+  //  ASTNode members
+  ////////////////////////////////////////////////////////////////
+  //ASTNode constructors are inlined in AST.h
+  bool ASTNode::IsAlreadyPrinted() const {
+    BeevMgr &bm = GetBeevMgr();
+    return (bm.AlreadyPrintedSet.find(*this) != bm.AlreadyPrintedSet.end());
+  }
+
+  void ASTNode::MarkAlreadyPrinted() const {
+    // FIXME: Fetching BeevMgr is annoying.  Can we put this in lispprinter class?
+    BeevMgr &bm = GetBeevMgr();
+    bm.AlreadyPrintedSet.insert(*this);
+  }
+
+  // Get the name from a symbol (char *).  It's an error if kind != SYMBOL
+  const char * const ASTNode::GetName() const {
+    if (GetKind() != SYMBOL)
+      FatalError("GetName: Called GetName on a non-symbol: ", *this);
+    return ((ASTSymbol *) _int_node_ptr)->GetName();    
+  }
+  
+  // Print in lisp format
+  ostream &ASTNode::LispPrint(ostream &os, int indentation) const {
+    // Clear the PrintMap
+    BeevMgr& bm = GetBeevMgr(); 
+    bm.AlreadyPrintedSet.clear();
+    return LispPrint_indent(os, indentation);
+  }
+
+  // Print newline and indentation, then print the thing.
+  ostream &ASTNode::LispPrint_indent(ostream &os,
+				     int indentation) const
+  {
+    os << endl << spaces(indentation);
+    LispPrint1(os, indentation);
+    return os;
+  }
+  
+  /** Internal function to print in lisp format.  Assume newline
+      and indentation printed already before first line.  Recursive
+      calls will have newline & indent, though */
+  ostream &ASTNode::LispPrint1(ostream &os, int indentation) const {
+    if (!IsDefined()) {
+      os << "<undefined>";
+      return os;
+    }
+    Kind kind = GetKind();
+    // FIXME: figure out how to avoid symbols with same names as kinds.
+//    if (kind == READ) {
+//      const ASTVec &children = GetChildren();
+//      children[0].LispPrint1(os, indentation);
+//	os << "[" << children[1] << "]";
+//    } else 
+    if(kind == BVGETBIT) {
+      const ASTVec &children = GetChildren();
+      // child 0 is a symbol.  Print without the NodeNum.
+      os << GetNodeNum() << ":";
+
+
+
+      children[0]._int_node_ptr->nodeprint(os);
+      //os << "{" << children[1].GetBVConst() << "}";
+      os << "{";
+      children[1]._int_node_ptr->nodeprint(os);
+      os << "}";
+    } else if (kind == NOT) {
+      const ASTVec &children = GetChildren();
+      os << GetNodeNum() << ":";	
+      os << "(NOT ";
+      children[0].LispPrint1(os, indentation);
+      os << ")";
+    }
+    else if (Degree() == 0) {
+      // Symbol or a kind with no children print as index:NAME if shared,
+      // even if they have been printed before.	
+      os << GetNodeNum() << ":";
+      _int_node_ptr->nodeprint(os); 
+      // os << "(" << _int_node_ptr->_ref_count << ")";
+      // os << "{" << GetValueWidth() << "}";
+    }
+    else if (IsAlreadyPrinted()) {
+      // print non-symbols as "[index]" if seen before.
+      os << "[" << GetNodeNum() << "]";
+      //	   << "(" << _int_node_ptr->_ref_count << ")";
+    }
+    else {
+      MarkAlreadyPrinted();
+      const ASTVec &children = GetChildren();
+      os << GetNodeNum() << ":"
+	//<< "(" << _int_node_ptr->_ref_count << ")" 
+	 << "(" << kind << " ";
+      // os << "{" << GetValueWidth() << "}";
+      ASTVec::const_iterator iend = children.end();
+      for (ASTVec::const_iterator i = children.begin(); i != iend; i++) {
+	i->LispPrint_indent(os, indentation+2);
+	}
+      os << ")";	
+    }
+    return os;
+  }
+
+  //print in PRESENTATION LANGUAGE
+  //
+  //two pass algorithm: 
+  //
+  //1. In the first pass, letize this Node, N: i.e. if a node
+  //1. appears more than once in N, then record this fact.
+  //
+  //2. In the second pass print a "global let" and then print N
+  //2. as follows: Every occurence of a node occuring more than
+  //2. once is replaced with the corresponding let variable.
+  ostream& ASTNode::PL_Print(ostream &os,
+			     int indentation) const {
+    // Clear the PrintMap
+    BeevMgr& bm = GetBeevMgr(); 
+    bm.PLPrintNodeSet.clear();
+    bm.NodeLetVarMap.clear();
+    bm.NodeLetVarVec.clear();
+    bm.NodeLetVarMap1.clear();
+
+    //pass 1: letize the node
+    LetizeNode();
+
+    //pass 2: 
+    //
+    //2. print all the let variables and their counterpart expressions
+    //2. as follows (LET var1 = expr1, var2 = expr2, ...
+    //
+    //3. Then print the Node itself, replacing every occurence of
+    //3. expr1 with var1, expr2 with var2, ...
+    //os << "(";
+    if(0 < bm.NodeLetVarMap.size()) {
+      //ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
+      //ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
+      std::vector<pair<ASTNode,ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
+      std::vector<pair<ASTNode,ASTNode> >::iterator itend = bm.NodeLetVarVec.end();
+
+      os << "(LET ";      
+      //print the let var first
+      it->first.PL_Print1(os,indentation,false);
+      os << " = ";
+      //print the expr
+      it->second.PL_Print1(os,indentation,false);
+
+      //update the second map for proper printing of LET
+      bm.NodeLetVarMap1[it->second] = it->first;
+
+      for(it++;it!=itend;it++) {
+        os << "," << endl;
+	//print the let var first
+	it->first.PL_Print1(os,indentation,false);
+	os << " = ";
+	//print the expr
+	it->second.PL_Print1(os,indentation,false);
+
+        //update the second map for proper printing of LET
+        bm.NodeLetVarMap1[it->second] = it->first;
+      }
+    
+      os << " IN " << endl;      
+      PL_Print1(os,indentation, true);
+      os << ") ";
+    }
+    else
+      PL_Print1(os,indentation, false);
+    //os << " )";
+    os << " ";
+    return os;
+  } //end of PL_Print()
+
+  //traverse "*this", and construct "let variables" for terms that
+  //occur more than once in "*this".
+  void ASTNode::LetizeNode(void) const {
+    Kind kind = this->GetKind();
+
+    if(kind == SYMBOL  || 
+       kind == BVCONST ||
+       kind == FALSE   ||
+       kind == TRUE)
+      return;
+
+    //FIXME: this is ugly.
+    BeevMgr& bm = GetBeevMgr();     
+    const ASTVec &c = this->GetChildren();
+    for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
+      ASTNode ccc = *it;
+      if(bm.PLPrintNodeSet.find(ccc) == bm.PLPrintNodeSet.end()){
+	//If branch: if *it is not in NodeSet then,
+	//
+	//1. add it to NodeSet
+	//
+	//2. Letize its childNodes
+
+	//FIXME: Fetching BeevMgr is annoying.  Can we put this in
+	//some kind of a printer class
+	bm.PLPrintNodeSet.insert(ccc);
+	//debugging
+	//cerr << ccc;
+	ccc.LetizeNode();
+      } 
+      else{
+	Kind k = ccc.GetKind();
+	if(k == SYMBOL  || 
+	   k == BVCONST ||
+	   k == FALSE   ||
+	   k == TRUE)
+	  continue;
+	
+	//0. Else branch: Node has been seen before
+	//
+	//1. Check if the node has a corresponding letvar in the
+	//1. NodeLetVarMap.
+	//
+	//2. if no, then create a new var and add it to the
+	//2. NodeLetVarMap
+	if(bm.NodeLetVarMap.find(ccc) == bm.NodeLetVarMap.end()) {
+	  //Create a new symbol. Get some name. if it conflicts with a
+	  //declared name, too bad. 
+	  int sz = bm.NodeLetVarMap.size();
+	  ostringstream oss;
+	  oss << "let_k_" << sz;
+
+	  ASTNode CurrentSymbol = bm.CreateSymbol(oss.str().c_str());
+	  CurrentSymbol.SetValueWidth(this->GetValueWidth());
+	  CurrentSymbol.SetIndexWidth(this->GetIndexWidth());	  
+	  /* If for some reason the variable being created here is
+	   * already declared by the user then the printed output will
+	   * not be a legal input to the system. too bad. I refuse to
+	   * check for this.  [Vijay is the author of this comment.]
+	   */
+	  
+	  bm.NodeLetVarMap[ccc] = CurrentSymbol;
+	  std::pair<ASTNode,ASTNode> node_letvar_pair(CurrentSymbol,ccc);
+	  bm.NodeLetVarVec.push_back(node_letvar_pair);
+	}
+      }    
+    }
+  } //end of LetizeNode()
+
+  void ASTNode::PL_Print1(ostream& os,
+			  int indentation, 
+			  bool letize) const {
+    //os << spaces(indentation);
+    //os << endl << spaces(indentation);
+    if (!IsDefined()) {
+      os << "<undefined>";
+      return;
+    }
+    
+    //if this node is present in the letvar Map, then print the letvar
+    BeevMgr &bm = GetBeevMgr();
+
+    //this is to print letvars for shared subterms inside the printing
+    //of "(LET v0 = term1, v1=term1@term2,...
+    if((bm.NodeLetVarMap1.find(*this) != bm.NodeLetVarMap1.end()) && !letize) {
+      (bm.NodeLetVarMap1[*this]).PL_Print1(os,indentation,letize);
+      return;
+    }
+
+    //this is to print letvars for shared subterms inside the actual
+    //term to be printed
+    if((bm.NodeLetVarMap.find(*this) != bm.NodeLetVarMap.end()) && letize) {
+      (bm.NodeLetVarMap[*this]).PL_Print1(os,indentation,letize);
+      return;
+    }
+    
+    //otherwise print it normally
+    Kind kind = GetKind();
+    const ASTVec &c = GetChildren();     
+    switch(kind) {
+    case BVGETBIT:
+      c[0].PL_Print1(os,indentation,letize);
+      os << "{";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "}";
+      break;
+    case BITVECTOR:
+      os << "BITVECTOR(";
+      unsigned char * str;
+      str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
+      os << str << ")";
+      CONSTANTBV::BitVector_Dispose(str);
+      break;
+    case BOOLEAN:
+      os << "BOOLEAN";
+      break;
+    case FALSE:
+    case TRUE:
+      os << kind;
+      break;
+    case BVCONST:
+    case SYMBOL:
+      _int_node_ptr->nodeprint(os); 
+      break;
+    case READ:
+      c[0].PL_Print1(os, indentation,letize);
+      os << "[";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "]";
+      break;
+    case WRITE:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " WITH [";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "] := ";
+      c[2].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << endl;
+      break;
+    case BVUMINUS:
+      os << kind << "( ";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case NOT:
+      os << "NOT(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ") " << endl;
+      break;
+    case BVNEG:
+      os << " ~(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVCONCAT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " @ ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVOR:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " | ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVAND:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " & ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVEXTRACT:
+      c[0].PL_Print1(os,indentation,letize);
+      os << "[";
+      os << GetUnsignedConst(c[1]);
+      os << ":";
+      os << GetUnsignedConst(c[2]);
+      os << "]";
+      break;
+    case BVLEFTSHIFT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " << ";
+      os << GetUnsignedConst(c[1]);
+      os << ")";
+      break;
+    case BVRIGHTSHIFT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " >> ";
+      os << GetUnsignedConst(c[1]);
+      os << ")";
+      break;
+    case BVMULT:
+    case BVSUB:
+    case BVPLUS:
+    case SBVDIV:      
+    case SBVMOD:
+    case BVDIV:      
+    case BVMOD:
+      os << kind << "(";
+      os << this->GetValueWidth();
+      for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	os << ", " << endl;
+	it->PL_Print1(os,indentation,letize);	
+      }
+      os << ")" << endl;
+      break;    
+    case ITE:
+      os << "IF(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      os << "THEN ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << endl << "ELSE ";
+      c[2].PL_Print1(os,indentation,letize);
+      os << endl << "ENDIF";
+      break;
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVXOR:
+    case BVNAND:
+    case BVNOR:
+    case BVXNOR:
+      os << kind << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSLT:
+      os << "SBVLT" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSLE:
+      os << "SBVLE" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSGT:
+      os << "SBVGT" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSGE:
+      os << "SBVGE" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case EQ:
+      c[0].PL_Print1(os,indentation,letize);
+      os << " = ";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << endl;
+      break;
+    case NEQ:
+      c[0].PL_Print1(os,indentation,letize);
+      os << " /= ";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << endl;
+      break;
+    case AND:
+    case OR:
+    case NAND:
+    case NOR:
+    case XOR: {
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      ASTVec::const_iterator it=c.begin();
+      ASTVec::const_iterator itend=c.end();
+
+      it++;
+      for(;it!=itend;it++) {
+	os << " " << kind << " ";
+	it->PL_Print1(os,indentation,letize);
+	os << endl;
+      }
+      os << ")";
+      break;
+    }
+    case IFF:
+      os << "(";
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << " <=> ";
+      os << "(";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << ")";
+      os << ")";
+      os << endl;
+      break;
+    case IMPLIES:
+      os << "(";
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << " => ";
+      os << "(";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << ")";
+      os << endl;
+      break;
+    case BVSX:
+      os << kind << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      os << this->GetValueWidth();
+      os << ")" << endl;
+      break;
+    default:
+      //remember to use LispPrinter here. Otherwise this function will
+      //go into an infinite loop. Recall that "<<" is overloaded to
+      //the lisp printer. FatalError uses lispprinter
+      FatalError("PL_Print1: printing not implemented for this kind: ",*this);
+      break;
+    }
+  } //end of PL_Print1()
+
+  ////////////////////////////////////////////////////////////////
+  //  BeevMgr members
+  ////////////////////////////////////////////////////////////////
+  ASTNode BeevMgr::CreateNode(Kind kind, const ASTVec & back_children) {
+    // create a new node.  Children will be modified.
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+
+    // insert all of children at end of new_children.
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTVec & back_children) {
+
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    ASTNode n(CreateInteriorNode(kind, n_ptr,  back_children));
+    return n;
+  }
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTNode& child1,
+			      const ASTVec & back_children) {
+
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    front_children.push_back(child1);
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTNode& child1,
+			      const ASTNode& child2,
+			      const ASTVec & back_children) {
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    front_children.push_back(child1);
+    front_children.push_back(child2);
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  
+  ASTInterior *BeevMgr::CreateInteriorNode(Kind kind,
+					   // children array of this node will be modified.
+					   ASTInterior *n_ptr,
+					   const ASTVec & back_children) {
+
+    // insert back_children at end of front_children
+    ASTVec &front_children = n_ptr->_children;
+
+    front_children.insert(front_children.end(), back_children.begin(), back_children.end());
+
+    // check for undefined nodes.
+    ASTVec::const_iterator it_end = front_children.end();
+    for (ASTVec::const_iterator it = front_children.begin(); it != it_end; it++) {
+      if (it->IsNull())
+	FatalError("CreateInteriorNode: Undefined childnode in CreateInteriorNode: ", ASTUndefined);      
+    }
+
+    return LookupOrCreateInterior(n_ptr);
+  }
+    
+  /** Trivial but virtual destructor */
+  ASTSymbol::~ASTSymbol() {}
+  
+  ostream &operator<<(ostream &os, const ASTNodeMap &nmap)
+  {
+    ASTNodeMap::const_iterator iend = nmap.end();
+    for (ASTNodeMap::const_iterator i = nmap.begin(); i!=iend; i++) {
+      os << "Key: " << i->first << endl;
+      os << "Value: " << i->second << endl;
+    }
+    return os;
+  }
+  
+  ////////////////////////////////////////////////////////////////
+  // BeevMgr member functions to create ASTSymbol and ASTBVConst
+  ////////////////////////////////////////////////////////////////
+  ASTNode BeevMgr::CreateSymbol(const char * const name) 
+  { 
+    ASTSymbol temp_sym(name, *this);
+    ASTNode n(LookupOrCreateSymbol(temp_sym));
+    return n;
+  }
+
+#ifndef NATIVE_C_ARITH
+  //Create a ASTBVConst node
+  ASTNode BeevMgr::CreateBVConst(unsigned int width, 
+				 unsigned long long int bvconst){ 
+    if(width > (sizeof(unsigned long long int)<<3) || width <= 0)
+      FatalError("CreateBVConst: trying to create a bvconst of width: ", ASTUndefined, width);
+    
+
+    CBV bv = CONSTANTBV::BitVector_Create(width, true);
+    unsigned long c_val = (0x00000000ffffffffLL) & bvconst;
+    unsigned int copied = 0;
+
+    // sizeof(unsigned long) returns the number of bytes in unsigned
+    // long. In order to convert it to bits, we need to shift left by
+    // 3. Hence, sizeof(unsigned long) << 3
+
+    //The algo below works as follows: It starts by copying the
+    //lower-order bits of the input "bvconst" in chunks of size =
+    //number of bits in unsigned long. The variable "copied" keeps
+    //track of the number of chunks copied so far
+
+    while(copied + (sizeof(unsigned long)<<3) < width){
+      CONSTANTBV::BitVector_Chunk_Store(bv, sizeof(unsigned long)<<3,copied,c_val);
+      bvconst = bvconst >> (sizeof(unsigned long) << 3);
+      c_val = (0x00000000ffffffffLL) & bvconst;
+      copied += sizeof(unsigned long) << 3;
+    }
+    CONSTANTBV::BitVector_Chunk_Store(bv,width - copied,copied,c_val);
+    return CreateBVConst(bv,width);
+  }
+
+  //Create a ASTBVConst node from std::string
+  ASTNode BeevMgr::CreateBVConst(const char* const strval, int base) {
+    size_t width = strlen((const char *)strval);    
+    if(!(2 == base || 10 == base || 16 == base)){
+      FatalError("CreateBVConst: unsupported base: ",ASTUndefined,base);
+    }
+    //FIXME Tim: Earlier versions of the code assume that the length of
+    //binary strings is 32 bits.
+    if(10 == base) width = 32;
+    if(16 == base) width = width * 4;
+
+    //checking if the input is in the correct format
+    CBV bv = CONSTANTBV::BitVector_Create(width,true);
+    CONSTANTBV::ErrCode e;
+    if(2 == base){
+      e = CONSTANTBV::BitVector_from_Bin(bv, (unsigned char*)strval);
+    }else if(10 == base){
+      e = CONSTANTBV::BitVector_from_Dec(bv, (unsigned char*)strval);
+    }else if(16 == base){
+      e = CONSTANTBV::BitVector_from_Hex(bv, (unsigned char*)strval);
+    }else{
+      e = CONSTANTBV::ErrCode_Pars;
+    }
+
+    if(0 != e) {
+      cerr << "CreateBVConst: " << BitVector_Error(e);
+      FatalError("",ASTUndefined);
+    }
+
+    //FIXME 
+    return CreateBVConst(bv, width);
+  }
+  
+
+  //FIXME Code currently assumes that it will destroy the bitvector passed to it
+  ASTNode BeevMgr::CreateBVConst(CBV bv, unsigned width){
+     ASTBVConst temp_bvconst(bv, width, *this);
+     ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+     
+     CONSTANTBV::BitVector_Destroy(bv);
+     
+     return n;
+  }
+
+  ASTNode BeevMgr::CreateZeroConst(unsigned width) {
+    CBV z = CONSTANTBV::BitVector_Create(width, true);
+    return CreateBVConst(z, width);
+  }
+  
+  ASTNode BeevMgr::CreateOneConst(unsigned width) {
+    CBV o = CONSTANTBV::BitVector_Create(width, true);
+    CONSTANTBV::BitVector_increment(o);
+    
+    return CreateBVConst(o,width);
+  }
+
+  ASTNode BeevMgr::CreateTwoConst(unsigned width) {
+    CBV two = CONSTANTBV::BitVector_Create(width, true);
+    CONSTANTBV::BitVector_increment(two);
+    CONSTANTBV::BitVector_increment(two);
+
+    return CreateBVConst(two,width);
+  }
+
+  ASTNode BeevMgr::CreateMaxConst(unsigned width) {
+    CBV max = CONSTANTBV::BitVector_Create(width, false);
+    CONSTANTBV::BitVector_Fill(max);
+
+    return CreateBVConst(max,width);
+  }
+
+  //To ensure unique BVConst nodes, lookup the node in unique-table
+  //before creating a new one.
+  ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
+    ASTBVConst *s_ptr = &s;  // it's a temporary key.
+    
+    // Do an explicit lookup to see if we need to create a copy of the string.    
+    ASTBVConstSet::const_iterator it;
+    if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
+      // Make a new ASTBVConst with duplicated string (can't assign
+      // _name because it's const).  Can cast the iterator to
+      // non-const -- carefully.
+
+      ASTBVConst * s_copy = new ASTBVConst(s);      
+      s_copy->SetNodeNum(NewNodeNum());
+      
+      pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_copy);
+      return *p.first;
+    }
+    else{
+      // return symbol found in table.
+      return *it;
+    }
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTBVConst::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._bvconst_unique_table.erase(this);
+    delete this;
+  }
+
+  // Get the value of bvconst from a bvconst.  It's an error if kind != BVCONST
+  CBV const ASTNode::GetBVConst() const {
+    if(GetKind() != BVCONST)
+      FatalError("GetBVConst: non bitvector-constant: ",*this);
+    return ((ASTBVConst *) _int_node_ptr)->GetBVConst();      
+  }
+#else
+  //Create a ASTBVConst node
+  ASTNode BeevMgr::CreateBVConst(const unsigned int width, 
+				 const unsigned long long int bvconst) { 
+    if(width > 64 || width <= 0)
+      FatalError("Fatal Error: CreateBVConst: trying to create a bvconst of width:", ASTUndefined, width);
+    
+    //64 bit mask
+    unsigned long long int mask = 0xffffffffffffffffLL;
+    mask = mask >> (64 - width);
+
+    unsigned long long int bv = bvconst;
+    bv = bv & mask;
+
+    ASTBVConst temp_bvconst(bv, *this);
+    temp_bvconst._value_width = width;    
+    ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+    n.SetValueWidth(width);
+    n.SetIndexWidth(0);
+    return n;
+  }
+  //Create a ASTBVConst node from std::string
+  ASTNode BeevMgr::CreateBVConst(const char* strval, int base) {    
+    if(!(base == 2 || base == 16 || base == 10))
+      FatalError("CreateBVConst: This base is not supported: ", ASTUndefined, base);
+
+    if(10 != base) {
+      unsigned int width = (base == 2) ? strlen(strval) : strlen(strval)*4;
+      unsigned long long int val =  strtoull(strval, NULL, base);
+      ASTNode bvcon = CreateBVConst(width, val);
+      return bvcon;
+    }
+    else {
+      //this is an ugly hack to accomodate SMTLIB format
+      //restrictions. SMTLIB format represents bitvector constants in
+      //base 10 (what a terrible idea, but i have no choice but to
+      //support it), and make an implicit assumption that the length
+      //is 32 (another terrible idea).
+      unsigned width = 32;
+      unsigned long long int val = strtoull(strval, NULL, base);
+      ASTNode bvcon = CreateBVConst(width, val);
+      return bvcon;
+    }
+  }
+  
+  //To ensure unique BVConst nodes, lookup the node in unique-table
+  //before creating a new one.
+  ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
+    ASTBVConst *s_ptr = &s;	// it's a temporary key.
+
+    // Do an explicit lookup to see if we need to create a copy of the
+    // string.
+    ASTBVConstSet::const_iterator it;
+    if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
+      // Make a new ASTBVConst. Can cast the iterator to non-const --
+      // carefully.
+      unsigned int width = s_ptr->_value_width;
+      ASTBVConst * s_ptr1 = new ASTBVConst(s_ptr->GetBVConst(), *this);
+      s_ptr1->SetNodeNum(NewNodeNum());
+      s_ptr1->_value_width = width;
+      pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_ptr1);
+      return *p.first;
+    }
+    else
+      // return BVConst found in table.
+      return *it;
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTBVConst::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._bvconst_unique_table.erase(this);
+    delete this;
+  }
+
+  // Get the value of bvconst from a bvconst.  It's an error if kind
+  // != BVCONST
+  unsigned long long int ASTNode::GetBVConst() const {
+    if(GetKind() != BVCONST)
+      FatalError("GetBVConst: non bitvector-constant: ", *this);
+    return ((ASTBVConstTmp *) _int_node_ptr)->GetBVConst();
+  }
+
+  ASTNode BeevMgr::CreateZeroConst(unsigned width) {
+    return CreateBVConst(width,0);
+  }
+  
+  ASTNode BeevMgr::CreateOneConst(unsigned width) {
+    return CreateBVConst(width,1);
+  }
+
+  ASTNode BeevMgr::CreateTwoConst(unsigned width) {
+    return CreateBVConst(width,2);
+  }
+
+  ASTNode BeevMgr::CreateMaxConst(unsigned width) {
+    std::string s;
+    s.insert(s.end(),width,'1');
+    return CreateBVConst(s.c_str(),2);
+  }
+
+#endif  
+
+  // FIXME: _name is now a constant field, and this assigns to it
+  // because it tries not to copy the string unless it needs to.  How
+  // do I avoid copying children in ASTInterior?  Perhaps I don't!
+  
+  // Note: There seems to be a limitation of hash_set, in that insert
+  // returns a const iterator to the value.  That prevents us from
+  // modifying the name (in a hash-preserving way) after the symbol is
+  // inserted.  FIXME: Is there a way to do this with insert?  Need a
+  // function to make a new object in the middle of insert.  Read STL
+  // documentation.
+  
+  ASTSymbol *BeevMgr::LookupOrCreateSymbol(ASTSymbol& s) {
+    ASTSymbol *s_ptr = &s;  // it's a temporary key.
+    
+    // Do an explicit lookup to see if we need to create a copy of the string.    
+    ASTSymbolSet::const_iterator it;
+    if ((it = _symbol_unique_table.find(s_ptr)) == _symbol_unique_table.end()) {
+      // Make a new ASTSymbol with duplicated string (can't assign
+      // _name because it's const).  Can cast the iterator to
+      // non-const -- carefully.
+      //std::string strname(s_ptr->GetName());
+      ASTSymbol * s_ptr1 = new ASTSymbol(strdup(s_ptr->GetName()), *this);
+      s_ptr1->SetNodeNum(NewNodeNum());
+      s_ptr1->_value_width = s_ptr->_value_width;
+      pair<ASTSymbolSet::const_iterator, bool> p = _symbol_unique_table.insert(s_ptr1);
+      return *p.first;
+    }
+    else
+      // return symbol found in table.
+      return *it;    
+  }
+
+  bool BeevMgr::LookupSymbol(ASTSymbol& s) {
+    ASTSymbol* s_ptr = &s;  // it's a temporary key.
+
+    if(_symbol_unique_table.find(s_ptr) == _symbol_unique_table.end()) 
+      return false;
+    else
+      return true;
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTSymbol::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._symbol_unique_table.erase(this);
+    //FIXME This is a HUGE free to invoke.
+    //TEST IT!
+    free((char*) this->_name);
+    delete this;
+  }
+  
+  ////////////////////////////////////////////////////////////////
+  //
+  //  IO manipulators for Lisp format printing of AST.
+  //
+  ////////////////////////////////////////////////////////////////
+  
+  // FIXME: Additional controls
+  //   * Print node numbers  (addresses/nums)
+  //   * Printlength limit
+  //   * Printdepth limit
+  
+  /** Print a vector of ASTNodes in lisp format */
+  ostream &LispPrintVec(ostream &os, const ASTVec &v, int indentation)
+  {
+    // Print the children
+    ASTVec::const_iterator iend = v.end();
+    for (ASTVec::const_iterator i = v.begin(); i != iend; i++) {
+      i->LispPrint_indent(os, indentation);
+    }
+    return os;
+  }
+
+  // FIXME: Made non-ref in the hope that it would work better.
+  void lp(ASTNode node)
+  {
+    cout << lisp(node) << endl;
+  }
+
+  void lpvec(const ASTVec &vec)
+  {
+    vec[0].GetBeevMgr().AlreadyPrintedSet.clear();
+    LispPrintVec(cout, vec, 0);
+    cout << endl;
+  }
+
+  // Copy constructor.  Maintain _ref_count
+  ASTNode::ASTNode(const ASTNode &n) : _int_node_ptr(n._int_node_ptr) {
+#ifndef SMTLIB    
+    if (n._int_node_ptr) {
+      n._int_node_ptr->IncRef();
+    }
+#endif
+  }
+  
+
+  /* FUNCTION: Typechecker for terms and formulas
+   * 
+   * TypeChecker: Assumes that the immediate Children of the input
+   * ASTNode have been typechecked. This function is suitable in
+   * scenarios like where you are building the ASTNode Tree, and you
+   * typecheck as you go along. It is not suitable as a general
+   * typechecker      
+   */
+  void BeevMgr::BVTypeCheck(const ASTNode& n) {
+    Kind k = n.GetKind();
+    //The children of bitvector terms are in turn bitvectors.
+    ASTVec v = n.GetChildren();
+    if(is_Term_kind(k)) {
+      switch(k) {
+      case BVCONST:
+	if(BITVECTOR_TYPE != n.GetType())
+	  FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",n);
+	break;
+      case SYMBOL:
+	return;
+      case ITE:     
+	if(BOOLEAN_TYPE != n[0].GetType() && 
+	   BITVECTOR_TYPE != n[1].GetType() &&
+	   BITVECTOR_TYPE != n[2].GetType())
+	  FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",n);
+	if(n[1].GetValueWidth() != n[2].GetValueWidth())
+	  FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n",n);
+	if(n[1].GetIndexWidth() != n[2].GetIndexWidth())
+	  FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n",n);
+	break;
+      case READ:
+	if(n[0].GetIndexWidth() != n[1].GetValueWidth()) {
+	  cerr << "Length of indexwidth of array: " << n[0] << " is : " << n[0].GetIndexWidth() << endl;
+	  cerr << "Length of the actual index is: " << n[1] << " is : " << n[1].GetValueWidth() << endl;
+	  FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n",n);
+	}
+	break;      
+      case WRITE:
+	if(n[0].GetIndexWidth() != n[1].GetValueWidth())
+	  FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n",n);
+	if(n[0].GetValueWidth() != n[2].GetValueWidth())
+	  FatalError("BVTypeCheck: valuewidth of array != length of actual value in the term t = \n",n);
+	break;      
+      case BVOR:
+      case BVAND:
+      case BVXOR:
+      case BVNOR:
+      case BVNAND:
+      case BVXNOR: 
+      case BVPLUS: 
+      case BVMULT:
+      case BVDIV:
+      case BVMOD:
+      case BVSUB: {
+	if(!(v.size() >= 2))
+	  FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have atleast two arguments\n",n);
+	unsigned int width = n.GetValueWidth();
+	for(ASTVec::iterator it=v.begin(),itend=v.end();it!=itend;it++){
+	  if(width != it->GetValueWidth()) {
+	    cerr << "BVTypeCheck:Operands of bitwise-Booleans and BV arith operators must be of equal length\n";
+	    cerr << n << endl;
+	    cerr << "width of term:" << width << endl;
+	    cerr << "width of offending operand:" << it->GetValueWidth() << endl;
+	    FatalError("BVTypeCheck:Offending operand:\n",*it);
+	  }
+	  if(BITVECTOR_TYPE != it->GetType())
+	    FatalError("BVTypeCheck: ChildNodes of bitvector-terms must be bitvectors\n",n);
+	}
+	break;
+      }
+      case BVSX:
+	//in BVSX(n[0],len), the length of the BVSX term must be
+	//greater than the length of n[0]
+	if(n[0].GetValueWidth() >= n.GetValueWidth()) {
+	  FatalError("BVTypeCheck: BVSX(t,bvsx_len) : length of 't' must be <= bvsx_len\n",n);
+	} 
+	break;
+      default:
+	for(ASTVec::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);
+	  }
+	break;
+      }
+      
+      switch(k) {
+      case BVCONCAT:
+	if(n.Degree() != 2)
+	  FatalError("BVTypeCheck: should have exactly 2 args\n",n);
+	if(n.GetValueWidth() != n[0].GetValueWidth() + n[1].GetValueWidth())
+	  FatalError("BVTypeCheck:BVCONCAT: lengths do not add up\n",n);	
+	break;
+      case BVUMINUS:
+      case BVNEG:
+	if(n.Degree() != 1)
+	  FatalError("BVTypeCheck: should have exactly 1 args\n",n);
+	break;
+      case BVEXTRACT:
+	if(n.Degree() != 3)
+	  FatalError("BVTypeCheck: should have exactly 3 args\n",n);
+	if(!(BVCONST == n[1].GetKind() && BVCONST == n[2].GetKind()))
+	  FatalError("BVTypeCheck: indices should be BVCONST\n",n);
+	if(n.GetValueWidth() != GetUnsignedConst(n[1])- GetUnsignedConst(n[2])+1)
+	  FatalError("BVTypeCheck: length mismatch\n",n);
+	break;
+      case BVLEFTSHIFT:
+      case BVRIGHTSHIFT:
+	if(n.Degree() != 2)
+	  FatalError("BVTypeCheck: should have exactly 2 args\n",n);
+	break;
+	//case BVVARSHIFT:
+	//case BVSRSHIFT:
+	break;
+      default:
+	break;
+      }
+    }
+    else {
+      if(!(is_Form_kind(k) && BOOLEAN_TYPE == n.GetType()))
+	FatalError("BVTypeCheck: not a formula:",n);
+      switch(k){
+      case TRUE:
+      case FALSE:
+      case SYMBOL:
+	return;
+      case EQ:
+      case NEQ:	 
+	if(!(n[0].GetValueWidth() == n[1].GetValueWidth() &&
+	     n[0].GetIndexWidth() == n[1].GetIndexWidth())) {
+	  cerr << "valuewidth of lhs of EQ: " << n[0].GetValueWidth() << endl;
+	  cerr << "valuewidth of rhs of EQ: " << n[1].GetValueWidth() << endl;
+	  cerr << "indexwidth of lhs of EQ: " << n[0].GetIndexWidth() << endl;
+	  cerr << "indexwidth of rhs of EQ: " << n[1].GetIndexWidth() << endl;
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	}
+	break;
+      case BVLT:
+      case BVLE:
+      case BVGT:
+      case BVGE:
+      case BVSLT:
+      case BVSLE:
+      case BVSGT:
+      case BVSGE:	
+	if(BITVECTOR_TYPE != n[0].GetType() && BITVECTOR_TYPE != n[1].GetType())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be bitvectors",n);
+	if(n[0].GetValueWidth() != n[1].GetValueWidth())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	if(n[0].GetIndexWidth() != n[1].GetIndexWidth())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	break;
+      case NOT:
+	if(1 != n.Degree())
+	  FatalError("BVTypeCheck: NOT formula can have exactly one childNode",n);
+	break;
+      case AND:
+      case OR:
+      case XOR:
+      case NAND:
+      case NOR:
+	if(2 > n.Degree())
+	  FatalError("BVTypeCheck: AND/OR/XOR/NAND/NOR: must have atleast 2 ChildNodes",n);
+	break;
+      case IFF:
+      case IMPLIES:	
+	if(2 != n.Degree())
+	  FatalError("BVTypeCheck:IFF/IMPLIES must have exactly 2 ChildNodes",n);
+	break;
+      case ITE:
+	if(3 != n.Degree())
+	  FatalError("BVTypeCheck:ITE must have exactly 3 ChildNodes",n);		
+	break;
+      default:
+	FatalError("BVTypeCheck: Unrecognized kind: ",ASTUndefined);
+	break;
+      }
+    }
+  } //End of TypeCheck function
+
+  //add an assertion to the current logical context
+  void BeevMgr::AddAssert(const ASTNode& assert) {
+    if(!(is_Form_kind(assert.GetKind()) && BOOLEAN_TYPE == assert.GetType())) {
+      FatalError("AddAssert:Trying to assert a non-formula:",assert);
+    }
+      
+    ASTVec * v;
+    //if the stack of ASTVec is not empty, then take the top ASTVec
+    //and add the input assert to it
+    if(!_asserts.empty()) {
+      v = _asserts.back();
+      //v->push_back(TransformFormula(assert));
+      v->push_back(assert);
+    }
+    else {
+      //else create a logical context, and add it to the top of the
+      //stack
+      v = new ASTVec();
+      //v->push_back(TransformFormula(assert));
+      v->push_back(assert);
+      _asserts.push_back(v);	
+    }
+  }
+  
+  void BeevMgr::Push(void) {
+    ASTVec * v;
+    v = new ASTVec();
+    _asserts.push_back(v);
+  }
+  
+  void BeevMgr::Pop(void) {
+    if(!_asserts.empty()) {
+       ASTVec * c = _asserts.back();
+             //by calling the clear function we ensure that the ref count is
+             //decremented for the ASTNodes stored in c
+             c->clear();
+             delete c;
+      _asserts.pop_back();
+    }
+  }
+
+  void BeevMgr::AddQuery(const ASTNode& q) {
+    //_current_query = TransformFormula(q);
+    //cerr << "\nThe current query is: " << q << endl;
+    _current_query = q;
+  }
+    
+  const ASTNode BeevMgr::PopQuery() {
+    ASTNode q = _current_query;
+    _current_query = ASTTrue;
+    return q;
+  }
+   
+  const ASTNode BeevMgr::GetQuery() {
+    return _current_query;
+  }
+  
+  const ASTVec BeevMgr::GetAsserts(void) {
+    vector<ASTVec *>::iterator it = _asserts.begin();
+    vector<ASTVec *>::iterator itend = _asserts.end();
+    
+    ASTVec v;
+    for(;it!=itend;it++) {
+      if(!(*it)->empty())
+	  v.insert(v.end(),(*it)->begin(),(*it)->end());
+    }
+    return v;
+  }
+
+  //Create a new variable of ValueWidth 'n'
+  ASTNode BeevMgr::NewArrayVar(unsigned int index, unsigned int value) {
+    std:: string c("v");
+    char d[32];
+    sprintf(d,"%d",_symbol_count++);
+    std::string ccc(d);
+    c += "_writearray_" + ccc;
+    
+    ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+    CurrentSymbol.SetValueWidth(value);
+    CurrentSymbol.SetIndexWidth(index);
+    return CurrentSymbol;
+  } //end of NewArrayVar()
+
+
+  //Create a new variable of ValueWidth 'n'
+  ASTNode BeevMgr::NewVar(unsigned int value) {
+    std:: string c("v");
+    char d[32];
+    sprintf(d,"%d",_symbol_count++);
+    std::string ccc(d);
+    c += "_new_stp_var_" + ccc;
+    
+    ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+    CurrentSymbol.SetValueWidth(value);
+    CurrentSymbol.SetIndexWidth(0);
+    _introduced_symbols.insert(CurrentSymbol);
+    return CurrentSymbol;
+  } //end of NewVar()
+
+  //prints statistics for the ASTNode
+  void BeevMgr::ASTNodeStats(const char * c, const ASTNode& a){
+    if(!stats)
+      return;
+
+    StatInfoSet.clear();
+    //print node size:
+    cout << endl << "Printing: " << c;
+    if(print_nodes) {
+      //a.PL_Print(cout,0);
+      //cout << endl;
+      cout << a << endl;
+    }
+    cout << "Node size is: ";
+    cout << NodeSize(a) << endl << endl;    
+  }
+
+  unsigned int BeevMgr::NodeSize(const ASTNode& a, bool clearStatInfo) {    
+    if(clearStatInfo)
+      StatInfoSet.clear();
+
+    ASTNodeSet::iterator it;
+    if((it = StatInfoSet.find(a)) != StatInfoSet.end())
+      //has already been counted
+      return 0;
+
+    //record that you have seen this node already
+    StatInfoSet.insert(a);
+    
+    //leaf node has a size of 1
+    if(a.Degree() == 0)
+      return 1;
+
+    unsigned newn = 1;
+    ASTVec c = a.GetChildren();
+    for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
+      newn += NodeSize(*it);
+    return newn;
+  }
+
+  void BeevMgr::ClearAllTables(void) {
+    //clear all tables before calling toplevelsat
+    _ASTNode_to_SATVar.clear();
+    _SATVar_to_AST.clear();
+
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
+	  itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
+      delete it->second;
+    }
+    _ASTNode_to_Bitvector.clear();
+    
+    /* OLD Destructor
+     * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+
+    /*What should I do here? For ASTNodes?
+     * for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+    BBTermMemo.clear();
+    BBFormMemo.clear();
+    NodeLetVarMap.clear();
+    NodeLetVarMap1.clear();
+    PLPrintNodeSet.clear();
+    AlreadyPrintedSet.clear();
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    SolverMap.clear();
+    AlwaysTrueFormMap.clear();
+    _arrayread_ite.clear();
+    _arrayread_symbol.clear();
+    _introduced_symbols.clear();
+    TransformMap.clear();
+    _letid_expr_map.clear();
+    CounterExampleMap.clear();
+    ComputeFormulaMap.clear();
+    StatInfoSet.clear();
+
+    // for(std::vector<ASTVec *>::iterator it=_asserts.begin(),
+    // 	  itend=_asserts.end();it!=itend;it++) {
+    //       (*it)->clear();
+    //     }
+    _asserts.clear();
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), 
+	  iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      iset->second.clear();
+    }
+
+    _arrayname_readindices.clear();
+    _interior_unique_table.clear();
+    _symbol_unique_table.clear();
+    _bvconst_unique_table.clear();
+  }
+
+  void BeevMgr::ClearAllCaches(void) {
+    //clear all tables before calling toplevelsat
+    _ASTNode_to_SATVar.clear();
+    _SATVar_to_AST.clear();
+
+
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
+	  itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
+      delete it->second;
+    }
+    _ASTNode_to_Bitvector.clear();
+    
+    /*OLD destructor
+     * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+
+    /*What should I do here?
+     *for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+    BBTermMemo.clear();
+    BBFormMemo.clear();
+    NodeLetVarMap.clear();
+    NodeLetVarMap1.clear();
+    PLPrintNodeSet.clear();
+    AlreadyPrintedSet.clear();
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    SolverMap.clear();
+    AlwaysTrueFormMap.clear();
+    _arrayread_ite.clear();
+    _arrayread_symbol.clear();
+    _introduced_symbols.clear();
+    TransformMap.clear();
+    _letid_expr_map.clear();
+    CounterExampleMap.clear();
+    ComputeFormulaMap.clear();
+    StatInfoSet.clear();
+
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), 
+	  iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      iset->second.clear();
+    }
+
+    _arrayname_readindices.clear();
+    //_interior_unique_table.clear();
+    //_symbol_unique_table.clear();
+    //_bvconst_unique_table.clear();
+  }
+
+  void BeevMgr::CopySolverMap_To_CounterExample(void) {
+    if(!SolverMap.empty()) {
+      CounterExampleMap.insert(SolverMap.begin(),SolverMap.end());
+    }
+  }
+
+  void FatalError(const char * str, const ASTNode& a, int w) {
+    if(a.GetKind() != UNDEFINED) {
+      cerr << "Fatal Error: " << str << endl << a << endl;
+      cerr << w << endl;
+    }
+    else {
+      cerr << "Fatal Error: " << str << endl;
+      cerr << w << endl;
+    }
+    if (vc_error_hdlr)
+      vc_error_hdlr(str);
+    exit(-1);
+    //assert(0);
+  }
+
+  void FatalError(const char * str) {
+    cerr << "Fatal Error: " << str << endl;
+    if (vc_error_hdlr)
+      vc_error_hdlr(str);
+    exit(-1);
+    //assert(0);
+  }
+
+  //Variable Order Printer: A global function which converts a MINISAT
+  //var into a ASTNODE var. It then prints this var along with
+  //variable order dcisions taken by MINISAT.
+  void Convert_MINISATVar_To_ASTNode_Print(int minisat_var, 
+  					   int decision_level, int polarity) {
+    BEEV::ASTNode vv = globalBeevMgr_for_parser->_SATVar_to_AST[minisat_var];
+    cout << spaces(decision_level);
+    if(polarity) {
+      cout << "!";
+    }
+    vv.PL_Print(cout,0);
+    cout << endl;
+  }
+
+  void SortByExprNum(ASTVec& v) {
+    sort(v.begin(), v.end(), exprless);
+  }
+
+  bool isAtomic(Kind kind) {
+    if(TRUE == kind ||
+       FALSE == kind ||
+       EQ == kind ||
+       NEQ == kind ||
+       BVLT == kind ||
+       BVLE == kind ||
+       BVGT == kind ||
+       BVGE == kind ||
+       BVSLT == kind ||
+       BVSLE == kind ||
+       BVSGT == kind ||
+       BVSGE == kind ||
+       SYMBOL == kind ||
+       BVGETBIT == kind)
+      return true;
+    return false;
+  }
+
+  BeevMgr::~BeevMgr() {
+    ClearAllTables();
+  }
+}; // end namespace
+
diff --git a/stp/AST/AST.h b/stp/AST/AST.h
new file mode 100644
index 00000000..53ed7016
--- /dev/null
+++ b/stp/AST/AST.h
@@ -0,0 +1,1805 @@
+// -*- c++ -*-
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+
+#ifndef AST_H
+#define AST_H
+#include <vector>
+#ifdef EXT_HASH_MAP
+#include <ext/hash_set>
+#include <ext/hash_map>
+#else
+#include <hash_set>
+#include <hash_map>
+#endif
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <map>
+#include <set>
+#include "ASTUtil.h"
+#include "ASTKind.h"
+#include "../sat/Solver.h"
+#include "../sat/SolverTypes.h"
+#include <cstdlib>
+#ifndef NATIVE_C_ARITH
+#include "../constantbv/constantbv.h"
+#endif
+/*****************************************************************************
+ * LIST OF CLASSES DECLARED IN THIS FILE:
+ *
+ * class BeevMgr;  
+ * class ASTNode; 
+ * class ASTInternal;  
+ * class ASTInterior;  
+ * class ASTSymbol;
+ * class ASTBVConst;
+ *****************************************************************************/
+namespace BEEV {
+  using namespace std; 
+  using namespace MINISAT;
+#ifdef EXT_HASH_MAP
+  using namespace __gnu_cxx;
+#endif
+
+  //return types for the GetType() function in ASTNode class
+  enum types {
+    BOOLEAN_TYPE = 0,
+    BITVECTOR_TYPE,
+    ARRAY_TYPE,
+    UNKNOWN_TYPE
+  };
+  
+  class BeevMgr;  
+  class ASTNode; 
+  class ASTInternal;  
+  class ASTInterior;  
+  class ASTSymbol;
+  class ASTBVConst;
+  class BVSolver;
+
+  //Vector of ASTNodes, used for child nodes among other things.  
+  typedef vector<ASTNode> ASTVec;
+  extern ASTVec _empty_ASTVec;
+  extern BeevMgr * globalBeevMgr_for_parser;
+
+  typedef unsigned int * CBV;
+
+  /***************************************************************************/
+  /*  Class ASTNode: Smart pointer to actual ASTNode internal datastructure. */
+  /***************************************************************************/
+  class ASTNode {
+    friend class BeevMgr;
+    friend class vector<ASTNode>;
+    //Print the arguments in lisp format.
+    friend ostream &LispPrintVec(ostream &os, 
+				 const ASTVec &v, int indentation = 0); 
+
+  private:
+    // FIXME: make this into a reference?
+    ASTInternal * _int_node_ptr;	// The real data.
+
+    // Usual constructor.  
+    ASTNode(ASTInternal *in);
+
+    //Check if it points to a null node
+    bool IsNull () const { return _int_node_ptr == NULL; }
+
+    //Equal iff ASTIntNode pointers are the same.
+    friend bool operator==(const ASTNode node1, const ASTNode node2){
+      return ((size_t) node1._int_node_ptr) == ((size_t) node2._int_node_ptr);
+    }
+    
+    /* FIXME:  Nondeterministic code *** */
+    /** questionable pointer comparison function */
+    friend bool operator<(const ASTNode node1, const ASTNode node2){
+      return ((size_t) node1._int_node_ptr) < ((size_t) node2._int_node_ptr);
+    }
+
+  public:
+    // This is for sorting by expression number (used in Boolean
+    //optimization)
+    friend bool exprless(const ASTNode n1, const ASTNode n2) {
+      Kind k1 = n1.GetKind();
+      Kind k2 = n2.GetKind();
+      
+      if(BVCONST == k1 && BVCONST != k2){
+	return true;
+      }
+      if(BVCONST != k1 && BVCONST == k2){
+	return false;
+      }
+      
+      if(SYMBOL == k1 && SYMBOL != k2) {
+      	return true;
+      }
+      
+      if(SYMBOL != k1 && SYMBOL == k2) {
+      	return false;
+      }
+
+      return (n1.GetNodeNum() < n2.GetNodeNum());
+    }//end of exprless 
+    
+    // Internal lisp-form printer that does not clear _node_print_table
+    ostream &LispPrint1(ostream &os, int indentation) const;
+
+    ostream &LispPrint_indent(ostream &os, int indentation) const;
+
+    // For lisp DAG printing.  Has it been printed already, so we can
+    // just print the node number?
+    bool IsAlreadyPrinted() const;
+    void MarkAlreadyPrinted() const;
+
+  public:
+    // Default constructor.  This gets used when declaring an ASTVec
+    // of a given size, in the hash table, etc.  For faster
+    // refcounting, create a symbol node for NULL.  Give it a big
+    // initial refcount.  Never free it.  also check, for ref-count
+    // overflow?
+    ASTNode() : _int_node_ptr(NULL) { };
+
+    // Copy constructor
+    ASTNode(const ASTNode &n);
+
+    // Destructor
+    ~ASTNode();
+
+    // Assignment (for ref counting)
+    ASTNode& operator=(const ASTNode& n);
+
+    BeevMgr &GetBeevMgr() const;
+
+    // Access node number
+    int GetNodeNum() const;
+
+    // Access kind.  Inlined later because of declaration ordering problems.
+    Kind GetKind() const;
+
+    // access Children
+    const ASTVec &GetChildren() const;
+    
+    // Return the number of child nodes
+    size_t Degree() const{ 
+      return GetChildren().size(); 
+    };    
+
+    // Get indexth childNode.
+    const ASTNode operator[](size_t index) const { 
+      return GetChildren()[index]; 
+    };    
+
+    // Get begin() iterator for child nodes
+    ASTVec::const_iterator begin() const{ 
+      return GetChildren().begin(); 
+    };  
+
+    // Get end() iterator for child nodes
+    ASTVec::const_iterator end() const{ 
+      return GetChildren().end(); 
+    };
+
+    //Get back() element for child nodes
+    const ASTNode back() const{
+      return GetChildren().back();
+    };  
+
+    // Get the name from a symbol (char *).  It's an error if kind != SYMBOL
+    const char * const GetName() const;
+
+    //Get the BVCONST value
+#ifndef NATIVE_C_ARITH
+    const CBV GetBVConst() const;
+#else
+    unsigned long long int GetBVConst() const;
+#endif
+
+    /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
+     *
+     *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
+     *
+     *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+     *
+     *both indexwidth and valuewidth should never be less than 0
+     */
+    unsigned int GetIndexWidth () const;
+
+    // FIXME: This function is dangerous.  Try to eliminate it's use.
+    void SetIndexWidth (unsigned int iw) const;
+
+    unsigned int GetValueWidth () const;
+
+    // FIXME: This function is dangerous.  Try to eliminate it's use.
+    void SetValueWidth (unsigned int vw) const;
+
+    //return the type of the ASTNode
+    //0 iff BOOLEAN
+    //1 iff BITVECTOR
+    //2 iff ARRAY
+
+    /*ASTNode is of type BV <==> ((indexwidth=0)&&(valuewidth>0))
+     *
+     *ASTNode is of type ARRAY <==> ((indexwidth>0)&&(valuewidth>0))
+     *
+     *ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+     *
+     *both indexwidth and valuewidth should never be less than 0
+     */    
+    types GetType(void) const;
+
+    // Hash is pointer value of _int_node_ptr.
+    const size_t Hash() const{ 
+      return (size_t) _int_node_ptr; 
+      //return GetNodeNum(); 
+    }
+
+    // lisp-form printer 
+    ostream& LispPrint(ostream &os, int indentation = 0) const;
+
+    //Presentation Language Printer
+    ostream& PL_Print(ostream &os, int indentation = 0) const;
+
+    void PL_Print1(ostream &os, int indentation = 0, bool b = false) const;
+
+    //Construct let variables for shared subterms
+    void LetizeNode(void) const;
+
+    // Attempt to define something that will work in the gdb
+    friend void lp(ASTNode &node);
+    friend void lpvec(const ASTVec &vec);
+
+    friend ostream &operator<<(ostream &os, const ASTNode &node) { 
+      node.LispPrint(os, 0); 
+      return os; 
+    };
+    
+    // Check whether the ASTNode points to anything.  Undefined nodes
+    // are created by the default constructor.  In binding table (for
+    // lambda args, etc.), undefined nodes are used to represent
+    // deleted entries.
+    bool IsDefined() const { return _int_node_ptr != NULL; }        
+
+    /* Hasher class for STL hash_maps and hash_sets that use ASTNodes
+     * as keys.  Needs to be public so people can define hash tables
+     * (and use ASTNodeMap class)*/
+    class ASTNodeHasher {
+    public:
+      size_t operator() (const ASTNode& n) const{ 
+	return (size_t) n._int_node_ptr; 
+	//return (size_t)n.GetNodeNum();
+      };
+    }; //End of ASTNodeHasher
+  
+    /* Equality for ASTNode hash_set and hash_map. Returns true iff
+     * internal pointers are the same.  Needs to be public so people
+     * can define hash tables (and use ASTNodeSet class)*/
+    class ASTNodeEqual {
+    public:
+      bool operator()(const ASTNode& n1, const ASTNode& n2) const{ 
+	return (n1._int_node_ptr == n2._int_node_ptr); 
+      }
+    }; //End of ASTNodeEqual
+  }; //End of Class ASTNode
+
+  void FatalError(const char * str, const ASTNode& a, int w = 0);
+  void FatalError(const char * str);
+  void SortByExprNum(ASTVec& c);
+  bool exprless(const ASTNode n1, const ASTNode n2);
+  bool isAtomic(Kind k);
+
+  /***************************************************************************/
+  /*  Class ASTInternal:Abstract base class for internal node representation.*/
+  /*                    Requires Kind and ChildNodes so same traversal works */
+  /*                    on all nodes.                                        */
+  /***************************************************************************/
+  class ASTInternal {
+
+    friend class ASTNode;
+
+  protected:    
+
+    // reference count.
+    int _ref_count;
+
+    // Kind.  It's a type tag and the operator.
+    Kind _kind;  
+
+    // The vector of children (*** should this be in ASTInterior? ***)
+    ASTVec _children;
+
+    // Manager object.  Having this backpointer means it's easy to
+    // find the manager when we need it.
+    BeevMgr &_bm;
+
+    //Nodenum is a unique positive integer for the node.  The nodenum
+    //of a node should always be greater than its descendents (which
+    //is easily achieved by incrementing the number each time a new
+    //node is created).
+    int _node_num;
+
+    // Length of bitvector type for array index.  The term is an
+    // array iff this is positive.  Otherwise, the term is a bitvector
+    // or a bit.
+    unsigned int _index_width;
+
+    // Length of bitvector type for scalar value or array element.
+    // If this is one, the term represents a single bit (same as a bitvector
+    // of length 1).  It must be 1 or greater.
+    unsigned int _value_width;
+
+    // Increment refcount.
+#ifndef SMTLIB
+    void IncRef() { ++_ref_count; }
+#else
+    void IncRef() { }
+#endif
+
+    // DecRef is a potentially expensive, because it has to delete 
+    // the node from the unique table, in addition to freeing it.
+    // FIXME:  Consider putting in a backpointer (iterator) to the hash
+    // table entry so it can be deleted without looking it up again.
+    void DecRef();
+
+    virtual const Kind GetKind() const { return _kind; }
+
+    virtual ASTVec const &GetChildren() const { return _children; }
+
+    int GetNodeNum() const { return _node_num; }
+
+    void SetNodeNum(int nn) { _node_num = nn; };
+
+    // Constructor (bm only)
+    ASTInternal(BeevMgr &bm, int nodenum = 0) :
+      _ref_count(0),
+      _kind(UNDEFINED),
+      _bm(bm),
+      _node_num(nodenum),
+      _index_width(0),
+      _value_width(0) { }
+
+    // Constructor (kind only, empty children, int nodenum) 
+    ASTInternal(Kind kind, BeevMgr &bm, int nodenum = 0) : 
+      _ref_count(0),
+      _kind(kind),
+      _bm(bm),
+      _node_num(nodenum),
+      _index_width(0),
+      _value_width(0) { } 
+
+    // Constructor (kind and children).  This copies the contents of
+    // the child nodes.
+    // FIXME: is there a way to avoid repeating these?
+    ASTInternal(Kind kind, const ASTVec &children, BeevMgr &bm, int nodenum = 0) : 
+      _ref_count(0),
+      _kind(kind),
+      _children(children),
+      _bm(bm),
+      _node_num(nodenum),
+      _index_width(0),
+      _value_width(0) { } 
+
+    // Copy constructor.  This copies the contents of the child nodes
+    // array, along with everything else.  Assigning the smart pointer,
+    // ASTNode, does NOT invoke this; This should only be used for 
+    // temporary hash keys before uniquefication.
+    // FIXME:  I don't think children need to be copied.
+    ASTInternal(const ASTInternal &int_node, int nodenum = 0) :
+      _ref_count(0),
+      _kind(int_node._kind),
+      _children(int_node._children),
+      _bm(int_node._bm),
+      _node_num(int_node._node_num), 
+      _index_width(int_node._index_width),
+      _value_width(int_node._value_width) { } 
+
+    // Copying assign operator.  Also copies contents of children.
+    ASTInternal& operator=(const ASTInternal &int_node);
+
+    // Cleanup function for removing from hash table
+    virtual void CleanUp() = 0;
+
+    // Destructor (does nothing, but is declared virtual here.
+    virtual ~ASTInternal();
+
+    // Abstract virtual print function for internal node.
+    virtual void nodeprint(ostream& os) { os << "*"; };
+  }; //End of Class ASTInternal
+
+  // FIXME: Should children be only in interior node type?
+  /***************************************************************************
+    Class ASTInterior: Internal representation of an interior
+       ASTNode.  Generally, these nodes should have at least one
+      child
+  ***************************************************************************/
+  class ASTInterior : public ASTInternal {    
+
+    friend class BeevMgr;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;   
+
+  private:
+
+    // Hasher for ASTInterior pointer nodes
+    class ASTInteriorHasher {
+    public:
+      size_t operator()(const ASTInterior *int_node_ptr) const;
+    };
+
+    // Equality for ASTInterior nodes
+    class ASTInteriorEqual {
+    public:
+      bool operator()(const ASTInterior *int_node_ptr1, 
+		      const ASTInterior *int_node_ptr2) const{
+	return (*int_node_ptr1 == *int_node_ptr2);
+      }
+    };
+
+    // Used in Equality class for hash tables
+    friend bool operator==(const ASTInterior &int_node1, 
+			   const ASTInterior &int_node2){
+      return (int_node1._kind == int_node2._kind) && 
+	(int_node1._children == int_node2._children);
+    }
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    // Returns kinds.  "lispprinter" handles printing of parenthesis
+    // and childnodes.
+    virtual void nodeprint(ostream& os) {
+      os << _kind_names[_kind];
+    }
+    public:
+
+    // FIXME: This should not be public, but has to be because the
+    // ASTInterior hash table insists on it.  I can't seem to make the
+    // private destructor visible to hash_set.  It does not even work
+    // to put "friend class hash_set<ASTInterior, ...>" in here.
+
+    // Basic constructors
+    ASTInterior(Kind kind,  BeevMgr &bm) :
+      ASTInternal(kind, bm) {  }    
+
+    ASTInterior(Kind kind, ASTVec &children, BeevMgr &bm) :
+      ASTInternal(kind, children, bm) {  }    
+
+    //Copy constructor.  This copies the contents of the child nodes
+    //array, along with everything else. Assigning the smart pointer,
+    //ASTNode, does NOT invoke this.
+    ASTInterior(const ASTInterior &int_node) : ASTInternal(int_node) { }
+
+    // Destructor (does nothing, but is declared virtual here.
+    virtual ~ASTInterior();
+
+  }; //End of ASTNodeInterior
+
+
+  /***************************************************************************/
+  /*  Class ASTSymbol:  Class to represent internals of Symbol node.         */
+  /***************************************************************************/
+  class ASTSymbol : public ASTInternal{
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+
+  private:
+    // The name of the symbol
+    const char * const _name;
+    
+    class ASTSymbolHasher{
+    public:
+      size_t operator() (const ASTSymbol *sym_ptr) const{ 
+	hash<char*> h; 
+	return h(sym_ptr->_name); 
+      };
+    };
+
+    // Equality for ASTInternal nodes
+    class ASTSymbolEqual{
+    public:
+      bool operator()(const ASTSymbol *sym_ptr1, const ASTSymbol *sym_ptr2) const{ 
+	return (*sym_ptr1 == *sym_ptr2); 
+      }
+    };
+
+    friend bool operator==(const ASTSymbol &sym1, const ASTSymbol &sym2){
+      return (strcmp(sym1._name, sym2._name) == 0);
+    }
+
+    const char * const GetName() const{return _name;}  
+
+    // Print function for symbol -- return name */
+    virtual void nodeprint(ostream& os) { os << _name;}
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    public:
+
+    // Default constructor
+    ASTSymbol(BeevMgr &bm) : ASTInternal(bm), _name(NULL) { }
+
+    // Constructor.  This does NOT copy its argument.
+    ASTSymbol(const char * const name, BeevMgr &bm) : ASTInternal(SYMBOL, bm), 
+						      _name(name) { }
+    
+    // Destructor (does nothing, but is declared virtual here.
+    virtual ~ASTSymbol();
+    
+    // Copy constructor
+    // FIXME: seems to be calling default constructor for astinternal
+    ASTSymbol(const ASTSymbol &sym) :
+      ASTInternal(sym._kind, sym._children, sym._bm), 
+      _name(sym._name) { } 
+  }; //End of ASTSymbol
+  
+
+  /***************************************************************************/
+  /*  Class ASTBVConst:  Class to represent internals of a bitvectorconst    */
+  /***************************************************************************/
+
+#ifndef NATIVE_C_ARITH
+
+  class ASTBVConst : public ASTInternal {
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+    
+  private:
+    //This is the private copy of a bvconst currently
+    //This should not be changed at any point
+    CBV _bvconst;
+
+    class ASTBVConstHasher{
+    public:
+      size_t operator() (const ASTBVConst * bvc) const {
+        return CONSTANTBV::BitVector_Hash(bvc->_bvconst);
+      };
+    };
+
+    class ASTBVConstEqual{
+    public:
+      bool operator()(const ASTBVConst * bvc1, const ASTBVConst  * bvc2) const { 
+        if( bvc1->_value_width != bvc2->_value_width){
+	  return false;
+	}  
+	return (0==CONSTANTBV::BitVector_Compare(bvc1->_bvconst,bvc2->_bvconst));
+      }
+    };
+    
+    //FIXME Keep an eye on this function
+    ASTBVConst(CBV bv, unsigned int width, BeevMgr &bm) :
+      ASTInternal(BVCONST, bm)
+    {
+      _bvconst = CONSTANTBV::BitVector_Clone(bv);
+      _value_width = width;
+    }
+
+    friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2){
+      if(bvc1._value_width != bvc2._value_width)
+        return false;
+      return (0==CONSTANTBV::BitVector_Compare(bvc1._bvconst,bvc2._bvconst));
+    }
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    // Print function for bvconst -- return _bvconst value in bin format
+    virtual void nodeprint(ostream& os) {
+      unsigned char *res;
+      const char *prefix;
+
+      if (_value_width%4 == 0) {
+        res = CONSTANTBV::BitVector_to_Hex(_bvconst);
+        prefix = "0hex";
+      } else {      
+        res = CONSTANTBV::BitVector_to_Bin(_bvconst);
+        prefix = "0bin";
+      }
+      if (NULL == res) {
+        os << "nodeprint: BVCONST : could not convert to string" << _bvconst;
+        FatalError("");
+      }
+      os << prefix << res;
+      CONSTANTBV::BitVector_Dispose(res);
+    }
+
+    // Copy constructor.     
+    ASTBVConst(const ASTBVConst &sym) : 
+      ASTInternal(sym._kind, sym._children, sym._bm)
+    {
+      _bvconst = CONSTANTBV::BitVector_Clone(sym._bvconst);
+      _value_width = sym._value_width;
+    }
+    
+  public:
+    virtual ~ASTBVConst(){
+       CONSTANTBV::BitVector_Destroy(_bvconst);
+    }
+
+    CBV GetBVConst() const {return _bvconst;}
+  }; //End of ASTBVConst
+
+  //FIXME This function is DEPRICATED
+  //Do not use in the future
+  inline unsigned int GetUnsignedConst(const ASTNode n) {
+    if(32 < n.GetValueWidth())
+      FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");
+        
+    return (unsigned int) *((unsigned int *)n.GetBVConst());
+  }
+#else
+  class ASTBVConst : public ASTInternal {
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+
+  private:
+    // the bitvector contents. bitvector contents will be in two
+    // modes. one mode where all bitvectors are NATIVE and in this
+    // mode we use native unsigned long long int to represent the
+    // 32/64 bitvectors. The other for arbitrary length bitvector
+    // operations.
+    const unsigned long long int _bvconst;
+
+    class ASTBVConstHasher{
+    public:
+      size_t operator() (const ASTBVConst * bvc) const{ 
+	//Thomas Wang's 64 bit Mix Function
+	unsigned long long int key(bvc->_bvconst);
+	key += ~(key << 32);
+	key ^= (key  >> 22);
+	key += ~(key << 13);
+	key ^= (key  >> 8);
+	key += (key  << 3);
+	key ^= (key  >> 15);
+	key += ~(key << 27);
+	key ^= (key  >> 31);
+	
+	size_t return_key = key;
+	return return_key;
+      };
+    };
+
+    class ASTBVConstEqual{
+    public:
+      bool operator()(const ASTBVConst * bvc1, const ASTBVConst  * bvc2) const { 
+	return ((bvc1->_bvconst == bvc2->_bvconst) 
+		&& (bvc1->_value_width == bvc2->_value_width));
+      }
+    };
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+  public:
+    // Default constructor
+    ASTBVConst(const unsigned long long int bv, BeevMgr &bm) : 
+      ASTInternal(BVCONST, bm), _bvconst(bv) { 
+    }
+
+    // Copy constructor. FIXME: figure out how this is supposed to
+    // work.
+    ASTBVConst(const ASTBVConst &sym) : 
+      ASTInternal(sym._kind, sym._children, sym._bm), 
+      _bvconst(sym._bvconst) { 
+      _value_width = sym._value_width;
+    } 
+
+    // Destructor (does nothing, but is declared virtual here)
+    virtual ~ASTBVConst() { } 
+    
+    friend bool operator==(const ASTBVConst &sym1, const ASTBVConst &sym2){
+      return ((sym1._bvconst == sym2._bvconst) && 
+	      (sym1._value_width == sym2._value_width));
+    }
+
+    // Print function for bvconst -- return _bvconst value in binary format
+    virtual void nodeprint(ostream& os) {
+      string s = "0bin";
+      unsigned long long int bitmask = 0x8000000000000000LL;
+      bitmask = bitmask >> (64-_value_width);
+
+      for (; bitmask > 0; bitmask >>= 1)
+	s += (_bvconst & bitmask) ? '1' : '0';	
+      os << s;
+    }
+    
+    unsigned long long int GetBVConst() const  {return _bvconst;}
+  }; //End of ASTBVConst
+
+  //return value of bvconst
+  inline unsigned int GetUnsignedConst(const ASTNode n) {
+    if(32 < n.GetValueWidth())
+      FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");    
+    return (unsigned int)n.GetBVConst();
+  }
+#endif
+/*
+#else
+  // the bitvector contents. bitvector contents will be in two
+  // modes. one mode where all bitvectors are NATIVE and in this mode
+  // we use native unsigned long long int to represent the 32/64
+  // bitvectors. The other for arbitrary length bitvector operations.
+
+  //BVCONST defined for arbitrary length bitvectors
+  class ASTBVConst : public ASTInternal{
+    friend class BeevMgr;
+    friend class ASTNode;
+    friend class ASTNodeHasher;
+    friend class ASTNodeEqual;
+
+  private:
+    const char * const _bvconst;
+
+    class ASTBVConstHasher{
+    public:
+      size_t operator() (const ASTBVConst * bvc) const{ 
+	hash<char*> h;	
+	return h(bvc->_bvconst);
+      };
+    };
+
+    class ASTBVConstEqual{
+    public:
+      bool operator()(const ASTBVConst * bvc1, const ASTBVConst  * bvc2) const { 
+	if(bvc1->_value_width != bvc2->_value_width)
+	  return false;
+	return (0 == strncmp(bvc1->_bvconst,bvc2->_bvconst,bvc1->_value_width));
+      }
+    };
+    
+    ASTBVConst(const char * bv, BeevMgr &bm) : 
+      ASTInternal(BVCONST, bm), _bvconst(bv) { 
+      //_value_width = strlen(bv);
+    }
+
+    friend bool operator==(const ASTBVConst &bvc1, const ASTBVConst &bvc2){
+      if(bvc1._value_width != bvc2._value_width)
+	return false;
+      return (0 == strncmp(bvc1._bvconst,bvc2._bvconst,bvc1._value_width));
+    }
+
+    // Call this when deleting a node that has been stored in the
+    // the unique table
+    virtual void CleanUp();
+
+    // Print function for bvconst -- return _bvconst value in binary format
+    virtual void nodeprint(ostream& os) {
+      if(_value_width%4 == 0) {
+	unsigned int *  iii = CONSTANTBV::BitVector_Create(_value_width,true);
+	CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,(unsigned char*)_bvconst);
+	//error printing
+	if(0 != e) {
+	  os << "nodeprint: BVCONST : wrong hex value: " << BitVector_Error(e);
+	  FatalError("");
+	}
+	unsigned char * ccc = CONSTANTBV::BitVector_to_Hex(iii);
+	os << "0hex" << ccc;
+	CONSTANTBV::BitVector_Destroy(iii);
+      }
+      else {
+	std::string s(_bvconst,_value_width);
+	s = "0bin" + s;
+	os << s;
+      }
+    }
+
+    // Copy constructor.     
+    ASTBVConst(const ASTBVConst &sym) : ASTInternal(sym._kind, sym._children, sym._bm),_bvconst(sym._bvconst) { 
+      //checking if the input is in the correct format
+      for(unsigned int jj=0;jj<sym._value_width;jj++)
+	if(!(sym._bvconst[jj] == '0' || sym._bvconst[jj] == '1')) {
+	  cerr << "Fatal Error: wrong input to ASTBVConst copy constructor:" << sym._bvconst << endl;
+	  FatalError("");
+	}
+      _value_width = sym._value_width;
+    } 
+  public:
+    // Destructor (does nothing, but is declared virtual here)
+    virtual ~ASTBVConst(){}
+
+    const char * const GetBVConst() const {return _bvconst;}
+  }; //End of ASTBVConst
+
+  unsigned int * ConvertToCONSTANTBV(const char * s);
+
+  //return value of bvconst
+  inline unsigned int GetUnsignedConst(const ASTNode n) {
+    if(32 < n.GetValueWidth())
+      FatalError("GetUnsignedConst: cannot convert bvconst of length greater than 32 to unsigned int:");    
+    std::string s(n.GetBVConst(), n.GetValueWidth());
+      unsigned int output = strtoul(s.c_str(),NULL,2);
+      return output;
+  } //end of ASTBVConst class
+#endif
+*/
+  /***************************************************************************
+   * Typedef ASTNodeMap:  This is a hash table from ASTNodes to ASTNodes.
+   * It is very convenient for attributes that are not speed-critical
+   **************************************************************************/
+  // These are generally useful for storing ASTNodes or attributes thereof
+  // Hash table from ASTNodes to ASTNodes
+  typedef hash_map<ASTNode, ASTNode, 
+		   ASTNode::ASTNodeHasher, 
+		   ASTNode::ASTNodeEqual> ASTNodeMap;
+
+  // Function to dump contents of ASTNodeMap
+  ostream &operator<<(ostream &os, const ASTNodeMap &nmap);
+  
+  /***************************************************************************
+   Typedef ASTNodeSet:  This is a hash set of ASTNodes.  Very useful
+   for representing things like "visited nodes"
+  ***************************************************************************/
+  typedef hash_set<ASTNode, 
+		   ASTNode::ASTNodeHasher, 
+		   ASTNode::ASTNodeEqual> ASTNodeSet;
+
+  typedef hash_multiset<ASTNode, 
+			ASTNode::ASTNodeHasher, 
+			ASTNode::ASTNodeEqual> ASTNodeMultiSet;
+
+  //external parser table for declared symbols.
+  //FIXME: move to a more appropriate place
+  extern ASTNodeSet _parser_symbol_table;
+  
+  /***************************************************************************
+    Class LispPrinter:  iomanipulator for printing ASTNode or ASTVec       
+  ***************************************************************************/
+  class LispPrinter {
+
+  public:
+    ASTNode _node;
+
+    // number of spaces to print before first real character of
+    // object.
+    int _indentation;  
+
+    // FIXME: pass ASTNode by reference
+    // Constructor to build the LispPrinter object
+    LispPrinter(ASTNode node, int indentation): _node(node), _indentation(indentation) { }    
+
+    friend ostream &operator<<(ostream &os, const LispPrinter &lp){ 
+      return lp._node.LispPrint(os, lp._indentation); 
+    };
+
+  }; //End of ListPrinter
+  
+  //This is the IO manipulator.  It builds an object of class
+  //"LispPrinter" that has a special overloaded "<<" operator.
+  inline LispPrinter lisp(const ASTNode &node, int indentation = 0){
+    LispPrinter lp(node, indentation);
+    return lp;
+  }
+  
+  /***************************************************************************/
+  /*  Class LispVecPrinter:iomanipulator for printing vector of ASTNodes     */
+  /***************************************************************************/
+  class LispVecPrinter {
+
+  public:
+    const ASTVec * _vec;
+    // number of spaces to print before first real
+    // character of object.    
+    int _indentation;
+    
+    // Constructor to build the LispPrinter object
+    LispVecPrinter(const ASTVec &vec, int indentation){
+      _vec = &vec; _indentation = indentation; 
+    }
+    
+    friend ostream &operator<<(ostream &os, const LispVecPrinter &lvp){
+    LispPrintVec(os, *lvp._vec, lvp._indentation);
+    return os;
+    };
+  }; //End of Class ListVecPrinter
+
+  //iomanipulator. builds an object of class "LisPrinter" that has a
+  //special overloaded "<<" operator.
+  inline LispVecPrinter lisp(const ASTVec &vec, int indentation = 0){
+    LispVecPrinter lvp(vec, indentation);
+    return lvp;
+  }
+
+
+  /*****************************************************************
+   * INLINE METHODS from various classed, declared here because of
+   * dependencies on classes that are declared later.
+   *****************************************************************/
+  // ASTNode accessor function.
+  inline Kind ASTNode::GetKind() const { 
+    //cout << "GetKind: " << _int_node_ptr; 
+    return _int_node_ptr->GetKind(); 
+  }
+
+  // FIXME: should be const ASTVec const?  
+  // Declared here because of same ordering problem as  GetKind.
+  inline const ASTVec &ASTNode::GetChildren() const { 
+    return _int_node_ptr->GetChildren(); 
+  }
+
+  // Access node number
+  inline int ASTNode::GetNodeNum() const { 
+    return _int_node_ptr->_node_num; 
+  }
+
+  inline unsigned int ASTNode::GetIndexWidth () const { 
+    return _int_node_ptr->_index_width; 
+  }
+  
+  inline void ASTNode::SetIndexWidth (unsigned int iw) const { 
+    _int_node_ptr->_index_width = iw;
+  }
+  
+  inline unsigned int ASTNode::GetValueWidth () const { 
+    return _int_node_ptr->_value_width; 
+  }
+  
+  inline void ASTNode::SetValueWidth (unsigned int vw) const {
+    _int_node_ptr->_value_width = vw; 
+  }
+
+  //return the type of the ASTNode: 0 iff BOOLEAN; 1 iff BITVECTOR; 2
+  //iff ARRAY; 3 iff UNKNOWN;
+  inline types ASTNode::GetType() const {
+    if((GetIndexWidth() == 0) && (GetValueWidth() == 0)) //BOOLEAN
+      return BOOLEAN_TYPE;
+    if((GetIndexWidth() == 0) && (GetValueWidth() > 0))  //BITVECTOR
+      return BITVECTOR_TYPE;
+    if((GetIndexWidth() > 0) && (GetValueWidth() > 0)) //ARRAY
+      return ARRAY_TYPE;
+    return UNKNOWN_TYPE; 
+  }
+
+  // Constructor; creates a new pointer, increments refcount of
+  // pointed-to object.
+#ifndef SMTLIB
+  inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in) { 
+    if (in) in->IncRef(); 
+  }
+#else
+  inline ASTNode::ASTNode(ASTInternal *in) : _int_node_ptr(in) { };
+#endif
+
+  // Assignment.  Increment refcount of new value, decrement refcount
+  // of old value and destroy if this was the last pointer.  FIXME:
+  // accelerate this by creating an intnode with a ref counter instead
+  // of pointing to NULL.  Need a special check in CleanUp to make
+  // sure the null node never gets freed.
+
+#ifndef SMTLIB
+  inline ASTNode& ASTNode::operator=(const ASTNode& n) {
+    if (n._int_node_ptr) {
+      n._int_node_ptr->IncRef();
+    }
+    if (_int_node_ptr) {
+      _int_node_ptr->DecRef();
+    }
+    _int_node_ptr = n._int_node_ptr;
+    return *this;
+  }
+#else
+  inline ASTNode& ASTNode::operator=(const ASTNode& n) {
+    _int_node_ptr = n._int_node_ptr;
+    return *this;
+  }
+#endif
+
+#ifndef SMTLIB
+  inline void ASTInternal::DecRef()
+  {
+    if (--_ref_count == 0) {
+      // Delete node from unique table and kill it.
+      CleanUp();
+    }
+  }
+
+  // Destructor
+  inline ASTNode::~ASTNode()
+  {
+    if (_int_node_ptr) {
+      _int_node_ptr->DecRef();
+    }
+  };
+#else
+  // No refcounting
+  inline void ASTInternal::DecRef()
+  {
+  }
+
+  // Destructor
+  inline ASTNode::~ASTNode()
+  {
+  };
+#endif
+
+  inline BeevMgr& ASTNode::GetBeevMgr() const { return _int_node_ptr->_bm; }
+
+  /***************************************************************************
+   * Class BeevMgr.  This holds all "global" variables for the system, such as
+   * unique tables for the various kinds of nodes.
+   ***************************************************************************/
+  class BeevMgr {
+    friend class ASTNode;	// ASTNode modifies AlreadyPrintedSet
+				// in BeevMgr
+    friend class ASTInterior;
+    friend class ASTBVConst;
+    friend class ASTSymbol;
+
+    // FIXME: The values appear to be the same regardless of the value of SMTLIB
+    // initial hash table sizes, to save time on resizing.
+#ifdef SMTLIB
+    static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
+    static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
+
+    static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
+    static const int INITIAL_SOLVER_MAP_SIZE = 100;
+    static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
+    static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
+#else
+    // these are the STL defaults
+    static const int INITIAL_INTERIOR_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_SYMBOL_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BVCONST_UNIQUE_TABLE_SIZE = 100;
+    static const int INITIAL_BBTERM_MEMO_TABLE_SIZE = 100;
+    static const int INITIAL_BBFORM_MEMO_TABLE_SIZE = 100;
+
+    static const int INITIAL_SIMPLIFY_MAP_SIZE = 100;
+    static const int INITIAL_SOLVER_MAP_SIZE = 100;
+    static const int INITIAL_ARRAYREAD_SYMBOL_SIZE = 100;
+    static const int INITIAL_INTRODUCED_SYMBOLS_SIZE = 100;
+#endif
+
+  private:
+    // Typedef for unique Interior node table. 
+    typedef hash_set<ASTInterior *, 
+		     ASTInterior::ASTInteriorHasher, 
+		     ASTInterior::ASTInteriorEqual> ASTInteriorSet;
+
+    // Typedef for unique Symbol node (leaf) table.
+    typedef hash_set<ASTSymbol *, 
+		     ASTSymbol::ASTSymbolHasher, 
+		     ASTSymbol::ASTSymbolEqual> ASTSymbolSet;
+
+    // Unique tables to share nodes whenever possible.
+    ASTInteriorSet _interior_unique_table;
+    //The _symbol_unique_table is also the symbol table to be used
+    //during parsing/semantic analysis
+    ASTSymbolSet _symbol_unique_table;
+    
+    //Typedef for unique BVConst node (leaf) table.
+    typedef hash_set<ASTBVConst *, 
+		     ASTBVConst::ASTBVConstHasher,
+		     ASTBVConst::ASTBVConstEqual> ASTBVConstSet;
+
+    //table to uniquefy bvconst
+    ASTBVConstSet _bvconst_unique_table;
+
+    // type of memo table.
+    typedef hash_map<ASTNode, ASTVec,
+		     ASTNode::ASTNodeHasher, 
+		     ASTNode::ASTNodeEqual> ASTNodeToVecMap;
+
+    typedef hash_map<ASTNode,ASTNodeSet,
+		     ASTNode::ASTNodeHasher,
+		     ASTNode::ASTNodeEqual> ASTNodeToSetMap;
+    
+    // Memo table for bit blasted terms.  If a node has already been
+    // bitblasted, it is mapped to a vector of Boolean formulas for
+    // the bits.
+    
+    //OLD: ASTNodeToVecMap BBTermMemo;
+    ASTNodeMap BBTermMemo;
+    
+    // Memo table for bit blasted formulas.  If a node has already
+    // been bitblasted, it is mapped to a node representing the
+    // bitblasted equivalent
+    ASTNodeMap BBFormMemo;
+    
+    //public:
+    // Get vector of Boolean formulas for sum of two
+    // vectors of Boolean formulas
+    void BBPlus2(ASTVec& sum, const ASTVec& y, ASTNode cin);
+    // Increment
+    ASTVec BBInc(ASTVec& x);
+    // Add one bit to a vector of bits.
+    ASTVec BBAddOneBit(ASTVec& x, ASTNode cin);
+    // Bitwise complement
+    ASTVec BBNeg(const ASTVec& x);
+    // Unary minus
+    ASTVec BBUminus(const ASTVec& x);
+    // Multiply.
+    ASTVec BBMult(const ASTVec& x, const ASTVec& y);
+    // AND each bit of vector y with single bit b and return the result.
+    // (used in BBMult)
+    ASTVec BBAndBit(const ASTVec& y, ASTNode b);
+    // Returns ASTVec for result - y.  This destroys "result".
+    void BBSub(ASTVec& result, const ASTVec& y);
+    // build ITE's (ITE cond then[i] else[i]) for each i.
+    ASTVec BBITE(const ASTNode& cond, 
+		 const ASTVec& thn, const ASTVec& els);
+    // Build a vector of zeros.
+    ASTVec BBfill(unsigned int width, ASTNode fillval);
+    // build an EQ formula
+    ASTNode BBEQ(const ASTVec& left, const ASTVec& right);
+
+    // This implements a variant of binary long division.
+    // q and r are "out" parameters.  rwidth puts a bound on the
+    // recursion depth.   Unsigned only, for now.
+    void BBDivMod(const ASTVec &y,
+		  const ASTVec &x,
+		  ASTVec &q,
+		  ASTVec &r,
+		  unsigned int rwidth);
+    
+    // Return formula for majority function of three formulas.
+    ASTNode Majority(const ASTNode& a, const ASTNode& b, const ASTNode& c);
+
+    // Internal bit blasting routines.
+    ASTNode BBBVLE(const ASTVec& x, const ASTVec& y, bool is_signed);
+
+    // Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc. 
+    ASTNode BBcompare(const ASTNode& form);
+
+    // Left and right shift one.  Writes into x.
+    void BBLShift(ASTVec& x);
+    void BBRShift(ASTVec& x);
+
+  public:
+    // Simplifying create functions
+    ASTNode CreateSimpForm(Kind kind, ASTVec &children);
+    ASTNode CreateSimpForm(Kind kind, const ASTNode& child0);
+    ASTNode CreateSimpForm(Kind kind,
+				    const ASTNode& child0,
+				    const ASTNode& child1);
+    ASTNode CreateSimpForm(Kind kind,
+				    const ASTNode& child0,
+				    const ASTNode& child1,
+				    const ASTNode& child2);
+
+    ASTNode CreateSimpNot(const ASTNode& form);
+
+    // These are for internal use only.
+    // FIXME: Find a way to make this local to SimpBool, so they're
+    // not in AST.h
+    ASTNode CreateSimpXor(const ASTNode& form1,
+			  const ASTNode& form2);
+    ASTNode CreateSimpXor(ASTVec &children);
+    ASTNode CreateSimpAndOr(bool isAnd,
+				     const ASTNode& form1,
+				     const ASTNode& form2);
+    ASTNode CreateSimpAndOr(bool IsAnd, ASTVec &children);
+    ASTNode CreateSimpFormITE(const ASTNode& child0,
+				       const ASTNode& child1,
+				       const ASTNode& child2);
+    
+
+    // Declarations of BitBlaster functions (BitBlast.cpp)
+  public:
+    // Adds or removes a NOT as necessary to negate a literal.
+    ASTNode Negate(const ASTNode& form);
+
+    // Bit blast a bitvector term.  The term must have a kind for a
+    // bitvector term.  Result is a ref to a vector of formula nodes
+    // representing the boolean formula.
+    const ASTNode BBTerm(const ASTNode& term);
+
+    const ASTNode BBForm(const ASTNode& formula);
+
+    // Declarations of CNF conversion (ToCNF.cpp)
+  public:
+    // ToCNF converts a bit-blasted Boolean formula to Conjunctive
+    // 	Normal Form, suitable for many SAT solvers.  Our CNF representation
+    // 	is an STL vector of STL vectors, for independence from any particular
+    // 	SAT solver's representation.  There needs to be a separate driver to
+    // 	convert our clauselist to the representation used by the SAT solver.    
+    // 	Currently, there is only one such solver and its driver is "ToSAT"
+    
+    // Datatype for clauses
+    typedef ASTVec * ClausePtr;
+    
+    // Datatype for Clauselists
+    typedef vector<ClausePtr> ClauseList;
+
+    // Convert a Boolean formula to an equisatisfiable CNF formula.
+    ClauseList *ToCNF(const ASTNode& form);
+
+    // Print function for debugging
+    void PrintClauseList(ostream& os, ClauseList& cll); 
+
+    // Free the clause list and all its clauses.
+    void DeleteClauseList(BeevMgr::ClauseList *cllp);
+
+    // Map from formulas to representative literals, for debugging.
+    ASTNodeMap RepLitMap;
+
+  private:
+    // Global for assigning new node numbers.
+    int _max_node_num;
+    
+    const ASTNode ASTFalse, ASTTrue, ASTUndefined;
+    
+    // I just did this so I could put it in as a fake return value in
+    // methods that return a ASTNode &, to make -Wall shut up.
+    ASTNode dummy_node;
+
+    //BeevMgr Constructor, Destructor and other misc. functions
+  public:
+
+    int NewNodeNum() { _max_node_num += 2; return _max_node_num; } 
+    
+    // Table for DAG printing.
+    ASTNodeSet AlreadyPrintedSet;
+
+    //Tables for Presentation language printing
+
+    //Nodes seen so far
+    ASTNodeSet PLPrintNodeSet;
+
+    //Map from ASTNodes to LetVars
+    ASTNodeMap NodeLetVarMap;
+    
+    //This is a vector which stores the Node to LetVars pairs. It
+    //allows for sorted printing, as opposed to NodeLetVarMap
+    std::vector<pair<ASTNode,ASTNode> > NodeLetVarVec;
+
+    //a partial Map from ASTNodes to LetVars. Needed in order to
+    //correctly print shared subterms inside the LET itself
+    ASTNodeMap NodeLetVarMap1;
+
+    //functions to lookup nodes from the memo tables. these should be
+    //private.
+  private:
+    //Destructively appends back_child nodes to front_child nodes.
+    //If back_child nodes is NULL, no appending is done.  back_child
+    //nodes are not modified.  Then it returns the hashed copy of the
+    //node, which is created if necessary.
+    ASTInterior *CreateInteriorNode(Kind kind,
+				    ASTInterior *new_node,
+				    // this is destructively modified.
+				    const ASTVec & back_children = _empty_ASTVec);
+
+    // Create unique ASTInterior node.
+    ASTInterior *LookupOrCreateInterior(ASTInterior *n);
+
+    // Create unique ASTSymbol node. 
+    ASTSymbol *LookupOrCreateSymbol(ASTSymbol& s);
+    
+    // Called whenever we want to make sure that the Symbol is
+    // declared during semantic analysis
+    bool LookupSymbol(ASTSymbol& s);
+      
+    // Called by ASTNode constructors to uniqueify ASTBVConst
+    ASTBVConst *LookupOrCreateBVConst(ASTBVConst& s);
+
+    //Public functions for CreateNodes and Createterms
+  public:
+    // Create and return an ASTNode for a symbol
+    ASTNode CreateSymbol(const char * const name);
+
+    // Create and return an ASTNode for a symbol
+    // Width is number of bits.
+    ASTNode CreateBVConst(unsigned int width, unsigned long long int bvconst);
+    ASTNode CreateZeroConst(unsigned int width);
+    ASTNode CreateOneConst(unsigned int width);
+    ASTNode CreateTwoConst(unsigned int width);
+    ASTNode CreateMaxConst(unsigned int width);
+
+    // Create and return an ASTNode for a symbol
+    // Optional base was a problem because 0 could be an int or char *,
+    // so CreateBVConst was ambiguous.
+    ASTNode CreateBVConst(const char *strval, int base);
+
+    //FIXME This is a dangerous function 
+    ASTNode CreateBVConst(CBV bv, unsigned width);
+
+    // Create and return an interior ASTNode
+    ASTNode CreateNode(Kind kind, const ASTVec &children = _empty_ASTVec);
+
+    ASTNode CreateNode(Kind kind,
+		       const ASTNode& child0,
+		       const ASTVec &children = _empty_ASTVec);
+
+    ASTNode CreateNode(Kind kind,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTVec &children = _empty_ASTVec);    
+
+    ASTNode CreateNode(Kind kind,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTNode& child2,
+		       const ASTVec &children = _empty_ASTVec);
+
+    // Create and return an ASTNode for a term
+    inline ASTNode CreateTerm(Kind kind, 
+		       unsigned int width, 
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, children);
+      n.SetValueWidth(width);
+
+      //by default we assume that the term is a Bitvector. If
+      //necessary the indexwidth can be changed later
+      n.SetIndexWidth(0);
+      return n;
+    }
+
+    inline ASTNode CreateTerm(Kind kind,
+		       unsigned int width,
+		       const ASTNode& child0,
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, child0, children);
+      n.SetValueWidth(width);
+      return n;
+    }
+     
+    inline ASTNode CreateTerm(Kind kind,
+		       unsigned int width,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, child0, child1, children);
+      n.SetValueWidth(width);
+      return n;
+    }
+
+    inline ASTNode CreateTerm(Kind kind,
+		       unsigned int width,
+		       const ASTNode& child0,
+		       const ASTNode& child1,
+		       const ASTNode& child2,
+		       const ASTVec &children = _empty_ASTVec) {
+      if(!is_Term_kind(kind))
+	FatalError("CreateTerm:  Illegal kind to CreateTerm:",ASTUndefined, kind);
+      ASTNode n = CreateNode(kind, child0, child1, child2, children);
+      n.SetValueWidth(width);
+      return n;
+    }
+
+    ASTNode SimplifyFormula_NoRemoveWrites(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyFormula_TopLevel(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyTerm_TopLevel(const ASTNode& b);
+    ASTNode SimplifyTerm(const ASTNode& a);
+    void CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output);    
+  private:
+    //memo table for simplifcation
+    ASTNodeMap SimplifyMap;
+    ASTNodeMap SimplifyNegMap;
+    ASTNodeMap SolverMap;
+    ASTNodeSet AlwaysTrueFormMap;
+    ASTNodeMap MultInverseMap;
+
+  public:
+    ASTNode SimplifyAtomicFormula(const ASTNode& a, bool pushNeg);
+    ASTNode CreateSimplifiedEQ(const ASTNode& t1, const ASTNode& t2);
+    ASTNode ITEOpt_InEqs(const ASTNode& in1);
+    ASTNode CreateSimplifiedTermITE(const ASTNode& t1, const ASTNode& t2, const ASTNode& t3);
+    ASTNode CreateSimplifiedINEQ(Kind k, const ASTNode& a0, const ASTNode& a1, bool pushNeg);
+    ASTNode SimplifyNotFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyAndOrFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyXorFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyNandFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyNorFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyImpliesFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyIffFormula(const ASTNode& a, bool pushNeg);
+    ASTNode SimplifyIteFormula(const ASTNode& a, bool pushNeg);
+    ASTNode FlattenOneLevel(const ASTNode& a);
+    ASTNode FlattenAndOr(const ASTNode& a);
+    ASTNode CombineLikeTerms(const ASTNode& a);
+    ASTNode LhsMinusRhs(const ASTNode& eq);
+    ASTNode DistributeMultOverPlus(const ASTNode& a, 
+				   bool startdistribution=false);
+    ASTNode ConvertBVSXToITE(const ASTNode& a);
+    //checks if the input constant is odd or not
+    bool BVConstIsOdd(const ASTNode& c);
+    //computes the multiplicatve inverse of the input
+    ASTNode MultiplicativeInverse(const ASTNode& c);
+ 
+    void ClearAllTables(void);
+    void ClearAllCaches(void);
+    int  BeforeSAT_ResultCheck(const ASTNode& q);
+    int  CallSAT_ResultCheck(MINISAT::Solver& newS, 
+			     const ASTNode& q, const ASTNode& orig_input);   
+    int  SATBased_ArrayReadRefinement(MINISAT::Solver& newS, 
+				      const ASTNode& q, const ASTNode& orig_input);
+    int SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input);
+    //creates array write axiom only for the input term or formula, if
+    //necessary. If there are no axioms to produce then it simply
+    //generates TRUE
+    ASTNode Create_ArrayWriteAxioms(const ASTNode& array_readoverwrite_term, const ASTNode& array_newname);
+    ASTVec ArrayWrite_RemainingAxioms;
+    //variable indicates that counterexample will now be checked by
+    //the counterexample checker, and hence simplifyterm must switch
+    //off certain optimizations. In particular, array write
+    //optimizations
+    bool start_abstracting;
+    bool Begin_RemoveWrites;
+    bool SimplifyWrites_InPlace_Flag;
+
+    void CopySolverMap_To_CounterExample(void);
+    //int LinearSearch(const ASTNode& orig_input);    
+    //Datastructures and functions needed for counterexample
+    //generation, and interface with MINISAT
+  private:
+    /* MAP: This is a map from ASTNodes to MINISAT::Vars. 
+     *
+     * The map is populated while ASTclauses are read from the AST
+     * ClauseList returned by CNF converter. For every new boolean
+     * variable in ASTClause a new MINISAT::Var is created (these vars
+     * typedefs for ints)
+     */
+    typedef hash_map<ASTNode, MINISAT::Var, 
+		     ASTNode::ASTNodeHasher, 
+		     ASTNode::ASTNodeEqual> ASTtoSATMap;        
+    ASTtoSATMap _ASTNode_to_SATVar;
+
+  public:  
+    //converts the clause to SAT and calls SAT solver
+    bool toSATandSolve(MINISAT::Solver& S, ClauseList& cll);
+
+    ///print SAT solver statistics
+    void PrintStats(MINISAT::SolverStats& stats);
+
+    //accepts query and returns the answer. if query is valid, return
+    //true, else return false. Automatically constructs counterexample
+    //for invalid queries, and prints them upon request.
+    int TopLevelSAT(const ASTNode& query, const ASTNode& asserts);
+
+    // Debugging function to find problems in BitBlast and ToCNF.
+    // See body in ToSAT.cpp for more explanation.
+    ASTNode CheckBBandCNF(MINISAT::Solver& newS, ASTNode form);
+
+    // Internal recursive body of above.
+    ASTNode CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form);
+
+    // Helper function for CheckBBandCNF
+    ASTNode SymbolTruthValue(MINISAT::Solver &newS, ASTNode form); 
+
+    //looksup a MINISAT var from the minisat-var memo-table. if none
+    //exists, then creates one.
+    const MINISAT::Var LookupOrCreateSATVar(MINISAT::Solver& S, const ASTNode& n);
+
+    // Memo table for CheckBBandCNF debugging function
+    ASTNodeMap CheckBBandCNFMemo;
+
+
+    //Data structures for Array Read Transformations
+  private:
+    /* MAP: This is a map from Array Names to list of array-read
+     * indices in the input. This map is used by the TransformArray()
+     * function
+     *
+     * This map is useful in converting array reads into nested ITE
+     * constructs. Suppose there are two array reads in the input
+     * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
+     * symbolic constant, say v1, and Read(A,j) is replaced with the
+     * following ITE:
+     *
+     * ITE(i=j,v1,v2)
+     */
+    //CAUTION: I tried using a set instead of vector for
+    //readindicies. for some odd reason the performance went down
+    //considerably. this is totally inexplicable.
+    ASTNodeToVecMap _arrayname_readindices;
+        
+    /* MAP: This is a map from Array Names to nested ITE constructs,
+     * which are built as described below. This map is used by the
+     * TransformArray() function
+     *
+     * This map is useful in converting array reads into nested ITE
+     * constructs. Suppose there are two array reads in the input
+     * Read(A,i) and Read(A,j). Then Read(A,i) is replaced with a
+     * symbolic constant, say v1, and Read(A,j) is replaced with the
+     * following ITE:
+     *
+     * ITE(i=j,v1,v2)
+     */
+    ASTNodeMap _arrayread_ite;
+
+    /*MAP: This is a map from array-reads to symbolic constants. This
+     *map is used by the TransformArray()
+     */
+    ASTNodeMap _arrayread_symbol;
+
+    ASTNodeSet _introduced_symbols;
+
+    /*Memoization map for TransformFormula/TransformTerm/TransformArray function
+     */
+    ASTNodeMap TransformMap;
+    
+    //count to keep track of new symbolic constants introduced
+    //corresponding to Array Reads
+    unsigned int _symbol_count;
+
+    //Formula/Term Transformers. Let Expr Manager, Type Checker
+  public:
+    //Functions that Transform ASTNodes
+    ASTNode TransformFormula(const ASTNode& query);
+    ASTNode TransformTerm(const ASTNode& term);
+    ASTNode TransformArray(const ASTNode& term);
+    ASTNode TranslateSignedDivMod(const ASTNode& term);
+
+    //LET Management
+  private:
+    // MAP: This map is from bound IDs that occur in LETs to
+    // expression. The map is useful in checking replacing the IDs
+    // with the corresponding expressions.
+    ASTNodeMap _letid_expr_map;
+  public:
+
+    ASTNode ResolveID(const ASTNode& var);
+
+    //Functions that are used to manage LET expressions
+    void LetExprMgr(const ASTNode& var, const ASTNode& letExpr);
+
+    //Delete Letid Map
+    void CleanupLetIDMap(void);
+
+    //Allocate LetID map
+    void InitializeLetIDMap(void);
+
+    //Substitute Let-vars with LetExprs
+    ASTNode SubstituteLetExpr(ASTNode inExpr);
+
+    /* MAP: This is a map from MINISAT::Vars to ASTNodes
+     *
+     * This is a reverse map, useful in constructing
+     * counterexamples. MINISAT returns a model in terms of MINISAT
+     * Vars, and this map helps us convert it to a model over ASTNode
+     * variables.
+     */    
+    vector<ASTNode> _SATVar_to_AST;
+
+  private:        
+    /* MAP: This is a map from ASTNodes to vectors of bits
+     *
+     * This map is used in constructing and printing
+     * counterexamples. MINISAT returns values for each bit (a
+     * BVGETBIT Node), and this maps allows us to assemble the bits
+     * into bitvectors.
+     */    
+    typedef hash_map<ASTNode, hash_map<unsigned int, bool> *, 
+		     ASTNode::ASTNodeHasher, 
+		     ASTNode::ASTNodeEqual> ASTtoBitvectorMap;        
+    ASTtoBitvectorMap _ASTNode_to_Bitvector;
+
+    //Data structure that holds the counter-model
+    ASTNodeMap CounterExampleMap;
+
+    //Checks if the counter_example is ok. In order for the
+    //counter_example to be ok, Every assert must evaluate to true 
+    //w.r.t couner_example and the query must evaluate to
+    //false. Otherwise the counter_example is bogus.
+    void CheckCounterExample(bool t);    
+
+    //Converts a vector of bools to a BVConst
+    ASTNode BoolVectoBVConst(hash_map<unsigned,bool> * w, unsigned int l);
+
+    //accepts a term and turns it into a constant-term w.r.t counter_example 
+    ASTNode TermToConstTermUsingModel(const ASTNode& term, bool ArrayReadFlag = true);
+    ASTNode Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool ArrayReadFlag = true);
+    //Computes the truth value of a formula w.r.t counter_example
+    ASTNode ComputeFormulaUsingModel(const ASTNode& form);
+
+    //Replaces WRITE(Arr,i,val) with ITE(j=i, val, READ(Arr,j))
+    ASTNode RemoveWrites_TopLevel(const ASTNode& term);
+    ASTNode RemoveWrites(const ASTNode& term);
+    ASTNode SimplifyWrites_InPlace(const ASTNode& term);
+    ASTNode ReadOverWrite_To_ITE(const ASTNode& term);
+
+    ASTNode NewArrayVar(unsigned int index, unsigned int value);
+    ASTNode NewVar(unsigned int valuewidth);
+    //For ArrayWrite Abstraction: map from read-over-write term to
+    //newname.
+    ASTNodeMap ReadOverWrite_NewName_Map;
+    //For ArrayWrite Refinement: Map new arraynames to Read-Over-Write
+    //terms
+    ASTNodeMap NewName_ReadOverWrite_Map;
+    
+  public:
+    //print the STP solver output
+    void PrintOutput(bool true_iff_valid);
+
+    //Converts MINISAT counterexample into an AST memotable (i.e. the
+    //function populates the datastructure CounterExampleMap)
+    void ConstructCounterExample(MINISAT::Solver& S);
+
+    //Prints the counterexample to stdout
+    void PrintCounterExample(bool t,std::ostream& os=cout);
+
+    //Prints the counterexample to stdout
+    void PrintCounterExample_InOrder(bool t);
+
+    //queries the counterexample, and returns the value corresponding
+    //to e
+    ASTNode GetCounterExample(bool t, const ASTNode& e);
+
+    int CounterExampleSize(void) const {return CounterExampleMap.size();}
+
+    //FIXME: This is bloody dangerous function. Hack attack to take
+    //care of requests from users who want to store complete
+    //counter-examples in their own data structures.
+    ASTNodeMap GetCompleteCounterExample() {return CounterExampleMap;}
+
+    // prints MINISAT assigment one bit at a time, for debugging.
+    void PrintSATModel(MINISAT::Solver& S);
+
+    //accepts constant input and normalizes it. 
+    ASTNode BVConstEvaluator(const ASTNode& t);
+
+    //FUNCTION TypeChecker: Assumes that the immediate Children of the
+    //input ASTNode have been typechecked. This function is suitable
+    //in scenarios like where you are building the ASTNode Tree, and
+    //you typecheck as you go along. It is not suitable as a general
+    //typechecker
+    void BVTypeCheck(const ASTNode& n);
+    
+  private:
+    //stack of Logical Context. each entry in the stack is a logical
+    //context. A logical context is a vector of assertions. The
+    //logical context is represented by a ptr to a vector of
+    //assertions in that logical context. Logical contexts are created
+    //by PUSH/POP
+    std::vector<ASTVec *>  _asserts;
+    //The query for the current logical context.
+    ASTNode _current_query;
+
+    //this flag, when true, indicates that counterexample is being
+    //checked by the counterexample checker
+    bool counterexample_checking_during_refinement;
+
+    //this flag indicates as to whether the input has been determined to
+    //be valid or not by this tool
+    bool ValidFlag;
+
+    //this flag, when true, indicates that a BVDIV divide by zero
+    //exception occured. However, the program must not exit with a
+    //fatalerror. Instead, it should evaluate the whole formula (which
+    //contains the BVDIV term) to be FALSE.
+    bool bvdiv_exception_occured;
+
+  public:
+    //set of functions that manipulate Logical Contexts.
+    //
+    //add an assertion to the current logical context
+    void AddAssert(const ASTNode& assert);
+    void Push(void);
+    void Pop(void);
+    void AddQuery(const ASTNode& q);    
+    const ASTNode PopQuery();
+    const ASTNode GetQuery();
+    const ASTVec GetAsserts(void);
+
+    //reports node size.  Second arg is "clearstatinfo", whatever that is.
+    unsigned int NodeSize(const ASTNode& a, bool t = false);
+
+  private:
+    //This memo map is used by the ComputeFormulaUsingModel()
+    ASTNodeMap ComputeFormulaMap;
+    //Map for statiscal purposes
+    ASTNodeSet StatInfoSet;
+
+
+    ASTNodeMap TermsAlreadySeenMap;
+    ASTNode CreateSubstitutionMap(const ASTNode& a);
+  public:
+    //prints statistics for the ASTNode. can add a prefix string c
+    void ASTNodeStats(const char * c, const ASTNode& a);
+
+    //substitution
+    bool CheckSubstitutionMap(const ASTNode& a, ASTNode& output);  
+    bool CheckSubstitutionMap(const ASTNode& a);
+    bool UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1);
+    //if (a > b) in the termorder, then return 1
+    //elseif (a < b) in the termorder, then return -1
+    //else return 0
+    int TermOrder(const ASTNode& a, const ASTNode& b);
+    //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
+    //and index is a BVCONST
+    void FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1);
+    bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
+
+    //functions for checking and updating simplifcation map
+    bool CheckSimplifyMap(const ASTNode& key, ASTNode& output, bool pushNeg);
+    void UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg);
+    bool CheckAlwaysTrueFormMap(const ASTNode& key);
+    void UpdateAlwaysTrueFormMap(const ASTNode& val);
+    bool CheckMultInverseMap(const ASTNode& key, ASTNode& output);
+    void UpdateMultInverseMap(const ASTNode& key, const ASTNode& value);
+
+    //Map for solved variables
+    bool CheckSolverMap(const ASTNode& a, ASTNode& output);
+    bool CheckSolverMap(const ASTNode& a);
+    bool UpdateSolverMap(const ASTNode& e0, const ASTNode& e1);
+  public:
+    //FIXME: HACK_ATTACK. this vector was hacked into the code to
+    //support a special request by Dawson' group. They want the
+    //counterexample to be printed in the order of variables declared.
+    //TO BE COMMENTED LATER (say by 1st week of march,2006)
+    ASTVec _special_print_set;
+
+    //prints the initial activity levels of variables
+    void PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS);
+
+    //this function biases the activity levels of MINISAT variables.
+    void ChangeActivityLevels_Of_SATVars(MINISAT::Solver& n);
+
+    // Constructor
+    BeevMgr() : _interior_unique_table(INITIAL_INTERIOR_UNIQUE_TABLE_SIZE),
+		_symbol_unique_table(INITIAL_SYMBOL_UNIQUE_TABLE_SIZE),
+		_bvconst_unique_table(INITIAL_BVCONST_UNIQUE_TABLE_SIZE),
+		BBTermMemo(INITIAL_BBTERM_MEMO_TABLE_SIZE),
+		BBFormMemo(INITIAL_BBFORM_MEMO_TABLE_SIZE),
+		_max_node_num(0),
+		ASTFalse(CreateNode(FALSE)),
+		ASTTrue(CreateNode(TRUE)),
+		ASTUndefined(CreateNode(UNDEFINED)),
+		SimplifyMap(INITIAL_SIMPLIFY_MAP_SIZE),
+		SimplifyNegMap(INITIAL_SIMPLIFY_MAP_SIZE),
+		SolverMap(INITIAL_SOLVER_MAP_SIZE),
+		_arrayread_symbol(INITIAL_ARRAYREAD_SYMBOL_SIZE),
+		_introduced_symbols(INITIAL_INTRODUCED_SYMBOLS_SIZE),
+		_symbol_count(0) { 
+      _current_query = ASTUndefined;
+      ValidFlag = false;
+      bvdiv_exception_occured = false;
+      counterexample_checking_during_refinement = false;
+      start_abstracting = false;
+      Begin_RemoveWrites = false;
+      SimplifyWrites_InPlace_Flag = false;
+    };
+    
+    //destructor
+    ~BeevMgr();
+  }; //End of Class BeevMgr
+
+
+  class CompleteCounterExample {
+    ASTNodeMap counterexample;
+    BeevMgr * bv;
+  public:
+    CompleteCounterExample(ASTNodeMap a, BeevMgr* beev) : counterexample(a), bv(beev){} 
+    ASTNode GetCounterExample(ASTNode e) {
+      if(BOOLEAN_TYPE == e.GetType() && SYMBOL != e.GetKind()) {
+	FatalError("You must input a term or propositional variables\n",e);
+      }
+      if(counterexample.find(e) != counterexample.end()) {
+	return counterexample[e];
+      }
+      else {
+	if(SYMBOL == e.GetKind() && BOOLEAN_TYPE == e.GetType()) {
+	  return bv->CreateNode(BEEV::FALSE);
+	}
+
+	if(SYMBOL == e.GetKind()) {
+	  ASTNode z = bv->CreateZeroConst(e.GetValueWidth());
+	  return z;
+	}
+
+	return e;	  
+      }
+    }
+  };
+
+}; // end namespace BEEV
+#endif
diff --git a/stp/AST/ASTKind.kinds b/stp/AST/ASTKind.kinds
new file mode 100644
index 00000000..03112eb8
--- /dev/null
+++ b/stp/AST/ASTKind.kinds
@@ -0,0 +1,71 @@
+#Please refer LICENSE FILE in the home directory for licensing information
+# name minkids maxkids cat1 cat2 ...
+Categories:	Term	Form
+
+# Leaf nodes.
+UNDEFINED	0	0
+SYMBOL		0	0	Term	Form 
+
+# These always produce terms
+BVCONST		0	0	Term
+BVNEG		1	1	Term
+BVCONCAT	2	-	Term
+BVOR		1	-	Term
+BVAND		1	-	Term
+BVXOR		1	-	Term
+BVNAND		1	-	Term
+BVNOR		1	-	Term
+BVXNOR		1	-	Term
+BVEXTRACT	3	3	Term
+BVLEFTSHIFT	3	3	Term
+BVRIGHTSHIFT	3	3	Term
+BVSRSHIFT	3	3	Term
+BVVARSHIFT	3	3	Term
+BVPLUS		1	-	Term
+BVSUB		2	2	Term
+BVUMINUS	1	1	Term
+BVMULTINVERSE	1	1	Term
+BVMULT		1	-	Term
+BVDIV		2	2	Term
+BVMOD		2	2	Term
+SBVDIV		2	2	Term
+SBVMOD		2	2	Term
+BVSX		1	1	Term
+BOOLVEC         0       -       Term
+
+# Formula OR term, depending on context
+ITE		3	3	Term	Form
+
+# These produce formulas.
+BVGETBIT	2	2	Form
+BVLT		2	2	Form
+BVLE		2	2	Form
+BVGT		2	2	Form
+BVGE		2	2	Form
+BVSLT		2	2	Form
+BVSLE		2	2	Form
+BVSGT		2	2	Form
+BVSGE		2	2	Form
+EQ		2	2	Form
+NEQ		2	2	Form
+FALSE		0	0	Form
+TRUE		0	0	Form
+NOT		1	1	Form
+AND		1	-	Form
+OR		1	-	Form
+NAND		1	-	Form
+NOR		1	-	Form
+XOR		1	-	Form
+IFF		1	-	Form
+IMPLIES		2	2	Form
+
+# array operations
+READ		2	2	Term
+WRITE		3	3	Term
+
+#Types: These kinds are used only in the API. Once processed inside
+#the API, they are never used again in the system 
+ARRAY           0       0
+BITVECTOR       0       0
+BOOLEAN         0       0
+
diff --git a/stp/AST/ASTUtil.cpp b/stp/AST/ASTUtil.cpp
new file mode 100644
index 00000000..bc36812c
--- /dev/null
+++ b/stp/AST/ASTUtil.cpp
@@ -0,0 +1,45 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "ASTUtil.h"
+#include <ostream>
+
+namespace BEEV {
+  ostream &operator<<(ostream &os, const Spacer &sp) {
+    // Instead of wrapping lines with hundreds of spaces, prints
+    // a "+" at the beginning of the line for each wrap-around.
+    // so lines print like: +14+		(XOR ...
+    int blanks = sp._spaces % 60;
+    int wraps = sp._spaces / 60;
+    if (wraps > 0) {
+      os << "+" << wraps;
+    }
+    for (int i = 0; i < blanks; i++)
+      os << " ";  
+    return os;
+  }
+   
+  //this function accepts the name of a function (as a char *), and
+  //records some stats about it. if the input is "print_func_stats",
+  //the function will then print the stats that it has collected.
+  void CountersAndStats(const char * functionname) {
+    if(!stats)
+      return;
+    static function_counters s;
+    
+    if(!strcmp(functionname,"print_func_stats")) {
+      cout << endl;
+      for(hash_map<const char*,int,hash<const char*>,eqstr>::iterator it=s.begin(),itend=s.end();
+	  it!=itend;it++)
+	cout << "Number of times the function: " << it->first << ": is called: " << it->second << endl;
+      return;
+    }
+    s[functionname] += 1;
+  }
+};// end of namespace
diff --git a/stp/AST/ASTUtil.h b/stp/AST/ASTUtil.h
new file mode 100644
index 00000000..0ed6bfa2
--- /dev/null
+++ b/stp/AST/ASTUtil.h
@@ -0,0 +1,107 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#ifndef ASTUTIL_H
+#define ASTUTIL_H
+
+#include <cstring>
+#include <iostream>
+#include <vector>
+#ifdef EXT_HASH_MAP
+#include <ext/hash_set>
+#include <ext/hash_map>
+#else
+#include <hash_set>
+#include <hash_map>
+#endif
+
+using namespace std; 
+namespace BEEV {
+#ifdef EXT_HASH_MAP
+  using namespace __gnu_cxx;
+#endif
+  //some global variables that are set through commandline options. it
+  //is best that these variables remain global. Default values set
+  //here
+  //
+  //collect statistics on certain functions
+  extern bool stats;
+  //print DAG nodes
+  extern bool print_nodes;
+  //tentative global var to allow for variable activity optimization
+  //in the SAT solver. deprecated.
+  extern bool variable_activity_optimize;
+  //run STP in optimized mode
+  extern bool optimize;
+  //do sat refinement, i.e. underconstraint the problem, and feed to
+  //SAT. if this works, great. else, add a set of suitable constraints
+  //to re-constraint the problem correctly, and call SAT again, until
+  //all constraints have been added.
+  extern bool arrayread_refinement;
+  //switch to control write refinements
+  extern bool arraywrite_refinement;
+  //check the counterexample against the original input to STP
+  extern bool check_counterexample;
+  //construct the counterexample in terms of original variable based
+  //on the counterexample returned by SAT solver
+  extern bool construct_counterexample;
+  extern bool print_counterexample;
+  //if this option is true then print the way dawson wants using a
+  //different printer. do not use this printer.
+  extern bool print_arrayval_declaredorder;
+  //flag to decide whether to print "valid/invalid" or not
+  extern bool print_output;
+  //do linear search in the array values of an input array. experimental
+  extern bool linear_search;
+  //print the variable order chosen by the sat solver while it is
+  //solving.
+  extern bool print_sat_varorder; 
+  //turn on word level bitvector solver
+  extern bool wordlevel_solve;
+  //XOR flattening optimizations.
+  extern bool xor_flatten;
+  //this flag indicates that the BVSolver() succeeded
+  extern bool toplevel_solved;
+  //the smtlib parser has been turned on
+  extern bool smtlib_parser_enable;
+  //print the input back
+  extern bool print_STPinput_back;
+
+  extern void (*vc_error_hdlr)(const char* err_msg);
+  /*Spacer class is basically just an int, but the new class allows
+    overloading of << with a special definition that prints the int as
+    that many spaces. */
+  class Spacer {
+  public:
+    int _spaces;
+    Spacer(int spaces) { _spaces = spaces; }
+    friend ostream& operator<<(ostream& os, const Spacer &ind);
+  };
+
+  inline Spacer spaces(int width) {
+    Spacer sp(width);
+    return sp;
+  }
+
+  struct eqstr {
+    bool operator()(const char* s1, const char* s2) const {
+      return strcmp(s1, s2) == 0;
+    }
+  };
+  
+  typedef hash_map<const char*,int, 
+		   hash<const char *>,eqstr> function_counters;
+  void CountersAndStats(const char * functionname);
+
+  //global function which accepts an integer and looks up the
+  //corresponding ASTNode and prints a char* of that ASTNode
+  void Convert_MINISATVar_To_ASTNode_Print(int minisat_var, 
+					   int decision, int polarity=0);
+}; // end namespace.
+#endif
diff --git a/stp/AST/BitBlast.cpp b/stp/AST/BitBlast.cpp
new file mode 100644
index 00000000..de78ec74
--- /dev/null
+++ b/stp/AST/BitBlast.cpp
@@ -0,0 +1,812 @@
+/********************************************************************
+ * AUTHORS: David L. Dill, Vijay Ganesh
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+// BitBlast -- convert bitvector terms and formulas to boolean
+// formulas.  A term is something that can represent a multi-bit
+// bitvector, such as BVPLUS or BVXOR (or a BV variable or constant).
+// A formula (form) represents a boolean value, such as EQ or BVLE.
+// Bit blasting a term representing an n-bit bitvector with BBTerm
+// yields a vector of n boolean formulas (returning ASTVec).
+// Bit blasting a formula returns a single boolean formula (type ASTNode).
+
+// A bitblasted term is a vector of ASTNodes for formulas.
+// The 0th element of the vector corresponds to bit 0 -- the low-order bit.
+
+#include "AST.h"
+namespace BEEV {
+  //  extern void lpvec(ASTVec &vec);
+
+// FIXME: Assert no zero-length bit vectors!!!
+// FIXME: Need top-level functions that create and destroy the memo tables.
+// FIXME:  Check resource limits and generate an exception when exceeded.
+// FIXME:  THis does a lot of unnecessary copying of vectors.
+//    Had to be careful not to modify memoized vectors!
+// FIXME:  Might be some redundant variables.
+
+// accepts a term, and returns a vector of bitblasted bits(ASTVec)
+
+ASTNode ASTJunk;
+const ASTNode BeevMgr::BBTerm(const ASTNode& term) {
+  //CHANGED TermMemo is now an ASTNodeMap. Based on BBFormMemo
+  ASTNodeMap::iterator it = BBTermMemo.find(term);
+  if (it != BBTermMemo.end()) {
+    // already there.  Just return it.
+    return it->second;
+  }
+
+//  ASTNode& result = ASTJunk;
+  ASTNode result;
+
+  Kind k = term.GetKind();
+  if (!is_Term_kind(k))
+    FatalError("BBTerm: Illegal kind to BBTerm",term);
+
+  ASTVec::const_iterator kids_end = term.end(); 
+  unsigned int num_bits = term.GetValueWidth();
+  switch (k) {
+  case BVNEG: {
+    // bitwise complement
+    // bitblast the child.
+    //FIXME Uses a tempory const ASTNode
+    const ASTNode& bbkids = BBTerm(term[0]);
+    result = CreateNode(BOOLVEC, BBNeg(bbkids.GetChildren()));
+    break;
+  }
+  case BVSRSHIFT:
+  case BVVARSHIFT: 
+    FatalError("BBTerm: These kinds have not been implemented in the BitBlaster: ", term);
+    break;
+  case ITE: {
+    // Term version of ITE.
+
+    // Blast the args
+    // FIXME Uses temporary const ASTNodes and an ASTVec&
+    const ASTNode& cond = BBForm(term[0]);
+    const ASTNode& thn = BBTerm(term[1]);
+    const ASTNode& els = BBTerm(term[2]);
+    result = 
+       CreateNode(BOOLVEC, BBITE(cond, thn.GetChildren(), els.GetChildren()));
+    break;
+  }
+  case BVSX: {
+    // Replicate high-order bit as many times as necessary.
+    // Arg 0 is expression to be sign extended.
+    const ASTNode& arg = term[0];
+    unsigned long result_width = term.GetValueWidth();
+    unsigned long arg_width = arg.GetValueWidth();
+    //FIXME Uses a temporary const ASTNode reference
+    const ASTNode& bbarg = BBTerm(arg);
+
+    if (result_width == arg_width) {
+      //nothing to sign extend
+      break;
+    }
+    else {
+      //we need to sign extend
+      const ASTNode& msbX = bbarg.back();
+      //const ASTNode& msb1 = msbX;
+      
+      ASTVec ccc = msbX.GetChildren();
+      const ASTNode& msb = CreateSimpForm(msbX.GetKind(),ccc);
+
+     //  Old version
+     //  ASTNode msb = bbarg.back();
+     //  const ASTNode msb1 = msb;
+      
+     //  ASTVec ccc = msb.GetChildren();
+     //  msb = CreateSimpForm(msb.GetKind(),ccc);
+
+      // DD 1/14/07 Simplify silently drops all but first two args of XOR.
+      // I expanded XOR to N args with flattening optimization.
+      // This bug took 2 days to track down!
+
+      // msb = SimplifyFormula(msb,false);
+
+      // cout << "!!!!!!!!!!!!!!!!" << endl
+      // << "Simplify msb:" << msb2 << endl
+      // << "Simplify result:" << msb << endl;
+
+      //FIXME Dynamically allocate the result vector?
+      //Is this doing multiple copies?
+      //ASTVec& tmp_res = *(new ASTVec(result_width));
+      ASTVec tmp_res(result_width);
+
+      //FIXME Should these be gotten from result?
+      ASTVec::const_iterator bb_it = bbarg.begin();
+      ASTVec::iterator res_it = tmp_res.begin();
+      ASTVec::iterator res_ext = res_it+arg_width; // first bit of extended part
+      ASTVec::iterator res_end = tmp_res.end();
+      // copy LSBs directly from bbvec
+      for( ; res_it < res_ext; (res_it++, bb_it++)) {
+	*res_it = *bb_it;
+      }
+      // repeat MSB to fill up rest of result.
+      for( ; res_it < res_end; (res_it++, bb_it++)) {
+	*res_it = msb;
+      }
+      
+       //Temporary debugging code
+       //    cout << "Sign extending:" << endl 
+       //	        << "  Vec ";
+       //    lpvec( bbarg.GetChildren() );
+       //    cout << "  Extended to ";
+       //    lp(result);
+       //    cout << endl;
+      
+      result = CreateNode(BOOLVEC, tmp_res);
+
+      break;
+    }
+  }
+  case BVEXTRACT: {
+    // bitblast the child, then extract the relevant bits.
+    // Note: This could be optimized by not bitblasting the bits
+    // that aren't fetched.  But that would be tricky, especially
+    // with memo-ization.
+
+    //FIXME Using const ASTNode w/out reference
+    const ASTNode& bbkids = BBTerm(term[0]); 
+    unsigned int high = GetUnsignedConst(term[1]);
+    unsigned int low = GetUnsignedConst(term[2]);
+
+    ASTVec::const_iterator bbkfit = bbkids.begin();
+    // I should have used pointers to ASTVec, to avoid this crock
+    
+    //FIXME Creates a new local ASTVec and does the CreateNode from that
+    result = CreateNode(BOOLVEC, ASTVec(bbkfit+low, bbkfit+high+1));
+    break;
+  }
+  case BVCONCAT: {
+    //FIXME Using temporary const ASTNodes 
+    const ASTNode& vec1 = BBTerm(term[0]);
+    const ASTNode& vec2 = BBTerm(term[1]);
+
+    //FIXME This has to be an unnessecary copy and a memory leak
+    //Leaking ASTVec tmp_res = *(new ASTVec(vec2.GetChildren()));
+    ASTVec tmp_res(vec2.GetChildren());
+    tmp_res.insert(tmp_res.end(), vec1.begin(), vec1.end());
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }
+  case BVPLUS: {
+    // ASSERT: at least one child.
+    // ASSERT: all children and result are the same size.
+    // Previous phase must make sure this is true.
+    // Add children pairwise and accumulate in BBsum
+
+    // FIXME: Unnecessary array copies.
+    ASTVec::const_iterator it = term.begin();
+    ASTVec tmp_res = BBTerm(*it).GetChildren();
+    for (++it; it < kids_end; it++) {
+      const ASTVec& tmp = BBTerm(*it).GetChildren();
+      BBPlus2(tmp_res, tmp, ASTFalse);
+    }
+
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }
+  case BVUMINUS: {
+    //FIXME Using const ASTNode reference
+    const ASTNode& bbkid = BBTerm(term[0]);
+    result = CreateNode(BOOLVEC, BBUminus(bbkid.GetChildren()));
+    break;
+  }
+  case BVSUB: {
+    // complement of subtrahend
+    // copy, since BBSub writes into it.
+    
+    //FIXME: Unnecessary array copies?
+    ASTVec tmp_res = BBTerm(term[0]).GetChildren(); 
+
+    const ASTVec& bbkid1 = BBTerm(term[1]).GetChildren();
+    BBSub(tmp_res, bbkid1);
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }
+  case BVMULT: {
+    // ASSERT 2 arguments, same length, result is same length.
+
+    const ASTNode& t0 = term[0];
+    const ASTNode& t1 = term[1];
+
+    const ASTNode& mpcd1 = BBTerm(t0);
+    const ASTNode& mpcd2 = BBTerm(t1);
+    //Reverese the order of the nodes w/out the need for temporaries
+    //This is needed because t0 an t1 must be const
+    if ((BVCONST != t0.GetKind()) && (BVCONST == t1.GetKind())) {
+      result = CreateNode(BOOLVEC, 
+        BBMult(mpcd2.GetChildren(), mpcd1.GetChildren()) );
+    }else{
+      result = CreateNode(BOOLVEC, 
+        BBMult(mpcd1.GetChildren(), mpcd2.GetChildren()) );
+    }
+    break;
+  }
+  case BVDIV:
+  case BVMOD: {
+    const ASTNode& dvdd = BBTerm(term[0]);
+    const ASTNode& dvsr = BBTerm(term[1]);
+    unsigned int width = dvdd.Degree();
+    ASTVec q(width); 
+    ASTVec r(width); 
+    BBDivMod(dvdd.GetChildren(),  dvsr.GetChildren(), q, r, width);
+    if (k == BVDIV)
+      result = CreateNode(BOOLVEC, q);    
+    else
+      result = CreateNode(BOOLVEC, r);
+    break;
+  }
+  //  n-ary bitwise operators.
+  case BVXOR:
+  case BVXNOR:
+  case BVAND:
+  case BVOR:
+  case BVNOR:
+  case BVNAND: {
+    // Add children pairwise and accumulate in BBsum
+    ASTVec::const_iterator it = term.begin();
+    Kind bk = UNDEFINED;  // Kind of individual bit op.
+    switch (k) {
+    case BVXOR: bk = XOR;  break;
+    case BVXNOR: bk = IFF; break;
+    case BVAND: bk = AND; break;
+    case BVOR: bk = OR; break;
+    case BVNOR: bk = NOR; break;
+    case BVNAND: bk = NAND; break;
+    default:
+      FatalError("BBTerm: Illegal kind to BBTerm",term);
+      break;
+    }
+
+    // Sum is destructively modified in the loop, so make a copy of value
+    // returned by BBTerm.
+    ASTNode temp = BBTerm(*it);
+    ASTVec sum(temp.GetChildren());	// First operand.
+
+    // Iterate over remaining bitvector term operands
+    for (++it; it < kids_end; it++) {
+      //FIXME FIXME FIXME: Why does using a temp. var change the behavior?
+      temp = BBTerm(*it);
+      const ASTVec& y = temp.GetChildren();
+      
+      // Iterate over bits
+      // FIXME: Why is this not using an iterator???
+      int n = y.size();
+      for (int i = 0; i < n; i++) {
+	sum[i] = CreateSimpForm(bk, sum[i], y[i]);
+      }
+    }
+    result = CreateNode(BOOLVEC, sum);
+    break;
+  }
+  case SYMBOL: {
+    // ASSERT: IndexWidth = 0?  Semantic analysis should check.
+    //Leaking ASTVec& bbvec = *(new ASTVec);
+    
+    //FIXME Why is isn't this ASTVEC bbvec(num_bits) ?
+    ASTVec bbvec;
+    for (unsigned int i = 0; i < num_bits; i++) {
+      ASTNode bit_node =
+	CreateNode(BVGETBIT, term, CreateBVConst(32,i));
+      bbvec.push_back(bit_node); 
+    }
+    result = CreateNode(BOOLVEC, bbvec);
+    break;
+  }
+  case BVCONST: {
+    ASTVec tmp_res(num_bits);
+#ifndef NATIVE_C_ARITH
+    CBV bv = term.GetBVConst();
+    for(unsigned int i = 0; i < num_bits; i++){
+      tmp_res[i] = CONSTANTBV::BitVector_bit_test(bv,i) ? ASTTrue : ASTFalse; 
+    }  
+#else
+    const unsigned long long int c = term.GetBVConst();
+    unsigned long long int bitmask = 0x00000000000000001LL;
+    for (unsigned int i = 0; i < num_bits; i++, bitmask <<= 1)
+      tmp_res[i] = ((c & (bitmask)) ? ASTTrue : ASTFalse);    
+#endif
+    result = CreateNode(BOOLVEC, tmp_res);
+    break;
+  }		  
+  case BOOLVEC: {
+    cerr << "Hit a boolvec! what to do?" << endl;
+    break;
+  }
+  default:
+    FatalError("BBTerm: Illegal kind to BBTerm",term);
+  }
+
+  //if(result == ASTJunk)
+  //  cout<<"result does not change"<<endl;
+  // cout << "================" << endl << "BBTerm:" << term << endl;
+  // cout << "----------------" << endl << "BBTerm result:";
+  // lpvec(result);
+  // cout << endl;
+
+  return (BBTermMemo[term] = result);
+
+}
+
+// bit blast a formula (boolean term).  Result is one bit wide,
+// so it returns a single ASTNode.
+// FIXME:  Add IsNegated flag.
+const ASTNode BeevMgr::BBForm(const ASTNode& form)
+{
+
+  ASTNodeMap::iterator it = BBFormMemo.find(form);
+  if (it != BBFormMemo.end()) {
+    // already there.  Just return it.
+    return it->second;
+  }
+
+  ASTNode result = ASTUndefined;
+
+  Kind k = form.GetKind();
+  if (!is_Form_kind(k)) {
+    FatalError("BBForm: Illegal kind: ",form);
+  }
+
+  //  Not returning until end, and memoizing everything, makes it easier
+  // to trace coherently.
+    
+  // Various special cases
+  switch (k) {
+  case TRUE:
+  case FALSE: {
+    result = form;
+    break;
+  }
+
+  case SYMBOL:
+    if (form.GetType() != BOOLEAN_TYPE) {
+      FatalError("BBForm: Symbol represents more than one bit", form);
+    }
+
+    result = form;
+    break;
+
+  case BVGETBIT: {
+    // exactly two children
+    const ASTNode bbchild = BBTerm(form[0]);
+    unsigned int index =  GetUnsignedConst(form[1]);
+    result = bbchild[index];
+    break;
+  }
+
+  case NOT:
+    result = CreateSimpNot(BBForm(form[0]));
+    break;  
+
+  case ITE:
+    // FIXME: SHould this be CreateSimpITE?
+    result = CreateNode(ITE, BBForm(form[0]), BBForm(form[1]), BBForm(form[2]));
+    break;
+
+  case AND: 
+  case OR: 
+  case NAND: 
+  case NOR: 
+  case IFF: 
+  case XOR:
+  case IMPLIES: {
+    ASTVec bbkids;		// bit-blasted children (formulas)
+
+    // FIXME: Put in fast exits for AND/OR/NAND/NOR/IMPLIES
+    ASTVec::const_iterator kids_end = form.end(); 
+    for (ASTVec::const_iterator it = form.begin(); it != kids_end; it++) {
+      bbkids.push_back(BBForm(*it));
+    }
+    result = CreateSimpForm(k, bbkids);
+    break;
+  }
+
+  case NEQ: {
+    ASTNode bbkid = BBForm(CreateNode(EQ, form.GetChildren()));
+    result = CreateSimpNot(bbkid);
+    break;
+  }
+
+  case EQ: {
+    // Common code for binary operations
+    // FIXME:  This ought to be in a semantic analysis phase.
+    const ASTNode left = BBTerm(form[0]);
+    const ASTNode right = BBTerm(form[1]);
+    if (left.Degree() != right.Degree()) {
+      cerr << "BBForm: Size mismatch" << endl << form[0] << endl << form[1] << endl;
+      FatalError("",ASTUndefined);
+    }
+    result = BBEQ(left.GetChildren(), right.GetChildren());
+    break;
+  }
+
+  case BVLE: 
+  case BVGE: 
+  case BVGT: 
+  case BVLT: 
+  case BVSLE:
+  case BVSGE:
+  case BVSGT:
+  case BVSLT: {
+    result = BBcompare(form);
+    break;
+  }
+  default:
+    FatalError("BBForm: Illegal kind: ", form);
+    break;
+  }
+
+  // cout << "================" << endl
+  // << "BBForm: " << form << endl
+  // << "----------------" << endl
+  // << "BBForm Result: " << result << endl;
+
+  return (BBFormMemo[form] = result);
+}
+  
+// Bit blast a sum of two equal length BVs.
+// Update sum vector destructively with new sum.
+void BeevMgr::BBPlus2(ASTVec& sum, const ASTVec& y, ASTNode cin)
+{
+//   cout << "Bitblasting plus.  Operand 1: " << endl;
+//   lpvec(sum);
+//   cout << endl << " operand 2: " << endl;
+//   lpvec(y);
+//   cout << endl << "carry: " << endl << cin << endl;
+
+
+  int n = sum.size();
+  // ASSERT: y.size() == x.size()
+  // FIXME: Don't bother computing i+1 carry, which is discarded.
+  for (int i = 0; i < n; i++) {
+    ASTNode nextcin = Majority(sum[i], y[i], cin); 
+    sum[i] = CreateSimpForm(XOR, CreateSimpForm(XOR, sum[i], y[i]), cin);
+    cin = nextcin;
+  }
+
+//   cout << "----------------" << endl << "Result: " << endl;
+//   lpvec(sum);
+//   cout << endl;
+
+}
+
+// Stores result - x in result, destructively
+void BeevMgr::BBSub(ASTVec& result, const ASTVec& y)
+{
+  ASTVec compsubtrahend  = BBNeg(y);
+  BBPlus2(result, compsubtrahend, ASTTrue);
+}
+
+// Add one bit
+ASTVec BeevMgr::BBAddOneBit(ASTVec& x, ASTNode cin)
+{
+  ASTVec result = ASTVec(0);
+  ASTVec::const_iterator itend = x.end();
+  for (ASTVec::const_iterator it = x.begin(); it < itend; it++) {
+    ASTNode nextcin = CreateSimpForm(AND, *it, cin); 
+    result.push_back(CreateSimpForm(XOR, *it, cin));
+    cin = nextcin;
+  }
+  // FIXME: unnecessary array copy on return?
+  return result;
+}
+
+// Increment bit-blasted vector and return result.
+ASTVec BeevMgr::BBInc(ASTVec& x)
+{
+  return BBAddOneBit(x, ASTTrue);
+}
+
+// Return formula for majority function of three bits.
+// Pass arguments by reference to reduce refcounting.
+ASTNode BeevMgr::Majority(const ASTNode& a, const ASTNode& b,const ASTNode& c)
+{
+  // Checking explicitly for constant a, b and c could
+  // be more efficient, because they are repeated in the logic.
+  if (ASTTrue == a) {
+    return CreateSimpForm(OR, b, c);
+  }
+  else if (ASTFalse == a) {
+    return CreateSimpForm(AND, b, c);
+  }
+  else if (ASTTrue == b) {
+    return CreateSimpForm(OR, a, c);
+  }
+  else if (ASTFalse == b) {
+    return CreateSimpForm(AND, a, c);
+  }
+  else if (ASTTrue == c) {
+    return CreateSimpForm(OR, a, b);
+  }
+  else if (ASTFalse == c) {
+    return CreateSimpForm(AND, a, b);
+  }
+  // there are lots more simplifications, but I'm not sure they're
+  // worth doing explicitly (e.g., a = b, a = ~b, etc.) 
+  else {
+    return
+      CreateSimpForm(OR,
+		     CreateSimpForm(AND, a, b),
+		     CreateSimpForm(AND, b, c),
+		     CreateSimpForm(AND, a, c));
+  }
+}
+
+
+// Bitwise complement
+ASTVec BeevMgr::BBNeg(const ASTVec& x)
+{
+  ASTVec result = ASTVec(0);		// FIXME: faster to preallocate n entries?
+  // Negate each bit.
+  ASTVec::const_iterator xend = x.end();
+  for (ASTVec::const_iterator it = x.begin(); it < xend; it++) {
+    result.push_back(CreateSimpNot(*it));
+  }
+  // FIXME: unecessary array copy when it returns?
+  return result;
+}
+
+// Compute unary minus
+ASTVec BeevMgr::BBUminus(const ASTVec& x)
+{
+  ASTVec xneg = BBNeg(x);
+  return BBInc(xneg);
+}
+
+// Multiply two bitblasted numbers
+ASTVec BeevMgr::BBMult(const ASTVec& x, const ASTVec& y)
+{
+  ASTVec ycopy(y);
+  ASTVec::const_iterator xend = x.end();
+  ASTVec::const_iterator xit = x.begin();
+  // start prod with first partial product.
+  // FIXME: This is unnecessary. Clean it up.
+  ASTVec prod = ASTVec(BBAndBit(y, *xit));
+  // start loop at next bit.
+  for(xit++; xit < xend; xit++) {
+    // shift first
+    BBLShift(ycopy);
+
+    if (ASTFalse == *xit) {
+      // If this bit is zero, the partial product will
+      // be zero.  No reason to add that in.
+      continue;
+    }
+
+    ASTVec pprod = BBAndBit(ycopy, *xit);
+    // accumulate in the product.
+    BBPlus2(prod, pprod, ASTFalse);
+  }
+  return prod;
+}
+
+// This implements a variant of binary long division.
+// q and r are "out" parameters.  rwidth puts a bound on the
+// recursion depth.
+void BeevMgr::BBDivMod(const ASTVec &y, const ASTVec &x, ASTVec &q, ASTVec &r, unsigned int rwidth)
+{
+  unsigned int width = y.size();
+  if (rwidth == 0) {
+    // When we have shifted the entire width, y is guaranteed to be 0.
+    q = BBfill(width, ASTFalse);
+    r = BBfill(width, ASTFalse);
+  }
+  else {
+    ASTVec q1, r1;
+    ASTVec yrshift1(y);
+    BBRShift(yrshift1);
+
+    // recursively divide y/2 by x.
+    BBDivMod(yrshift1, x, q1, r1, rwidth-1);
+
+    ASTVec q1lshift1(q1);
+    BBLShift(q1lshift1);
+
+    ASTVec r1lshift1(r1);
+    BBLShift(r1lshift1);
+    
+    ASTVec r1lshift1plusyodd = BBAddOneBit(r1lshift1, y[0]);
+    ASTVec rminusx(r1lshift1plusyodd);
+    BBSub(rminusx, x);
+
+    // Adjusted q, r values when when r is too large.
+    ASTNode rtoolarge = BBBVLE(x, r1lshift1plusyodd, false);
+    ASTVec ygtrxqval = BBITE(rtoolarge, BBInc(q1lshift1), q1lshift1);
+    ASTVec ygtrxrval = BBITE(rtoolarge, rminusx, r1lshift1plusyodd);
+
+    // q & r values when y >= x
+    ASTNode yeqx = BBEQ(y, x);
+    // *** Problem: the bbfill for qval is wrong.  Should be 1, not -1.
+    ASTVec one = BBfill(width, ASTFalse);
+    one[0] = ASTTrue;
+    ASTVec notylessxqval = BBITE(yeqx, one, ygtrxqval);
+    ASTVec notylessxrval = BBITE(yeqx, BBfill(width, ASTFalse), ygtrxrval);
+    // y < x <=> not x >= y.
+    ASTNode ylessx = CreateSimpNot(BBBVLE(x, y, false));
+    // final values of q and r
+    q = BBITE(ylessx, BBfill(width, ASTFalse), notylessxqval);
+    r = BBITE(ylessx, y, notylessxrval);
+  }
+}
+
+// build ITE's (ITE cond then[i] else[i]) for each i.
+ASTVec BeevMgr::BBITE(const ASTNode& cond, const ASTVec& thn, const ASTVec& els)
+{
+  // Fast exits.
+  if (ASTTrue == cond) {
+    return thn;
+  }
+  else if (ASTFalse == cond) {
+    return els;
+  }
+
+  ASTVec result(0);
+  ASTVec::const_iterator th_it_end = thn.end();
+  ASTVec::const_iterator el_it = els.begin();
+  for (ASTVec::const_iterator th_it = thn.begin(); th_it < th_it_end; th_it++, el_it++) {
+    result.push_back(CreateSimpForm(ITE, cond, *th_it, *el_it));
+  }
+  return result;
+}
+// AND each bit of vector y with single bit b and return the result.
+ASTVec BeevMgr::BBAndBit(const ASTVec& y, ASTNode b)
+{
+  ASTVec result(0); 
+
+  if (ASTTrue == b) {
+    return y;
+  }
+  // FIXME: put in fast exits when b is constant 0. 
+
+  ASTVec::const_iterator yend = y.end();
+  for(ASTVec::const_iterator yit = y.begin(); yit < yend; yit++) {
+    result.push_back(CreateSimpForm(AND, *yit, b));
+  }
+  return result;
+}
+
+
+// Workhorse for comparison routines.  This does a signed BVLE if is_signed
+// is true, else it's unsigned.  All other comparison operators can be reduced
+// to this by swapping args or complementing the result bit.
+// FIXME:  If this were done MSB first, it would enable a fast exit sometimes
+// when the MSB is constant, deciding the result without looking at the rest
+// of the bits.
+ASTNode BeevMgr::BBBVLE(const ASTVec& left, const ASTVec& right, bool is_signed)
+{
+  // "thisbit" represents BVLE of the suffixes of the BVs
+  // from that position .  if R < L, return TRUE, else if L < R
+  // return FALSE, else return BVLE of lower-order bits.  MSB is
+  // treated separately, because signed comparison is done by
+  // complementing the MSB of each BV, then doing an unsigned
+  // comparison.
+  ASTVec::const_iterator lit = left.begin();
+  ASTVec::const_iterator litend = left.end();
+  ASTVec::const_iterator rit = right.begin();
+  ASTNode prevbit = ASTTrue;
+  for ( ; lit  < litend-1; lit++, rit++) {
+    ASTNode neglit = CreateSimpNot(*lit);
+    ASTNode thisbit =
+      CreateSimpForm(OR,
+		 CreateSimpForm(AND,neglit,*rit), // TRUE if l < r
+		 CreateSimpForm(AND,
+			    CreateSimpForm(OR, neglit, *rit), // false if not equal
+			    prevbit)); // else prevbit
+    prevbit = thisbit;
+  }
+
+  // Handle MSB -- negate MSBs if signed comparison
+  // FIXME: make into refs after it's debugged.
+  ASTNode lmsb = *lit;
+  ASTNode rmsb = *rit;
+  if (is_signed) {
+    lmsb = CreateSimpNot(*lit);
+    rmsb = CreateSimpNot(*rit);
+  }
+
+  ASTNode neglmsb = CreateSimpNot(lmsb);
+  ASTNode msb =
+    CreateSimpForm(OR,
+	       CreateSimpForm(AND,neglmsb, rmsb), // TRUE if l < r
+	       CreateSimpForm(AND,
+			  CreateSimpForm(OR, neglmsb, rmsb), // false if not equal
+			  prevbit)); // else prevbit
+  return msb;
+}
+
+// Left shift by 1 within fixed field inserting zeros at LSB.
+// Writes result into first argument.
+// Fixme: generalize to n bits
+void BeevMgr::BBLShift(ASTVec& x)
+{
+  // left shift x (destructively) within width.
+  // loop backwards so that copy to self works correctly. (DON'T use STL insert!)
+  ASTVec::iterator xbeg = x.begin();
+  for(ASTVec::iterator xit = x.end()-1; xit > xbeg; xit--) {
+    *xit = *(xit-1);
+  }
+  *xbeg = ASTFalse;		// new LSB is zero.
+  // cout << "Shifted result" << endl;
+  // lpvec(x);
+}
+
+// Right shift by 1 within fixed field, inserting new zeros at MSB.
+// Writes result into first argument.
+// Fixme: generalize to n bits.
+void BeevMgr::BBRShift(ASTVec& x)
+{
+  ASTVec::iterator xend = x.end() - 1;
+  ASTVec::iterator xit = x.begin();
+  for( ; xit < xend; xit++) {
+    *xit = *(xit+1);
+  }
+  *xit = ASTFalse;		// new MSB is zero.
+}
+
+
+// Return bit-blasted form for BVLE, BVGE, BVGT, SBLE, etc. 
+ASTNode BeevMgr::BBcompare(const ASTNode& form) {
+  const ASTNode lnode = BBTerm(form[0]);
+  const ASTNode rnode = BBTerm(form[1]);
+  const ASTVec& left = lnode.GetChildren();
+  const ASTVec& right = rnode.GetChildren();
+
+  //const ASTVec& left = BBTerm(form[0]).GetChildren();
+  //const ASTVec& right = BBTerm(form[1]).GetChildren();
+
+  Kind k = form.GetKind();
+  switch(k) {
+  case BVLE: { return BBBVLE(left, right, false); break; }
+  case BVGE: { return BBBVLE(right, left, false); break; }
+  case BVGT: { return CreateSimpNot(BBBVLE(left, right, false)); break; }
+  case BVLT: { return CreateSimpNot(BBBVLE(right, left, false)); break; }
+  case BVSLE: { return BBBVLE(left, right, true); break; }
+  case BVSGE: { return BBBVLE(right, left, true); break; }
+  case BVSGT: { return CreateSimpNot(BBBVLE(left, right, true)); break; }
+  case BVSLT: { return CreateSimpNot(BBBVLE(right, left, true)); break; }
+  default:
+    cerr << "BBCompare: Illegal kind" << form << endl;    
+    FatalError("",ASTUndefined);
+  }
+  return ASTUndefined;
+}
+
+
+// return a vector with n copies of fillval
+ASTVec BeevMgr::BBfill(unsigned int width, ASTNode fillval)
+{
+  ASTVec zvec(width, fillval);
+  return zvec;
+}
+
+ASTNode BeevMgr::BBEQ(const ASTVec& left, const ASTVec& right)
+{
+  ASTVec andvec;
+  ASTVec::const_iterator lit = left.begin();
+  ASTVec::const_iterator litend = left.end();
+  ASTVec::const_iterator rit = right.begin();
+  
+  if(left.size() > 1) {
+    for(; lit != litend; lit++, rit++) {
+      ASTNode biteq = CreateSimpForm(IFF, *lit, *rit);
+      // fast path exit
+      if (biteq == ASTFalse) {
+	return ASTFalse;
+      }
+      else {
+	andvec.push_back(biteq);
+      }
+    }
+    ASTNode n = CreateSimpForm(AND, andvec);  
+    return n;
+  }
+  else
+    return CreateSimpForm(IFF,*lit,*rit);
+}
+} // BEEV namespace
diff --git a/stp/AST/Makefile b/stp/AST/Makefile
new file mode 100644
index 00000000..0218510b
--- /dev/null
+++ b/stp/AST/Makefile
@@ -0,0 +1,54 @@
+include ../Makefile.common
+
+SRCS = AST.cpp ASTKind.cpp  ASTUtil.cpp BitBlast.cpp SimpBool.cpp  ToCNF.cpp ToSAT.cpp Transform.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+#Make the ast library for use by other modules
+libast.a:	$(OBJS)
+	-rm -rf $@
+	$(AR) rc libast.a $(OBJS)
+	$(RANLIB) libast.a
+
+ASTKind.o: ASTKind.h ASTKind.cpp
+	$(CXX) $(CXXFLAGS)   -c -o ASTKind.o ASTKind.cpp
+
+# ASTKind.h and ASTKind.cpp are automatically generated
+ASTKind.h ASTKind.cpp:	ASTKind.kinds genkinds.pl
+	./genkinds.pl
+
+# cnftest:	cnftest.o ToCNF.o AST.o ASTUtil.o ASTKind.o BitBlast.o AST.h
+#	$(CC) $(LDFLAGS) ToCNF.o BitBlast.o ASTKind.o  ASTUtil.o AST.o  cnftest.o  -o cnftest 
+
+# bbtest: $(OBJS)
+#	$(CC) $(LDFLAGS) BitBlast.o ASTKind.o  ASTUtil.o AST.o  bbtest.o -o bbtest 
+
+# asttest: $(OBJS)
+#	$(CC) $(LDFLAGS) ASTKind.o  ASTUtil.o AST.o asttest.o  -lstdc++ -o asttest
+
+clean:
+	rm -rf *.o *~ bbtest asttest cnftest *.a  ASTKind.h ASTKind.cpp .#*
+
+depend:
+	makedepend -Y -- $(CFLAGS) -- $(SRCS)
+# DO NOT DELETE
+
+AST.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+AST.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+AST.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ASTUtil.o: ASTUtil.h
+BitBlast.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+BitBlast.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+BitBlast.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+SimpBool.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+SimpBool.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+SimpBool.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ToCNF.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+ToCNF.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+ToCNF.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ToSAT.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+ToSAT.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+ToSAT.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
+ToSAT.o: ../simplifier/bvsolver.h ../AST/AST.h
+Transform.o: AST.h ASTUtil.h ASTKind.h ../sat/Solver.h ../sat/SolverTypes.h
+Transform.o: ../sat/Global.h ../sat/VarOrder.h ../sat/Solver.h ../sat/Heap.h
+Transform.o: ../AST/ASTUtil.h ../sat/SolverTypes.h ../constantbv/constantbv.h
diff --git a/stp/AST/STLport_config.h b/stp/AST/STLport_config.h
new file mode 100644
index 00000000..9b7bc14f
--- /dev/null
+++ b/stp/AST/STLport_config.h
@@ -0,0 +1,20 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+// STLport debug checking, if we use STLport threads flag is to get
+// rid of link errors, since iostreams compiles with threads.  alloc
+// and uninitialized are extra checks Later on, if used with Purify or
+// Valgrind, may want to set flags to prevent reporting of false
+// leaks.  For some reason, _STLP_THREADS works on the command line
+// but not here (?)
+#define _STLP_THREADS
+#define _STLP_DEBUG 1
+#define _STLP_DEBUG_LEVEL _STLP_STANDARD_DBG_LEVEL 
+#define _STLP_DEBUG_ALLOC 1
+#define _STLP_DEBUG_UNINITIALIZED 1
diff --git a/stp/AST/SimpBool.cpp b/stp/AST/SimpBool.cpp
new file mode 100644
index 00000000..67f9825d
--- /dev/null
+++ b/stp/AST/SimpBool.cpp
@@ -0,0 +1,408 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: April, 2006
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+
+// -*- c++ -*-
+
+// Simplifying create methods for Boolean operations.
+// These are only very simple local simplifications.
+
+// This is somewhat redundant with Vijay's simplifier code.  They
+// need to be merged.
+// FIXME: control with optimize flag.
+
+static bool _trace_simpbool = 0;
+static bool _disable_simpbool = 0;
+
+#include "AST.h"
+
+// SMTLIB experimental hack.  Try allocating a single stack here for
+// children to reduce growing of vectors.
+//BEEV::ASTVec child_stack;
+
+namespace BEEV {
+
+  ASTNode BeevMgr::CreateSimpForm(Kind kind, ASTVec &children = _empty_ASTVec) {
+    if (_disable_simpbool) {
+      return CreateNode(kind, children);
+    }
+    else {
+      switch (kind) {
+      case NOT: return CreateSimpNot(children[0]); break; 
+      case AND: return CreateSimpAndOr(1, children); break; 
+      case OR: return CreateSimpAndOr(0, children); break;
+      case NAND: return CreateSimpNot(CreateSimpAndOr(1, children)); break;
+      case NOR: return CreateSimpNot(CreateSimpAndOr(0, children)); break;
+      case IFF: {
+	// Not sure children can ever be empty, but what the heck.
+	//	if (children.size() == 0) {
+	//	  return ASTTrue;
+	//	}
+	// Convert IFF to XOR ASAP.  IFF is not associative, so this makes
+	// flattening much easier.
+	children[0] = CreateSimpNot(children[0]);
+	return CreateSimpXor(children); break;
+      }
+      case XOR: 
+	return CreateSimpXor(children); break;
+	// FIXME: Earlier, check that this only has two arguments
+      case IMPLIES: return CreateSimpAndOr(0, CreateSimpNot(children[0]), children[1]); break;
+      case ITE: return CreateSimpFormITE(children[0], children[1], children[2]);
+      default: return CreateNode(kind, children);
+      }
+    }
+  }
+
+  // specialized versions
+  
+  ASTNode BeevMgr::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);
+  }
+  
+  ASTNode BeevMgr::CreateSimpForm(Kind kind,
+				  const ASTNode& child0,
+				  const ASTNode& child1) {
+    ASTVec children;
+    //child_stack.clear();	// could just reset top pointer.
+    children.push_back(child0);
+    //child_stack.push_back(child0);
+    children.push_back(child1);
+    //child_stack.push_back(child1);
+    return CreateSimpForm(kind, children);
+    //return CreateSimpForm(kind, child_stack);
+  }
+  
+  
+  ASTNode BeevMgr::CreateSimpForm(Kind kind,
+				  const ASTNode& child0,
+				  const ASTNode& child1,
+				  const ASTNode& child2) {
+    ASTVec children;
+    //child_stack.clear();	// could just reset top pointer.
+    children.push_back(child0);
+    //child_stack.push_back(child0);
+    children.push_back(child1);
+    //child_stack.push_back(child1);
+    children.push_back(child2);
+    //child_stack.push_back(child2);
+    return CreateSimpForm(kind, children);
+    //return CreateSimpForm(kind, child_stack);
+  }
+    
+  ASTNode BeevMgr::CreateSimpNot(const ASTNode& form) {
+    Kind k = form.GetKind();
+    switch (k) {
+    case FALSE: { return ASTTrue; }
+    case TRUE: { return ASTFalse; }
+    case NOT: { return form[0]; } // NOT NOT cancellation
+    case XOR: {
+      // Push negation down in this case.
+      // FIXME: Separate pre-pass to push negation down?
+      // CreateSimp should be local, and this isn't.  
+      // It isn't memoized.  Arg.
+      ASTVec children = form.GetChildren();
+      children[0] = CreateSimpNot(children[0]);
+      return CreateSimpXor(children);
+    }
+    default: { return CreateNode(NOT, form); }
+    }
+  }
+
+  // I don't think this is even called, since it called
+  // CreateSimpAndOr instead of CreateSimpXor until 1/9/07 with no
+  // ill effects.  Calls seem to go to the version that takes a vector
+  // of children.
+  ASTNode BeevMgr::CreateSimpXor(const ASTNode& form1, const ASTNode& form2) {
+    ASTVec children;
+    children.push_back(form1);
+    children.push_back(form2);
+    return CreateSimpXor(children);
+  }
+
+
+  ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, const ASTNode& form1, const ASTNode& form2) {
+    ASTVec children;
+    children.push_back(form1);
+    children.push_back(form2);
+    return CreateSimpAndOr(IsAnd, children);
+  }
+
+  ASTNode BeevMgr::CreateSimpAndOr(bool IsAnd, ASTVec &children) {
+
+    if (_trace_simpbool) {
+      cout << "========" << endl << "CreateSimpAndOr " << (IsAnd ? "AND " : "OR ") ;
+      lpvec(children);
+      cout << endl;
+    }
+
+    ASTVec new_children;
+
+    // sort so that identical nodes occur in sequential runs, followed by
+    // their negations.
+
+    SortByExprNum(children);
+    
+    ASTNode annihilator = (IsAnd ? ASTFalse : ASTTrue);
+    ASTNode identity = (IsAnd ? ASTTrue : ASTFalse);
+
+    ASTNode retval;
+
+    ASTVec::const_iterator it_end = children.end();
+    ASTVec::const_iterator next_it;
+    for(ASTVec::const_iterator it = children.begin(); it != it_end; it = next_it) {
+      next_it = it + 1;
+      bool nextexists = (next_it < it_end);
+
+      if (*it == annihilator) {
+	retval = annihilator;
+	if (_trace_simpbool) {
+	  cout << "returns " << retval << endl;
+	}
+	return retval;
+      }
+      else if (*it == identity) {
+	// just drop it
+      }
+      else if (nextexists && (*next_it == *it)) {
+	// drop it
+	//	cout << "Dropping [" << it->GetNodeNum() << "]" << endl;
+      }
+      else if (nextexists && (next_it->GetKind() == NOT) && ((*next_it)[0] == *it)) {
+	// form and negation -- return FALSE for AND, TRUE for OR.
+	retval = annihilator;
+	// cout << "X and/or NOT X" << endl; 
+	if (_trace_simpbool) {
+	  cout << "returns " << retval << endl;
+	}
+	return retval;
+      }
+      else {
+	// add to children
+	new_children.push_back(*it);
+      }
+    }
+
+    // If we get here, we saw no annihilators, and children should
+    // be only the non-True nodes.
+    if (new_children.size() < 2) {
+      if (0 == new_children.size()) {
+	retval = identity;
+      }
+      else {
+	// there is just one child
+	retval = new_children[0];
+      }
+    }
+    else {
+      // 2 or more children.  Create a new node.
+      retval = CreateNode(IsAnd ? AND : OR, new_children);
+    }
+    if (_trace_simpbool) {
+      cout << "returns " << retval << endl;
+    }
+    return retval;
+  }
+
+
+  // Constant children are accumulated in "accumconst".  
+  ASTNode BeevMgr::CreateSimpXor(ASTVec &children) {
+
+    if (_trace_simpbool) {
+      cout << "========" << endl
+	   << "CreateSimpXor ";
+      lpvec(children);
+      cout << endl;
+    }
+
+    // Change this not to init to children if flattening code is present.
+    // ASTVec flat_children = children;		// empty vector
+
+    ASTVec flat_children;		// empty vector
+
+    ASTVec::const_iterator it_end = children.end();
+
+    if (xor_flatten) {
+
+      bool fflag = 0;		// ***Temp debugging
+      
+      // Experimental flattening code.
+      
+      for(ASTVec::iterator it = children.begin(); it != it_end; it++) {
+	Kind ck = it->GetKind();
+	const ASTVec &gchildren = it->GetChildren();
+	if (XOR == ck) {
+	  fflag = 1;
+	  // append grandchildren to children
+	  flat_children.insert(flat_children.end(), gchildren.begin(), gchildren.end());
+	}
+	else {
+	  flat_children.push_back(*it);
+	}
+      }
+      
+      if (_trace_simpbool && fflag) {
+	cout << "========" << endl;
+	cout << "Flattening: " << endl;
+	lpvec(children);
+	
+	cout << "--------" << endl;
+	cout << "Flattening result: " << endl;
+	lpvec(flat_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;
+  }
+
+  // FIXME:  How do I know whether ITE is a formula or not?
+  ASTNode BeevMgr::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); 
+    }
+    // ITE (x, !y, y) == x XOR y
+//     else if (NOT == child1.GetKind() && (child1[0] == child2)) {
+//       retval = CreateSimpXor(child0, child2);
+//     }
+//     // ITE (x, y, !y) == x IFF y.  I think other cases are covered
+//     // by XOR/IFF optimizations
+//     else if (NOT == child2.GetKind() && (child2[0] == child1)) {
+//       retval = CreateSimpXor(CreateSimpNot(child0), child2);
+//     }
+    else {
+      retval = CreateNode(ITE, child0, child1, child2);
+    }
+
+    if (_trace_simpbool) {
+      cout << "returns " << retval << endl;
+    }
+
+    return retval;
+  }
+} // BEEV namespace
diff --git a/stp/AST/ToCNF.cpp b/stp/AST/ToCNF.cpp
new file mode 100644
index 00000000..2a18b3f5
--- /dev/null
+++ b/stp/AST/ToCNF.cpp
@@ -0,0 +1,506 @@
+/********************************************************************
+ * AUTHORS: David L. Dill, Vijay Ganesh 
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+// THEORY: This code translates an arbitrary Boolean DAG, generated by
+// the BitBlast.cpp, to an equi-satisfiable CNF formula.  There are
+// four kinds of variables in the CNF formula: (1) propositional
+// variables from the original formula; (2) BVGETBIT formulas from the
+// original formula (a precondition is that the BVGETBIT can only be
+// applied to bitvector-valued variables, array reads, or
+// uninterpreted functions); (3) TRUE; or (4) representative variables
+// (see below).  Each literal in the CNF formula is one of these or
+// its negation.  
+
+// It is convenient (though not perfectly efficient) to be able to add
+// TRUE and FALSE constants to clauses, which is not allowed in CNF.
+// So, there is a "dummy variable" representing TRUE, which is used in
+// its place (so FALSE is represented by the negation of the dummy
+// var).  The CNF formula has a unit clause containing this dummy
+// variable, so that any satisfying assignment must make the dummy var
+// TRUE.
+
+// Every sub-formula of the input formula has a "representative
+// literal."  A truth assignment satisfies the CNF formula iff the
+// restriction of that assignment to the original variables satisfies
+// the original formula, AND the rep lits have the same truth values
+// as the subformulas they represent in the original formula.  In the
+// trivial cases, the representative literal is the input variable, or
+// dummy true var, or its negation.  Representative literals may be
+// negated variables -- essentially, only AND formulas are translated,
+// and everything else is handled by rewriting or negating formulas.
+// The representative for (NOT alpha) is the negation of the
+// representative for alpha.
+
+// The translation is performed by ToCNF_int, which traverses the original
+// formula.  ToCNF adds clauses that constrain the representative variables
+// to be equal to the truth values of the formulas they represent.
+// ToCNF always returns a literal whose value must be equivalent to the formula
+// it translated.  In trivial cases, this literal is a literal from the original
+// formula, or the dummy true/false literals.  If the formula is of the form
+// (not alpha), ToCNF_int negates the literal representing alpha (which may
+// itself be a negative literal) and returns it.  Otherwise, ToCNF_int assigns
+// a new rep var, adds the clauses, and returns the new var.  ToCNF_int is
+// memoized so that it doesn't assign more than one variable to a subformula,
+// and to prevent exponential numbers of redundant visits to shared subformulas.
+
+// In reality, only AND/OR/NOT formulas are translated directly.  Everything
+// else (XOR, IFF, IMPLIES) is rewritten on-the-fly into these forms.  I
+// could have done that in bit-blasting, but I thought that, in the future,
+// we might be able to translate these operations differently in different
+// contexts to optimize the CNF formula.
+
+// FIXME: Inspection of the clauses is kind of horrifying.  In
+// addition to true/false, there are duplicate literals and duplicate
+// clauses all over the place.
+#include "AST.h"
+static bool CNF_trace = false;
+namespace BEEV {
+/**  Statistics class.  Total number of variables is best tracked in
+     ToSAT.  Number of clauses is just cll.size() */
+
+class CNFstats {
+public:
+  int _num_new_rep_vars;
+  int _num_clauses;
+  
+  // constructor
+  CNFstats() : _num_new_rep_vars(0), _num_clauses(0) {}
+
+  void printStats() {
+    if(stats) {
+      cout << "ToCNF statistics:" << endl;
+      cout << "Number of new representative variables: "
+	   << _num_new_rep_vars << endl;
+      cout << "Number of new clauses: "
+	   << _num_clauses << endl;
+    }
+  }
+
+};
+
+
+/** This class contains private data and function members for the
+    CNF conversion */
+class CNFMgr {
+
+  friend class BeevMgr;
+
+public:    
+
+  // Needed in the body of BeevMgr::ToCNF.  It's not visible outside
+  // this file, though.
+  ASTNode dummy_true_var;
+
+  // CNF Pre-pass
+  ASTNodeMap ToCNFPrePassMemo;
+
+  // CNF Memo Table.
+  ASTNodeMap CNFMemo;
+
+
+private:
+
+  // Pointer back to BeevMgr with the node tables, etc.
+  BeevMgr *bm;
+  
+  // For ToCNF conversion.  This holds a dummy variable representing
+  // "True".  It is added as a unit clause, so that it will be assigned
+  // to true and propagated immediately by any CNF solver.
+
+  ASTNode dummy_false_var;	// not of dummy_true_var
+
+  CNFstats stats;
+
+  // constructor
+  CNFMgr(BeevMgr *bmgr)
+  {
+    bm = bmgr;
+
+    // Dummy variable so TRUE can be a literal.
+    dummy_true_var = bm->CreateSymbol("*TrueDummy*");
+    dummy_false_var = bm->CreateSimpNot(dummy_true_var);
+  }
+  
+  // Returns true iff result has been memoized.
+  // if it returns true, result is returned in by-ref parameter "result"
+  // Consider just putitng this in-line.
+  bool CNFIsMemoized(ASTNode &form, ASTNode &result)
+  {
+    ASTNodeMap::iterator it = CNFMemo.find(form);
+    if (it != CNFMemo.end()) {
+      result = it->second;  //already there. Just return it.
+      return true;
+    }
+    else {
+      return false;
+    }
+  }
+
+
+  // Convert a big XOR to a bunch of AND/ORs.  Assumes subformulas have
+  // already been converted.
+  ASTNode convertXORs(ASTVec children)
+  {
+    ASTNode accum = children[0];
+    ASTVec::iterator itend = children.end();
+    for (ASTVec::iterator it = children.begin()+1; it < itend; it++) {
+      // a XOR b -> (a | b) & (!a | !b)
+
+      // For each XOR node with k children, creates approximately
+      // 5*(k-1) nodes. AND + 2 OR + 2 NOT.
+
+      ASTNode or1 = bm->CreateNode(OR, accum, *it);
+      ASTNode or2 = bm->CreateNode(OR, bm->CreateSimpNot(accum), bm->CreateSimpNot(*it));
+      accum = bm->CreateNode(AND, or1, or2);
+      
+    }
+    
+    return accum;
+  }
+
+
+  // Do preliminary transformations on bitblasted formula to make 
+  // CNF conversion easier.
+  // Converts XORs to AND/OR form.
+  ASTNode ToCNFPrePass(const ASTNode &form)
+  {
+
+    // Check memo table
+    ASTNodeMap::iterator mem_it = ToCNFPrePassMemo.find(form);
+    if (mem_it != ToCNFPrePassMemo.end()) {
+      return mem_it->second;
+    }
+    
+    ASTNode result;
+
+    ASTVec new_children;
+    ASTVec::const_iterator endit = form.end();
+    for (ASTVec::const_iterator it = form.begin(); it != endit; it++) {
+      ASTNode ch = ToCNFPrePass(*it);
+      new_children.push_back(ch);
+    }
+
+    Kind k = form.GetKind();
+
+    switch (k) {
+    case FALSE: 
+    case TRUE:
+    case SYMBOL: 
+    case BVGETBIT: {
+      result = form;
+      break;
+    }
+    case XOR: {
+      // convertXORs can only be called once per XOR node.
+      result = convertXORs(new_children);
+
+      // cout << "convertXORs num args: "  << new_children.size() << endl;
+      // temporary node for node count.
+      // ASTNode tmp = bm->CreateNode(XOR, new_children );
+      // cout << "convertXORs size of [" << form.GetNodeNum() << "] " << bm->NodeSize(form, true) << endl;
+      // cout << "convertXORs before size: " << bm->NodeSize(tmp, true) << endl;
+      // cout << "convertXORs after size: " << bm->NodeSize(result, true) << endl;
+      break;
+    }
+    default: {
+      // Be cautious about using CreateSimpForm -- It makes big xors!
+      result = bm->CreateNode(k, new_children);
+    }
+    }
+
+//     cout << "================" << endl
+// 	 << "ToCNFPrePass:" << form << endl
+// 	 << "----------------" << endl
+// 	 << "ToCNFPrePass Result:" << result << endl;
+    
+    return (ToCNFPrePassMemo[form] = result);
+    
+  }
+
+  // Memoize and return formula value
+  ASTNode CNFMemoize(ASTNode& form, ASTNode result)
+  {
+    CNFMemo[form] = result;
+    return result;    
+  }
+
+ 
+  // Create a representative variable for an original formula.
+  // The convention is that the variable will have the same truth
+  // value as the expression numbered "num."  
+  ASTNode RepLit(const char *name, int exprnum)
+  {
+    // FIXME: can this be done more efficiently with string type?
+    ostringstream oss;
+    oss << name << "{" << exprnum << "}";
+    ASTNode t = bm->CreateSymbol(oss.str().c_str());
+
+    // Track how many we're generating.
+    stats._num_new_rep_vars++;
+    
+    //ASTNode is of type BOOLEAN <==> ((indexwidth=0)&&(valuewidth=0))
+    t.SetIndexWidth(0);
+    t.SetValueWidth(0);
+    return t;
+  }
+
+  // Handle the cases where it's necessary to do n children.
+  // This code translates ANDs, and converts NAND, NOR, OR by negating
+  // the inputs or outputs of the AND.
+  ASTNode ToCNF_AndLike(Kind k, BeevMgr::ClauseList& cll, ASTNode form)
+  {  
+    // Build vectors of positive and negative rep lits for children
+    ASTVec kidlits(0);
+    ASTVec negkidlits(0);
+    ASTVec::const_iterator kids_end = form.end();
+    for (ASTVec::const_iterator it = form.begin(); it != kids_end; it++) {
+      ASTNode kidreplit = ToCNF_int(cll, *it);
+      kidlits.push_back(kidreplit);
+      negkidlits.push_back(bm->CreateSimpNot(kidreplit));
+    }
+    
+    ASTNode replit;
+    // translate the AND, negating inputs as appropriate.
+    if (k == OR || k == NOR) {
+      replit = ToCNF_AND(cll, form.GetNodeNum(), negkidlits, kidlits);
+    }
+    else {
+      replit = ToCNF_AND(cll, form.GetNodeNum(), kidlits, negkidlits);
+    }
+    
+    // Reduce NAND/OR to AND by negating result.
+    if (k == NAND || k == OR) {
+      return CNFMemoize(form, bm->CreateSimpNot(replit));
+    }
+    else {
+      return CNFMemoize(form, replit);
+    }
+  }
+
+  ASTNode ToCNF_AND(BeevMgr::ClauseList& cll, int nodenum, ASTVec& kidlits, ASTVec& negkidlits)
+  {
+    // Translate an AND, given rep lits for children
+    // Build clauses for (replit <-> a AND b AND c)
+
+    ASTNode replit = RepLit("cnf", nodenum);
+    ASTNode notreplit = bm->CreateSimpNot(replit);
+
+    if (CNF_trace) {
+      cout << "Translating AND" << endl << "-----------------------" << endl
+	   << "Rep lit =" <<  replit << endl
+	   << "-----------------------";
+    }
+
+    // (a AND b AND c -> replit) ==   (~a OR ~b OR ~c OR replit)
+    BeevMgr::ClausePtr clp = new ASTVec(negkidlits);
+    clp->push_back(replit);
+
+    if (CNF_trace) {
+      LispPrintVec(cout, *clp, 0);
+      cout << endl << "-----------------------" << endl;
+    }
+
+    cll.push_back(clp);
+
+    // (replit -> (a AND b AND c)) == 
+    //     (~replit OR a) AND (~replit OR b) AND (~replit OR c)
+    ASTVec::const_iterator kidlits_end = kidlits.end();
+    for (ASTVec::iterator it = kidlits.begin(); it != kidlits_end; it++) {
+      clp = new ASTVec();
+      clp->push_back(notreplit);
+      clp->push_back(*it);
+
+      if (CNF_trace) {
+	LispPrintVec(cout, *clp, 0);
+	cout << endl << "-----------------------" << endl;
+      }
+
+      cll.push_back(clp);
+    }
+
+    return replit;
+  }
+
+public:
+   
+  /** Builds clauses globally and returns a literal.
+      The literal can be a leaf from the expression, or a rep var
+      made up to represent the subexpression. */
+  ASTNode ToCNF_int(BeevMgr::BeevMgr::ClauseList& cll, ASTNode form) {
+    // FIXME: assert indexwidth= 0, valuewidth = 1
+
+    // FIXME:  rewriting is top-down, which is not efficient.
+    // It rewrites the top node of the tree, then does the children.
+    // Either rewrite in a separate pass, or translate children
+    // before rewriting somehow (might require handling rep lits
+    // as though they were real lits, which is probably ok).
+    
+    // Return memoized value if seen before.
+    ASTNode result;
+    Kind k = form.GetKind();
+
+    if (CNFIsMemoized(form, result)) {
+      return result;
+    }
+
+    switch (k) {
+      // handle the trivial cases here.  If none apply, call the
+      // heavy-duty function.  If a constant or literal, just return
+      // without creating a clause.
+    case FALSE: {
+      result = dummy_false_var;
+      break;
+    }
+    case TRUE: {
+      result =  dummy_true_var;
+      break;
+    }
+    case SYMBOL: 
+    case BVGETBIT: {
+      result = form;
+      break;
+    }
+      
+    case NOT: {
+	ASTNode replit = ToCNF_int(cll, form[0]);
+	result = bm->CreateSimpNot(replit);
+      break;
+    }
+      
+      // For these, I can't think of anything better than expanding into ANDs/ORs
+    case ITE: {
+      // (ite a b c) == (~a OR b) AND (a OR c)
+      ASTNode l = bm->CreateNode(OR, bm->CreateSimpNot(form[0]), form[1]);
+      ASTNode r = bm->CreateNode(OR, form[0], form[2]);
+      ASTNode andor = bm->CreateNode(AND, l, r);
+      if (CNF_trace) {
+	cout << "Rewriting " << form << endl
+	     << "to" << andor << endl
+	     << "-------------------" << endl;
+      }
+      result = ToCNF_int(cll, andor);
+      break;
+    }
+    case IMPLIES: {
+      // Just rewrite into (~a OR b)
+      ASTNode l = bm->CreateSimpNot(form[0]);
+      ASTNode andor = bm->CreateNode(OR, l, form[1]);
+      if (CNF_trace) {
+	cout << "Rewriting " << form << endl
+	     << "to" << andor << endl
+	     << "-------------------" << endl;
+      }
+      result = ToCNF_int(cll, andor);
+      break;
+    }
+    case XOR: {
+      FatalError("ToCNF_int: XORs should have been converted to AND/OR by this point.");
+      break;
+    }
+
+    case IFF: {
+      FatalError("BitBlaster failed to eliminate all IFFs.");
+      break;
+    }
+    
+    case AND:
+    case OR:
+    case NOR:
+    case NAND: {
+      result = ToCNF_AndLike(k, cll, form);
+      break;
+    }
+    default:
+      cerr << "ToCNF: can't handle this kind: " << k << endl;
+      FatalError("");
+    }
+
+    if (CNF_trace) {
+      cout << "ToCNF_int: Literal " << result << " represents formula " <<
+	form << endl << "---------------" << endl;
+    }
+
+    return CNFMemoize(form, result);
+  } //end of ToCNF_int()
+
+
+}; // end of CNFMgr class
+
+  // These are the bodies of functions in the BeevMgr that are part of
+  // the public interface.
+
+  // Debug printing function.
+  void BeevMgr::PrintClauseList(ostream& os, BeevMgr::ClauseList& cll)
+  {
+    int num_clauses = cll.size();
+    os << "Clauses: " << endl << "=========================================" << endl;
+    for(int i=0; i < num_clauses; i++) {
+      os << "Clause " << i << endl
+	 << "-------------------------------------------" << endl;
+      LispPrintVec(os, *cll[i], 0);
+      os << endl
+	 << "-------------------------------------------" << endl;
+    }
+  }
+
+  void BeevMgr::DeleteClauseList(BeevMgr::ClauseList *cllp)
+  {
+    BeevMgr::ClauseList::const_iterator iend = cllp->end();
+    for (BeevMgr::ClauseList::const_iterator i = cllp->begin(); i < iend; i++) {
+      delete *i;
+    }
+    delete cllp;
+  }
+
+  // Top level conversion function
+  BeevMgr::ClauseList *BeevMgr::ToCNF(const ASTNode& form) 
+  {
+
+    // FIXME: This is leaked as well.
+    CNFMgr *cm = new CNFMgr(this);
+   
+    // Prepass
+    ASTNode form1 = cm->ToCNFPrePass(form);
+
+    // cout << "Number of nodes after ToCNFPrePass" << NodeSize(form1, true) << endl;
+
+    // cout << "ToCNF: After ToCNFPrePass" << form1 << endl;
+
+    // FIXME: Assert CNFMemo is empty.
+
+    // The clause list we will be building up.
+    // FIXME: This is never freed.
+    ClauseList *cllp = new ClauseList();
+
+    BeevMgr::ClausePtr dummy_true_unit_clause = new ASTVec();
+    dummy_true_unit_clause->push_back(cm->dummy_true_var);
+    cllp->push_back(dummy_true_unit_clause);
+
+    // This is where the translation happens.
+    ASTNode toplit = cm->ToCNF_int(*cllp, form1);
+
+    // Add the top literal as a unit clause, since it must
+    // be true when original formula is satsfied.
+    BeevMgr::ClausePtr clp = new ASTVec(0);
+    clp->push_back(toplit);
+    cllp->push_back(clp);
+
+    cm->stats._num_clauses = cllp->size();
+    cm->stats.printStats();
+
+    RepLitMap = cm->CNFMemo;	// Save memo table for debugging (DD 1/13/07).
+
+    cm->CNFMemo.clear();   // Important to do this so nodes get freed.
+
+    delete cm;
+
+    return cllp;
+  }
+
+} // end namespace
diff --git a/stp/AST/ToSAT.cpp b/stp/AST/ToSAT.cpp
new file mode 100644
index 00000000..7a164c9c
--- /dev/null
+++ b/stp/AST/ToSAT.cpp
@@ -0,0 +1,1385 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+#include "AST.h"
+#include "ASTUtil.h"
+#include "../simplifier/bvsolver.h"
+#include <math.h>
+
+
+namespace BEEV {
+  /* FUNCTION: lookup or create a new MINISAT literal
+   * lookup or create new MINISAT Vars from the global MAP
+   * _ASTNode_to_SATVar.
+   */
+  const MINISAT::Var BeevMgr::LookupOrCreateSATVar(MINISAT::Solver& newS, const ASTNode& n) {  
+    ASTtoSATMap::iterator it;  
+    MINISAT::Var v;
+    
+    //look for the symbol in the global map from ASTNodes to ints. if
+    //not found, create a S.newVar(), else use the existing one.
+    if((it = _ASTNode_to_SATVar.find(n)) == _ASTNode_to_SATVar.end()) {
+      v = newS.newVar();
+      _ASTNode_to_SATVar[n] = v;	
+      
+      //ASSUMPTION: I am assuming that the newS.newVar() call increments v
+      //by 1 each time it is called, and the initial value of a
+      //MINISAT::Var is 0.
+      _SATVar_to_AST.push_back(n);
+    }
+    else
+      v = it->second;
+    return v;
+  }
+  
+  /* FUNCTION: convert ASTClauses to MINISAT clauses and solve.
+   * Accepts ASTClauses and converts them to MINISAT clauses. Then adds
+   * the newly minted MINISAT clauses to the local SAT instance, and
+   * calls solve(). If solve returns unsat, then stop and return
+   * unsat. else continue.
+   */  
+  // FIXME: Still need to deal with TRUE/FALSE in clauses!
+ bool BeevMgr::toSATandSolve(MINISAT::Solver& newS, BeevMgr::ClauseList& cll)
+ {
+    CountersAndStats("SAT Solver");
+
+    //iterate through the list (conjunction) of ASTclauses cll
+    BeevMgr::ClauseList::const_iterator i = cll.begin(), iend = cll.end();
+    
+    if(i == iend)
+      FatalError("toSATandSolve: Nothing to Solve",ASTUndefined);
+    
+    //turnOffSubsumption
+    newS.turnOffSubsumption();
+
+    // (*i) is an ASTVec-ptr which denotes an ASTclause
+    for(; i!=iend; i++) {    
+      //Clause for the SATSolver
+      MINISAT::vec<MINISAT::Lit> satSolverClause;
+      
+      //now iterate through the internals of the ASTclause itself
+      ASTVec::const_iterator j = (*i)->begin(), jend = (*i)->end();
+      //j is a disjunct in the ASTclause (*i)
+      for(;j!=jend;j++) {
+
+	bool negate = (NOT == j->GetKind()) ? true : false;		
+	ASTNode n = negate ? (*j)[0] : *j;
+	
+	//Lookup or create the MINISAT::Var corresponding to the Booelan
+	//ASTNode Variable, and push into sat Solver clause
+	MINISAT::Var v = LookupOrCreateSATVar(newS,n);
+	MINISAT::Lit l(v, negate);
+	satSolverClause.push(l);
+      }
+      newS.addClause(satSolverClause);
+      // clause printing.
+      // (printClause<MINISAT::vec<MINISAT::Lit> >)(satSolverClause);
+      // cout << " 0 ";
+      // cout << endl;
+      
+      if(newS.okay()) {
+	continue;
+      }
+      else {
+	PrintStats(newS.stats);
+	return false;
+      }
+      
+      if(!newS.simplifyDB(false)) {
+      	PrintStats(newS.stats);
+      	return false;
+      }
+    }
+
+    // if input is UNSAT return false, else return true    
+    if(!newS.simplifyDB(false)) {
+      PrintStats(newS.stats);
+      return false;
+    }
+    
+    //PrintActivityLevels_Of_SATVars("Before SAT:",newS);
+    //ChangeActivityLevels_Of_SATVars(newS);
+    //PrintActivityLevels_Of_SATVars("Before SAT and after initial bias:",newS); 
+    newS.solve();
+    //PrintActivityLevels_Of_SATVars("After SAT",newS);
+
+    PrintStats(newS.stats);
+    if (newS.okay())
+      return true;
+    else
+      return false;
+  }
+
+  // GLOBAL FUNCTION: Prints statistics from the MINISAT Solver   
+  void BeevMgr::PrintStats(MINISAT::SolverStats& s) {
+    if(!stats)
+      return;
+    double  cpu_time = MINISAT::cpuTime();
+    MINISAT::int64   mem_used = MINISAT::memUsed();
+    reportf("restarts              : %"I64_fmt"\n", s.starts);
+    reportf("conflicts             : %-12"I64_fmt"   (%.0f /sec)\n", s.conflicts   , s.conflicts   /cpu_time);
+    reportf("decisions             : %-12"I64_fmt"   (%.0f /sec)\n", s.decisions   , s.decisions   /cpu_time);
+    reportf("propagations          : %-12"I64_fmt"   (%.0f /sec)\n", s.propagations, s.propagations/cpu_time);
+    reportf("conflict literals     : %-12"I64_fmt"   (%4.2f %% deleted)\n", 
+	    s.tot_literals, 
+	    (s.max_literals - s.tot_literals)*100 / (double)s.max_literals);
+    if (mem_used != 0) reportf("Memory used           : %.2f MB\n", mem_used / 1048576.0);
+    reportf("CPU time              : %g s\n", cpu_time);
+  }
+  
+  // Prints Satisfying assignment directly, for debugging.
+  void BeevMgr::PrintSATModel(MINISAT::Solver& newS) {
+    if(!newS.okay())
+      FatalError("PrintSATModel: NO COUNTEREXAMPLE TO PRINT",ASTUndefined);
+    // FIXME: Don't put tests like this in the print functions.  The print functions
+    // should print unconditionally.  Put a conditional around the call if you don't 
+    // want them to print
+    if(!(stats && print_nodes))
+      return;
+
+    int num_vars = newS.nVars();
+    cout << "Satisfying assignment: " << endl;
+    for (int i = 0; i < num_vars; i++) {
+      if (newS.model[i] == MINISAT::l_True) {
+	ASTNode s = _SATVar_to_AST[i];
+	cout << s << endl;
+      }
+      else if (newS.model[i] == MINISAT::l_False) {
+	ASTNode s = _SATVar_to_AST[i];
+	cout << CreateNode(NOT, s) << endl;
+      }
+    }
+  }
+
+
+  // Looks up truth value of ASTNode SYMBOL in MINISAT satisfying assignment.
+  // Returns ASTTrue if true, ASTFalse if false or undefined.
+  ASTNode BeevMgr::SymbolTruthValue(MINISAT::Solver &newS, ASTNode form) 
+  {
+    MINISAT::Var satvar = _ASTNode_to_SATVar[form];
+    if (newS.model[satvar] == MINISAT::l_True) {
+      return ASTTrue;
+    }
+    else if (newS.model[satvar] == MINISAT::l_False){
+      // False
+      return ASTFalse;
+    }
+    else {
+      return (rand() > 4096) ? ASTTrue : ASTFalse; 
+    }
+  }
+
+
+  // This function is for debugging problems with BitBlast and especially
+  // ToCNF. It evaluates the bit-blasted formula in the satisfying
+  // assignment.  While doing that, it checks that every subformula has
+  // the same truth value as its representative literal, if it has one.
+  // If this condition is violated, it halts immediately (on the leftmost
+  // lowest term).
+  // Use CreateSimpForm to evaluate, even though it's expensive, so that
+  // we can use the partial truth assignment.
+  ASTNode BeevMgr::CheckBBandCNF(MINISAT::Solver& newS, ASTNode form)
+  {
+    // Clear memo table (in case newS has changed).
+    CheckBBandCNFMemo.clear();
+    // Call recursive version that does the work.
+    return CheckBBandCNF_int(newS, form);
+  }
+
+  // Recursive body CheckBBandCNF
+  // FIXME:  Modify this to just check if result is true, and print mismatch 
+  // if not.   Might have a trace flag for the other stuff.
+  ASTNode BeevMgr::CheckBBandCNF_int(MINISAT::Solver& newS, ASTNode form)
+  {
+
+    //    cout << "++++++++++++++++" << endl << "CheckBBandCNF_int form = " <<
+    //      form << endl;
+  
+    ASTNodeMap::iterator memoit = CheckBBandCNFMemo.find(form);
+    if (memoit != CheckBBandCNFMemo.end()) {
+      // found it.  Return memoized value.
+      return memoit->second;
+    }
+
+    ASTNode result;		// return value, to memoize.
+
+    Kind k = form.GetKind();
+    switch (k) {
+    case TRUE:
+    case FALSE: {
+      return form;
+      break;
+    }
+    case SYMBOL: 
+    case BVGETBIT:  {
+      // Look up the truth value
+      // ASTNode -> Sat -> Truthvalue -> ASTTrue or ASTFalse;
+      // FIXME: Could make up a fresh var in undefined case.
+
+      result = SymbolTruthValue(newS, form);
+
+      cout << "================" << endl << "Checking BB formula:" << form << endl;
+      cout << "----------------" << endl << "Result:" << result << endl;
+
+      break;
+    }
+    default: {
+      // Evaluate the children recursively.
+      ASTVec eval_children;
+      ASTVec ch = form.GetChildren();
+      ASTVec::iterator itend = ch.end();
+      for(ASTVec::iterator it = ch.begin(); it < itend; it++) {
+	eval_children.push_back(CheckBBandCNF_int(newS, *it));
+      }
+      result = CreateSimpForm(k, eval_children);
+
+      cout << "================" << endl << "Checking BB formula:" << form << endl;
+      cout << "----------------" << endl << "Result:" << result << endl;
+
+      ASTNode replit_eval;
+      // Compare with replit, if there is one.
+      ASTNodeMap::iterator replit_it = RepLitMap.find(form);
+      if (replit_it != RepLitMap.end()) {
+	ASTNode replit = RepLitMap[form];
+	// Replit is symbol or not symbol.
+	if (SYMBOL == replit.GetKind()) {
+	  replit_eval = SymbolTruthValue(newS, replit);
+	}
+	else {
+	  // It's (NOT sym).  Get value of sym and complement.
+	  replit_eval = CreateSimpNot(SymbolTruthValue(newS, replit[0]));
+	}
+
+	cout << "----------------" << endl << "Rep lit: " << replit << endl;
+	cout << "----------------" << endl << "Rep lit value: " << replit_eval << endl;
+
+	if (result != replit_eval) {
+	  // Hit the panic button.
+	  FatalError("Truth value of BitBlasted formula disagrees with representative literal in CNF.");
+	}
+      }
+      else {
+	cout << "----------------" << endl << "No rep lit" << endl;
+      }
+
+    }
+    }
+
+    return (CheckBBandCNFMemo[form] = result);
+  }
+
+  /*FUNCTION: constructs counterexample from MINISAT counterexample
+   * step1 : iterate through MINISAT counterexample and assemble the
+   * bits for each AST term. Store it in a map from ASTNode to vector
+   * of bools (bits).
+   *
+   * step2: Iterate over the map from ASTNodes->Vector-of-Bools and
+   * populate the CounterExampleMap data structure (ASTNode -> BVConst)
+   */
+  void BeevMgr::ConstructCounterExample(MINISAT::Solver& newS) {
+    //iterate over MINISAT counterexample and construct a map from AST
+    //terms to vector of bools. We need this iteration step because
+    //MINISAT might return the various bits of a term out of
+    //order. Therfore, we need to collect all the bits and assemble
+    //them properly
+    
+    if(!newS.okay())
+      return;
+    if(!construct_counterexample)
+      return;    
+
+    CopySolverMap_To_CounterExample();
+    for (int i = 0; i < newS.nVars(); i++) {
+      //Make sure that the MINISAT::Var is defined
+      if (newS.model[i] != MINISAT::l_Undef) {
+	
+	//mapping from MINISAT::Vars to ASTNodes. We do not need to
+	//print MINISAT vars or CNF vars.
+	ASTNode s = _SATVar_to_AST[i];
+	
+	//assemble the counterexample here
+	if(s.GetKind() == BVGETBIT && s[0].GetKind() == SYMBOL) {
+	  ASTNode symbol = s[0];
+	  unsigned int symbolWidth = symbol.GetValueWidth();
+	  
+	  //'v' is the map from bit-index to bit-value
+	  hash_map<unsigned,bool> * v;	
+	  if(_ASTNode_to_Bitvector.find(symbol) == _ASTNode_to_Bitvector.end())
+	    _ASTNode_to_Bitvector[symbol] = new hash_map<unsigned,bool>(symbolWidth);	
+	  
+	  //v holds the map from bit-index to bit-value
+	  v = _ASTNode_to_Bitvector[symbol];
+	  
+	  //kk is the index of BVGETBIT
+	  unsigned int kk = GetUnsignedConst(s[1]); 	
+	  
+	  //Collect the bits of 'symbol' and store in v. Store in reverse order.
+	  if(newS.model[i]==MINISAT::l_True)
+	    (*v)[(symbolWidth-1) - kk] = true;
+	  else
+	    (*v)[(symbolWidth-1) - kk] = false;
+	}
+	else {	 
+	  if(s.GetKind() == SYMBOL && s.GetType() == BOOLEAN_TYPE) {
+	    const char * zz = s.GetName();
+	    //if the variables are not cnf variables then add them to the counterexample
+	    if(0 != strncmp("cnf",zz,3) && 0 != strcmp("*TrueDummy*",zz)) {
+	      if(newS.model[i]==MINISAT::l_True)
+		CounterExampleMap[s] = ASTTrue;
+	      else
+		CounterExampleMap[s] = ASTFalse;	    
+	    }
+	  }
+	}
+      }
+    }
+
+    //iterate over the ASTNode_to_Bitvector data-struct and construct
+    //the the aggregate value of the bitvector, and populate the
+    //CounterExampleMap datastructure
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),itend=_ASTNode_to_Bitvector.end();
+	it!=itend;it++) {
+      ASTNode var = it->first;      
+      //debugging
+      //cerr << var;
+      if(SYMBOL != var.GetKind())
+	FatalError("ConstructCounterExample: error while constructing counterexample: not a variable: ",var);
+
+      //construct the bitvector value
+      hash_map<unsigned,bool> * w = it->second;
+      ASTNode value = BoolVectoBVConst(w, var.GetValueWidth());      
+      //debugging
+      //cerr << value;
+
+      //populate the counterexample datastructure. add only scalars
+      //variables which were declared in the input and newly
+      //introduced variables for array reads
+      CounterExampleMap[var] = value;
+    }
+    
+    //In this loop, we compute the value of each array read, the
+    //corresponding ITE against the counterexample generated above.
+    for(ASTNodeMap::iterator it=_arrayread_ite.begin(),itend=_arrayread_ite.end();
+	it!=itend;it++){
+      //the array read
+      ASTNode arrayread = it->first;
+      ASTNode value_ite = _arrayread_ite[arrayread];
+      
+      //convert it to a constant array-read and store it in the
+      //counter-example. First convert the index into a constant. then
+      //construct the appropriate array-read and store it in the
+      //counterexample
+      ASTNode arrayread_index = TermToConstTermUsingModel(arrayread[1]);
+      ASTNode key = CreateTerm(READ,arrayread.GetValueWidth(),arrayread[0],arrayread_index);
+
+      //Get the ITE corresponding to the array-read and convert it
+      //to a constant against the model
+      ASTNode value = TermToConstTermUsingModel(value_ite);
+      //save the result in the counter_example
+      if(!CheckSubstitutionMap(key))
+	CounterExampleMap[key] = value;      
+    }
+  } //End of ConstructCounterExample
+
+  // FUNCTION: accepts a non-constant term, and returns the
+  // corresponding constant term with respect to a model. 
+  //
+  // term READ(A,i) is treated as follows:
+  //
+  //1. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
+  //1. has value in counterexample), then return the value of the
+  //1. arrayread.
+  //
+  //2. If (the boolean variable 'ArrayReadFlag' is true && ArrayRead
+  //2. doesn't have value in counterexample), then return the
+  //2. arrayread itself (normalized such that arrayread has a constant
+  //2. index)
+  //
+  //3. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
+  //3. has a value in the counterexample then return the value of the
+  //3. arrayread.
+  //
+  //4. If (the boolean variable 'ArrayReadFlag' is false) && ArrayRead
+  //4. doesn't have a value in the counterexample then return 0 as the
+  //4. value of the arrayread.
+  ASTNode BeevMgr::TermToConstTermUsingModel(const ASTNode& t, bool ArrayReadFlag) {
+    Begin_RemoveWrites = false;
+    SimplifyWrites_InPlace_Flag = false;
+    //ASTNode term = SimplifyTerm(t);
+    ASTNode term = t;
+    Kind k = term.GetKind();
+    
+
+    //cerr << "Input to TermToConstTermUsingModel: " << term << endl;
+    if(!is_Term_kind(k)) {
+      FatalError("TermToConstTermUsingModel: The input is not a term: ",term);
+    }
+    if(k == WRITE) {
+      FatalError("TermToConstTermUsingModel: The input has wrong kind: WRITE : ",term);
+    }
+    if(k == SYMBOL && BOOLEAN_TYPE == term.GetType()) {
+      FatalError("TermToConstTermUsingModel: The input has wrong kind: Propositional variable : ",term);
+    }
+
+    ASTNodeMap::iterator it1;
+    if((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end()) {
+      ASTNode val = it1->second;
+      if(BVCONST != val.GetKind()) {
+	//CounterExampleMap has two maps rolled into
+	//one. SubstitutionMap and SolverMap.
+	//
+	//recursion is fine here. There are two maps that are checked
+	//here. One is the substitutionmap. We garuntee that the value
+	//of a key in the substitutionmap is always a constant.
+	//
+	//in the SolverMap we garuntee that "term" does not occur in
+	//the value part of the map
+	if(term == val) {
+	  FatalError("TermToConstTermUsingModel: The input term is stored as-is "
+		     "in the CounterExample: Not ok: ",term);    
+	}
+	return TermToConstTermUsingModel(val,ArrayReadFlag);
+      }
+      else {
+	return val;
+      }
+    }
+
+    ASTNode output;
+    switch(k) {
+    case BVCONST:
+      output = term;
+      break;
+    case SYMBOL: {
+      if(term.GetType() == ARRAY_TYPE) {
+	return term;
+      }
+
+      //when all else fails set symbol values to some constant by
+      //default. if the variable is queried the second time then add 1
+      //to and return the new value.
+      ASTNode zero = CreateZeroConst(term.GetValueWidth());
+      output = zero;
+      break;    
+    }
+    case READ: {      
+      ASTNode arrName = term[0];
+      ASTNode index = term[1];
+      if(0 == arrName.GetIndexWidth()) {
+	FatalError("TermToConstTermUsingModel: array has 0 index width: ",arrName);
+      }
+      
+      //READ over a WRITE
+      if(WRITE == arrName.GetKind()) {
+	ASTNode wrtterm = Expand_ReadOverWrite_UsingModel(term, ArrayReadFlag);
+	if(wrtterm == term) {
+	  FatalError("TermToConstTermUsingModel: Read_Over_Write term must be expanded into an ITE", term);
+	}
+	ASTNode rtterm = TermToConstTermUsingModel(wrtterm,ArrayReadFlag);	
+	return rtterm;
+      } 
+      //READ over an ITE
+      if(ITE == arrName.GetKind()) {
+	arrName = TermToConstTermUsingModel(arrName,ArrayReadFlag);
+      }
+
+      ASTNode modelentry;
+      if(CounterExampleMap.find(index) != CounterExampleMap.end()) {	
+	//index has a const value in the CounterExampleMap
+	ASTNode indexVal = CounterExampleMap[index];
+	modelentry = CreateTerm(READ, arrName.GetValueWidth(), arrName, indexVal);
+      }
+      else { 
+	//index does not have a const value in the CounterExampleMap. compute it.
+	ASTNode indexconstval = TermToConstTermUsingModel(index,ArrayReadFlag);
+	//update model with value of the index
+	//CounterExampleMap[index] = indexconstval;
+	modelentry = CreateTerm(READ,arrName.GetValueWidth(), arrName,indexconstval);	
+      }
+      //modelentry is now an arrayread over a constant index
+      BVTypeCheck(modelentry);
+      
+      //if a value exists in the CounterExampleMap then return it
+      if(CounterExampleMap.find(modelentry) != CounterExampleMap.end()) {
+	output = TermToConstTermUsingModel(CounterExampleMap[modelentry],ArrayReadFlag);
+      }
+      else if(ArrayReadFlag) {
+	//return the array read over a constantindex
+	output = modelentry;
+      }
+      else {
+	//when all else fails set symbol values to some constant by
+	//default. if the variable is queried the second time then add 1
+	//to and return the new value.
+	ASTNode zero = CreateZeroConst(modelentry.GetValueWidth());
+	output = zero;
+      }
+      break;
+    }
+    case ITE: {
+      ASTNode condcompute = ComputeFormulaUsingModel(term[0]);
+      if(ASTTrue == condcompute) {
+	output = TermToConstTermUsingModel(term[1],ArrayReadFlag);
+      }
+      else if(ASTFalse == condcompute) {
+	output = TermToConstTermUsingModel(term[2],ArrayReadFlag);
+      } 
+      else {
+	cerr << "TermToConstTermUsingModel: termITE: value of conditional is wrong: " << condcompute << endl; 
+	FatalError(" TermToConstTermUsingModel: termITE: cannot compute ITE conditional against model: ",term);
+      }
+      break;
+    }
+    default: {
+      ASTVec c = term.GetChildren();
+      ASTVec o;
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	ASTNode ff = TermToConstTermUsingModel(*it,ArrayReadFlag);
+	o.push_back(ff);
+      }
+      output = CreateTerm(k,term.GetValueWidth(),o);
+      //output is a CONST expression. compute its value and store it
+      //in the CounterExampleMap
+      ASTNode oo = BVConstEvaluator(output);
+      //the return value
+      output = oo;
+      break;
+    }
+    }
+
+    //when this flag is false, we should compute the arrayread to a
+    //constant. this constant is stored in the counter_example
+    //datastructure
+    if(!ArrayReadFlag) {
+      CounterExampleMap[term] = output;
+    }
+    
+    //cerr << "Output to TermToConstTermUsingModel: " << output << endl;
+    return output;
+  } //End of TermToConstTermUsingModel
+
+  //Expands read-over-write by evaluating (readIndex=writeIndex) for
+  //every writeindex until, either it evaluates to TRUE or all
+  //(readIndex=writeIndex) evaluate to FALSE
+  ASTNode BeevMgr::Expand_ReadOverWrite_UsingModel(const ASTNode& term, bool arrayread_flag) {
+    if(READ != term.GetKind() && 
+       WRITE != term[0].GetKind()) {
+      FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+    }
+
+    ASTNode output;
+    ASTNodeMap::iterator it1;    
+    if((it1 = CounterExampleMap.find(term)) != CounterExampleMap.end()) {
+      ASTNode val = it1->second;
+      if(BVCONST != val.GetKind()) {
+	//recursion is fine here. There are two maps that are checked
+	//here. One is the substitutionmap. We garuntee that the value
+	//of a key in the substitutionmap is always a constant.
+	if(term == val) {
+	  FatalError("TermToConstTermUsingModel: The input term is stored as-is "
+		     "in the CounterExample: Not ok: ",term);    
+	}
+	return TermToConstTermUsingModel(val,arrayread_flag);
+      }
+      else {
+	return val;
+      }
+    }
+
+    unsigned int width = term.GetValueWidth();
+    ASTNode writeA = ASTTrue; 
+    ASTNode newRead = term;
+    ASTNode readIndex = TermToConstTermUsingModel(newRead[1],false);
+    //iteratively expand read-over-write, and evaluate against the
+    //model at every iteration
+    do {
+      ASTNode write = newRead[0];
+      writeA = write[0];
+      ASTNode writeIndex = TermToConstTermUsingModel(write[1],false);
+      ASTNode writeVal = TermToConstTermUsingModel(write[2],false);
+      
+      ASTNode cond = ComputeFormulaUsingModel(CreateSimplifiedEQ(writeIndex,readIndex));
+      if(ASTTrue == cond) {
+	//found the write-value. return it
+	output = writeVal;
+	CounterExampleMap[term] = output;
+	return output;
+      }
+
+      newRead = CreateTerm(READ,width,writeA,readIndex);
+    } while(READ == newRead.GetKind() && WRITE == newRead[0].GetKind());
+    
+    output = TermToConstTermUsingModel(newRead,arrayread_flag);
+        
+    //memoize
+    CounterExampleMap[term] = output;
+    return output;  
+  } //Exand_ReadOverWrite_To_ITE_UsingModel()
+
+  /* FUNCTION: accepts a non-constant formula, and checks if the
+   * formula is ASTTrue or ASTFalse w.r.t to a model
+   */
+  ASTNode BeevMgr::ComputeFormulaUsingModel(const ASTNode& form) {
+    ASTNode in = form;
+    Kind k = form.GetKind();
+    if(!(is_Form_kind(k) && BOOLEAN_TYPE == form.GetType())) {
+      FatalError(" ComputeConstFormUsingModel: The input is a non-formula: ", form);
+    }
+
+    //cerr << "Input to ComputeFormulaUsingModel:" << form << endl;
+    ASTNodeMap::iterator it1;
+    if((it1 = ComputeFormulaMap.find(form)) != ComputeFormulaMap.end()) {
+      ASTNode res = it1->second;
+      if(ASTTrue == res || ASTFalse == res) {
+	return res;
+      }
+      else {
+	FatalError("ComputeFormulaUsingModel: The value of a formula must be TRUE or FALSE:", form);
+      }
+    }
+    
+    ASTNode t0,t1;
+    ASTNode output = ASTFalse;
+    switch(k) {
+    case TRUE:
+    case FALSE:
+      output = form;      
+      break;
+    case SYMBOL:
+      if(BOOLEAN_TYPE != form.GetType())
+	FatalError(" ComputeFormulaUsingModel: Non-Boolean variables are not formulas",form);
+      if(CounterExampleMap.find(form) != CounterExampleMap.end()) {
+	ASTNode counterexample_val = CounterExampleMap[form];
+	if(!VarSeenInTerm(form,counterexample_val)) {
+	  output = ComputeFormulaUsingModel(counterexample_val);
+	}
+	else {
+	  output = counterexample_val;
+	}
+      }
+      else
+	output = ASTFalse;
+      break;  
+    case EQ:
+    case NEQ:
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVSLT:
+    case BVSLE:
+    case BVSGT:
+    case BVSGE:
+      //convert form[0] into a constant term
+      t0 = TermToConstTermUsingModel(form[0],false);
+      //convert form[0] into a constant term
+      t1 = TermToConstTermUsingModel(form[1],false);
+      output = BVConstEvaluator(CreateNode(k,t0,t1));
+      
+      //evaluate formula to false if bvdiv execption occurs while
+      //counterexample is being checked during refinement.
+      if(bvdiv_exception_occured && 
+	 counterexample_checking_during_refinement) {
+	output = ASTFalse;
+      }
+      break;   
+    case NAND: {
+      ASTNode o = ASTTrue;
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++)
+	if(ASTFalse == ComputeFormulaUsingModel(*it)) {
+	  o = ASTFalse;
+	  break;
+	}      
+      if(o == ASTTrue) 
+	output = ASTFalse;
+      else 
+	output = ASTTrue;
+      break;
+    }
+    case NOR: {
+      ASTNode o = ASTFalse;
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++)
+	if(ASTTrue == ComputeFormulaUsingModel(*it)) {
+	  o = ASTTrue;
+	  break;
+	}
+      if(o == ASTTrue) 
+	output = ASTFalse;
+      else 
+	output = ASTTrue;
+      break;
+    }
+    case NOT:
+      if(ASTTrue == ComputeFormulaUsingModel(form[0]))
+	output = ASTFalse;
+      else
+	output = ASTTrue;
+      break;
+    case OR:
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++) 
+	if(ASTTrue == ComputeFormulaUsingModel(*it))
+	  output = ASTTrue;
+      break;
+    case AND:
+      output = ASTTrue;
+      for(ASTVec::const_iterator it=form.begin(),itend=form.end();it!=itend;it++) {
+	if(ASTFalse == ComputeFormulaUsingModel(*it)) {	    
+	  output = ASTFalse;
+	  break;	  
+	}
+      }
+      break;
+    case XOR:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      t1 = ComputeFormulaUsingModel(form[1]);
+      if((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
+	output = ASTFalse;
+      else
+	output = ASTTrue;
+      break;
+    case IFF:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      t1 = ComputeFormulaUsingModel(form[1]);
+      if((ASTTrue == t0 && ASTTrue == t1) || (ASTFalse == t0 && ASTFalse == t1))
+	output = ASTTrue;
+      else
+	output = ASTFalse;
+      break;
+    case IMPLIES:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      t1 = ComputeFormulaUsingModel(form[1]);
+      if((ASTFalse == t0) || (ASTTrue == t0 && ASTTrue == t1))
+	output = ASTTrue;
+      else
+	output = ASTFalse;
+      break;    
+    case ITE:
+      t0 = ComputeFormulaUsingModel(form[0]);
+      if(ASTTrue == t0)
+	output = ComputeFormulaUsingModel(form[1]);
+      else if(ASTFalse == t0)
+	output = ComputeFormulaUsingModel(form[2]);
+      else 
+	FatalError("ComputeFormulaUsingModel: ITE: something is wrong with the formula: ",form);
+      break;
+    default:
+      FatalError(" ComputeFormulaUsingModel: the kind has not been implemented", ASTUndefined);
+      break;
+    }
+
+    //cout << "ComputeFormulaUsingModel output is:" << output << endl;
+    ComputeFormulaMap[form] = output;
+    return output;
+  }
+
+  void BeevMgr::CheckCounterExample(bool t) {
+    // FIXME:  Code is more useful if enable flags are check OUTSIDE the method.
+    // If I want to check a counterexample somewhere, I don't want to have to set
+    // the flag in order to make it actualy happen!
+
+    if(!check_counterexample) {
+      return;
+    }
+
+    //input is valid, no counterexample to check
+    if(ValidFlag)
+      return;
+
+    //t is true if SAT solver generated a counterexample, else it is false
+    if(!t)
+      FatalError("CheckCounterExample: No CounterExample to check", ASTUndefined);
+    const ASTVec c = GetAsserts();    
+    for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++)
+      if(ASTFalse == ComputeFormulaUsingModel(*it))
+	FatalError("CheckCounterExample:counterexample bogus:"\
+		   "assert evaluates to FALSE under counterexample: NOT OK",*it);
+        
+    if(ASTTrue == ComputeFormulaUsingModel(_current_query))
+      FatalError("CheckCounterExample:counterexample bogus:"\
+		 "query evaluates to TRUE under counterexample: NOT OK",_current_query);
+  }
+
+  /* FUNCTION: prints a counterexample for INVALID inputs.  iterate
+   * through the CounterExampleMap data structure and print it to
+   * stdout
+   */
+  void BeevMgr::PrintCounterExample(bool t, std::ostream& os) {
+    //global command-line option
+    // FIXME: This should always print the counterexample.  If you want
+    // to turn it off, check the switch at the point of call.
+    if(!print_counterexample)
+      return;
+
+    //input is valid, no counterexample to print
+    if(ValidFlag)
+      return;
+
+    //if this option is true then print the way dawson wants using a
+    //different printer. do not use this printer.
+    if(print_arrayval_declaredorder)
+      return;
+
+    //t is true if SAT solver generated a counterexample, else it is
+    //false
+    if(!t) {
+      cerr << "PrintCounterExample: No CounterExample to print: " << endl;
+      return;
+    }
+
+    //os << "\nCOUNTEREXAMPLE: \n" << endl;
+    ASTNodeMap::iterator it  = CounterExampleMap.begin();
+    ASTNodeMap::iterator itend = CounterExampleMap.end();
+    for(;it!=itend;it++) {
+      ASTNode f = it->first;
+      ASTNode se = it->second;
+      
+      if(ARRAY_TYPE == se.GetType()) {
+	FatalError("TermToConstTermUsingModel: entry in counterexample is an arraytype. bogus:",se);
+      }
+
+      //skip over introduced variables
+      if(f.GetKind() == SYMBOL && (_introduced_symbols.find(f) != _introduced_symbols.end())) 
+	continue;
+      if(f.GetKind() == SYMBOL || 
+	 (f.GetKind() == READ && f[0].GetKind() == SYMBOL && f[1].GetKind() == BVCONST)) {
+	os << "ASSERT( ";
+	f.PL_Print(os,0);
+	os << " = ";	
+	if(BITVECTOR_TYPE == se.GetType()) {
+	  TermToConstTermUsingModel(se,false).PL_Print(os,0);
+	}
+	else {
+	  se.PL_Print(os,0);
+	}
+	os << " );" << endl;
+      }
+    }	      
+    //os << "\nEND OF COUNTEREXAMPLE" << endl;
+  } //End of PrintCounterExample
+
+  /* iterate through the CounterExampleMap data structure and print it
+   * to stdout. this function prints only the declared array variables
+   * IN the ORDER in which they were declared. It also assumes that
+   * the variables are of the form 'varname_number'. otherwise it will
+   * not print anything. This function was specifically written for
+   * Dawson Engler's group (bug finding research group at Stanford)
+   */
+  void BeevMgr::PrintCounterExample_InOrder(bool t) {
+    //global command-line option to print counterexample. we do not
+    //want both counterexample printers to print at the sametime.
+    // FIXME: This should always print the counterexample.  If you want
+    // to turn it off, check the switch at the point of call.
+    if(print_counterexample)
+      return;
+
+    //input is valid, no counterexample to print
+    if(ValidFlag)
+      return;
+    
+    //print if the commandline option is '-q'. allows printing the
+    //counterexample in order.
+    if(!print_arrayval_declaredorder)
+      return;
+
+    //t is true if SAT solver generated a counterexample, else it is
+    //false
+    if(!t) {
+      cerr << "PrintCounterExample: No CounterExample to print: " << endl;
+      return;
+    }
+    
+    //vector to store the integer values
+    std::vector<int> out_int;	
+    cout << "% ";
+    for(ASTVec::iterator it=_special_print_set.begin(),itend=_special_print_set.end();
+	it!=itend;it++) {
+      if(ARRAY_TYPE == it->GetType()) {
+	//get the name of the variable
+	const char * c = it->GetName();
+	std::string ss(c);
+	if(!(0 == strncmp(ss.c_str(),"ini_",4)))
+	  continue;
+	reverse(ss.begin(),ss.end());
+
+	//cout << "debugging: " << ss;
+	size_t pos = ss.find('_',0);
+	if(!(0 < pos && pos < ss.size()))
+	  continue;
+
+	//get the associated length
+	std::string sss = ss.substr(0,pos);
+	reverse(sss.begin(),sss.end());
+	int n = atoi(sss.c_str());
+
+	it->PL_Print(cout,2);
+	for(int j=0;j < n; j++) {
+	  ASTNode index = CreateBVConst(it->GetIndexWidth(),j);
+	  ASTNode readexpr = CreateTerm(READ,it->GetValueWidth(),*it,index);
+	  ASTNode val = GetCounterExample(t, readexpr);
+	  //cout << "ASSERT( ";
+	  //cout << " = ";	  
+	  out_int.push_back(GetUnsignedConst(val));
+	  //cout << "\n";
+	}
+      }
+    }
+    cout << endl;
+    for(unsigned int jj=0; jj < out_int.size();jj++)
+      cout << out_int[jj] << endl;
+    cout << endl;
+  } //End of PrintCounterExample_InOrder
+
+  /* FUNCTION: queries the CounterExampleMap object with 'expr' and
+   * returns the corresponding counterexample value.
+   */
+  ASTNode BeevMgr::GetCounterExample(bool t, const ASTNode& expr) {    
+    //input is valid, no counterexample to get
+    if(ValidFlag)
+      return ASTUndefined;
+    
+    if(BOOLEAN_TYPE == expr.GetType()) {
+      return ComputeFormulaUsingModel(expr);
+    }
+
+    if(BVCONST == expr.GetKind()) {
+      return expr;
+    }
+
+    ASTNodeMap::iterator it;
+    ASTNode output;
+    if((it = CounterExampleMap.find(expr)) != CounterExampleMap.end())
+      output =  TermToConstTermUsingModel(CounterExampleMap[expr],false);
+    else
+      output = CreateZeroConst(expr.GetValueWidth());
+    return output;
+  } //End of GetCounterExample
+
+  // FIXME:  Don't use numeric codes.  Use an enum type!
+  //Acceps a query, calls the SAT solver and generates Valid/InValid.
+  //if returned 0 then input is INVALID
+  //if returned 1 then input is VALID
+  //if returned 2 then ERROR
+  int BeevMgr::TopLevelSAT( const ASTNode& inputasserts, const ASTNode& query) {  
+    /******start solving**********/
+    ASTNode q = CreateNode(AND, inputasserts, CreateNode(NOT,query));
+    ASTNode orig_input = q;
+    ASTNodeStats("input asserts and query: ", q);
+ 
+    ASTNode newq = q;
+    //round of substitution, solving, and simplification. ensures that
+    //DAG is minimized as much as possibly, and ideally should
+    //garuntee that all liketerms in BVPLUSes have been combined.
+    BVSolver bvsolver(this);
+    SimplifyWrites_InPlace_Flag = false;
+    Begin_RemoveWrites = false;
+    start_abstracting = false;    
+    TermsAlreadySeenMap.clear();
+    do {
+      q = newq;
+      newq = CreateSubstitutionMap(newq);
+      //ASTNodeStats("after pure substitution: ", newq);
+      newq = SimplifyFormula_TopLevel(newq,false);
+      //ASTNodeStats("after simplification: ", newq);
+      //newq = bvsolver.TopLevelBVSolve(newq);
+      //ASTNodeStats("after solving: ", newq);      
+    }while(q!=newq);
+
+    ASTNodeStats("Before SimplifyWrites_Inplace begins: ", newq);
+    SimplifyWrites_InPlace_Flag = true;
+    Begin_RemoveWrites = false;
+    start_abstracting = false;
+    TermsAlreadySeenMap.clear();
+    do {
+      q = newq;
+      //newq = CreateSubstitutionMap(newq);
+      //ASTNodeStats("after pure substitution: ", newq);
+      newq = SimplifyFormula_TopLevel(newq,false);
+      //ASTNodeStats("after simplification: ", newq);
+      newq = bvsolver.TopLevelBVSolve(newq);
+      //ASTNodeStats("after solving: ", newq);      
+    }while(q!=newq);
+    ASTNodeStats("After SimplifyWrites_Inplace: ", newq);        
+
+    start_abstracting = (arraywrite_refinement) ? true : false;
+    SimplifyWrites_InPlace_Flag = false;
+    Begin_RemoveWrites = (start_abstracting) ? false : true;    
+    if(start_abstracting) {
+      ASTNodeStats("before abstraction round begins: ", newq);
+    }
+
+    TermsAlreadySeenMap.clear();
+    do {
+      q = newq;
+      //newq = CreateSubstitutionMap(newq);
+      //Begin_RemoveWrites = true;
+      //ASTNodeStats("after pure substitution: ", newq);
+      newq = SimplifyFormula_TopLevel(newq,false);
+      //ASTNodeStats("after simplification: ", newq);
+      //newq = bvsolver.TopLevelBVSolve(newq);
+      //ASTNodeStats("after solving: ", newq);
+    }while(q!=newq);
+
+    if(start_abstracting) {
+      ASTNodeStats("After abstraction: ", newq);
+    }
+    start_abstracting = false;
+    SimplifyWrites_InPlace_Flag = false;
+    Begin_RemoveWrites = false;    
+    
+    newq = TransformFormula(newq);
+    ASTNodeStats("after transformation: ", newq);
+    TermsAlreadySeenMap.clear();
+
+    int res;    
+    //solver instantiated here
+    MINISAT::Solver newS;
+    if(arrayread_refinement) {
+      counterexample_checking_during_refinement = true;
+    }
+    
+    //call SAT and check the result
+    res = CallSAT_ResultCheck(newS,newq,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }
+
+    res = SATBased_ArrayReadRefinement(newS,newq,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }
+ 
+    res = SATBased_ArrayWriteRefinement(newS,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }          
+
+    res = SATBased_ArrayReadRefinement(newS,newq,orig_input);
+    if(2 != res) {
+      CountersAndStats("print_func_stats");
+      return res;
+    }
+
+    FatalError("TopLevelSAT: reached the end without proper conclusion:" 
+	       "either a divide by zero in the input or a bug in STP");
+    //bogus return to make the compiler shut up
+    return 2;
+  } //End of TopLevelSAT
+
+  //go over the list of indices for each array, and generate Leibnitz
+  //axioms. Then assert these axioms into the SAT solver. Check if the
+  //addition of the new constraints has made the bogus counterexample
+  //go away. if yes, return the correct answer. if no, continue adding
+  //Leibnitz axioms systematically.
+  // FIXME:  What it really does is, for each array, loop over each index i.
+  // inside that loop, it finds all the true and false axioms with i as first
+  // index.  When it's got them all, it adds the false axioms to the formula
+  // and re-solves, and returns if the result is correct.  Otherwise, it
+  // goes on to the next index.
+  // If it gets through all the indices without a correct result (which I think
+  // is impossible, but this is pretty confusing), it then solves with all
+  // the true axioms, too.
+  // This is not the most obvious way to do it, and I don't know how it 
+  // compares with other approaches (e.g., one false axiom at a time or
+  // all the false axioms each time).
+  int BeevMgr::SATBased_ArrayReadRefinement(MINISAT::Solver& newS, 
+					    const ASTNode& q, const ASTNode& orig_input) {
+    if(!arrayread_refinement)
+      FatalError("SATBased_ArrayReadRefinement: Control should not reach here");
+
+    ASTVec FalseAxiomsVec, RemainingAxiomsVec;
+    RemainingAxiomsVec.push_back(ASTTrue);   
+    FalseAxiomsVec.push_back(ASTTrue);
+
+    //in these loops we try to construct Leibnitz axioms and add it to
+    //the solve(). We add only those axioms that are false in the
+    //current counterexample. we keep adding the axioms until there
+    //are no more axioms to add
+    //
+    //for each array, fetch its list of indices seen so far
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      ASTVec listOfIndices = iset->second;
+      //loop over the list of indices for the array and create LA, and add to q
+      for(ASTVec::iterator it=listOfIndices.begin(),itend=listOfIndices.end();it!=itend;it++) {
+	if(BVCONST == it->GetKind()) {
+	  continue;
+	}	
+
+	ASTNode the_index = *it;
+	//get the arrayname
+	ASTNode ArrName = iset->first;
+	// if(SYMBOL != ArrName.GetKind())
+	// 	  FatalError("SATBased_ArrayReadRefinement: arrname is not a SYMBOL",ArrName);
+	ASTNode arr_read1 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, the_index);
+	//get the variable corresponding to the array_read1
+	ASTNode arrsym1 = _arrayread_symbol[arr_read1];
+	if(!(SYMBOL == arrsym1.GetKind() || BVCONST == arrsym1.GetKind()))
+	  FatalError("TopLevelSAT: refinementloop:term arrsym1 corresponding to READ must be a var", arrsym1);
+
+	//we have nonconst index here. create Leibnitz axiom for it
+	//w.r.t every index in listOfIndices
+	for(ASTVec::iterator it1=listOfIndices.begin(),itend1=listOfIndices.end();
+	    it1!=itend1;it1++) {
+	  ASTNode compare_index = *it1;
+	  //do not compare with yourself
+	  if(the_index == compare_index)
+	    continue;
+	  
+	  //prepare for SAT LOOP 
+	  //first construct the antecedent for the LA axiom
+	  ASTNode eqOfIndices = 
+	    (exprless(the_index,compare_index)) ? 
+	    CreateSimplifiedEQ(the_index,compare_index) : CreateSimplifiedEQ(compare_index,the_index);
+	  	  
+	  ASTNode arr_read2 = CreateTerm(READ, ArrName.GetValueWidth(), ArrName, compare_index);
+	  //get the variable corresponding to the array_read2
+	  ASTNode arrsym2 = _arrayread_symbol[arr_read2];
+	  if(!(SYMBOL == arrsym2.GetKind() || BVCONST == arrsym2.GetKind()))
+	    FatalError("TopLevelSAT: refinement loop:"
+		       "term arrsym2 corresponding to READ must be a var", arrsym2);
+	  
+	  ASTNode eqOfReads = CreateSimplifiedEQ(arrsym1,arrsym2);
+	  //construct appropriate Leibnitz axiom
+	  ASTNode LeibnitzAxiom = CreateNode(IMPLIES, eqOfIndices, eqOfReads);
+	  if(ASTFalse == ComputeFormulaUsingModel(LeibnitzAxiom))
+	    //FalseAxioms = CreateNode(AND,FalseAxioms,LeibnitzAxiom);
+	    FalseAxiomsVec.push_back(LeibnitzAxiom);
+	  else
+	    //RemainingAxioms = CreateNode(AND,RemainingAxioms,LeibnitzAxiom);
+	    RemainingAxiomsVec.push_back(LeibnitzAxiom);
+	}
+	ASTNode FalseAxioms = (FalseAxiomsVec.size()>1) ? CreateNode(AND,FalseAxiomsVec) : FalseAxiomsVec[0];
+	ASTNodeStats("adding false readaxioms to SAT: ", FalseAxioms);  
+	int res2 = CallSAT_ResultCheck(newS,FalseAxioms,orig_input);
+	if(2!=res2) {
+	  return res2;
+	}	
+      }
+    }
+    ASTNode RemainingAxioms = (RemainingAxiomsVec.size()>1) ? CreateNode(AND,RemainingAxiomsVec):RemainingAxiomsVec[0];
+    ASTNodeStats("adding remaining readaxioms to SAT: ", RemainingAxioms);  
+    return CallSAT_ResultCheck(newS,RemainingAxioms,orig_input);
+  } //end of SATBased_ArrayReadRefinement
+
+  ASTNode BeevMgr::Create_ArrayWriteAxioms(const ASTNode& term, const ASTNode& newvar) {
+    if(READ != term.GetKind() && WRITE != term[0].GetKind()) {
+      FatalError("Create_ArrayWriteAxioms: Input must be a READ over a WRITE",term);
+    }
+    
+    ASTNode lhs = newvar;
+    ASTNode rhs = term;
+    ASTNode arraywrite_axiom = CreateSimplifiedEQ(lhs,rhs);
+    return arraywrite_axiom;
+  }//end of Create_ArrayWriteAxioms()
+
+  int BeevMgr::SATBased_ArrayWriteRefinement(MINISAT::Solver& newS, const ASTNode& orig_input) {
+    ASTNode writeAxiom;
+    ASTNodeMap::iterator it = ReadOverWrite_NewName_Map.begin();
+    ASTNodeMap::iterator itend = ReadOverWrite_NewName_Map.end();
+    //int count = 0;
+    //int num_write_axioms = ReadOverWrite_NewName_Map.size();
+
+    ASTVec FalseAxioms, RemainingAxioms;
+    FalseAxioms.push_back(ASTTrue);
+    RemainingAxioms.push_back(ASTTrue);
+    for(;it!=itend;it++) {
+      //Guided refinement starts here
+      ComputeFormulaMap.clear();      
+      writeAxiom = Create_ArrayWriteAxioms(it->first,it->second);
+      if(ASTFalse == ComputeFormulaUsingModel(writeAxiom)) {
+	writeAxiom = TransformFormula(writeAxiom);
+	FalseAxioms.push_back(writeAxiom);
+      }
+      else {
+	writeAxiom = TransformFormula(writeAxiom);
+	RemainingAxioms.push_back(writeAxiom);
+      }
+    }
+      
+    writeAxiom = (FalseAxioms.size() != 1) ? CreateNode(AND,FalseAxioms) : FalseAxioms[0];
+    ASTNodeStats("adding false writeaxiom to SAT: ", writeAxiom);
+    int res2 = CallSAT_ResultCheck(newS,writeAxiom,orig_input);
+    if(2!=res2) {
+      return res2;
+    }
+    
+    writeAxiom = (RemainingAxioms.size() != 1) ? CreateNode(AND,RemainingAxioms) : RemainingAxioms[0];
+    ASTNodeStats("adding remaining writeaxiom to SAT: ", writeAxiom);
+    res2 = CallSAT_ResultCheck(newS,writeAxiom,orig_input);
+    if(2!=res2) {
+	return res2;
+    }
+    
+    return 2;
+  } //end of SATBased_ArrayWriteRefinement
+
+  //Check result after calling SAT FIXME: Document arguments in
+  //comments, and give them meaningful names.  How is anyone supposed
+  //to know what "q" is?
+  int BeevMgr::CallSAT_ResultCheck(MINISAT::Solver& newS, 
+				   const ASTNode& q, const ASTNode& orig_input) {
+    //Bitblast, CNF, call SAT now
+    ASTNode BBFormula = BBForm(q);
+    //ASTNodeStats("after bitblasting", BBFormula);    
+    ClauseList *cllp = ToCNF(BBFormula);
+    // if(stats && print_nodes) {
+    //       cout << "\nClause list" << endl;
+    //       PrintClauseList(cout, *cllp);
+    //       cerr << "\n finished printing clauselist\n";
+    //     }
+
+    bool sat = toSATandSolve(newS,*cllp);    
+    // Temporary debugging call.
+    // CheckBBandCNF(newS, BBFormula);
+
+    DeleteClauseList(cllp);
+    if(!sat) {
+      PrintOutput(true);
+      return 1;
+    }
+    else if(newS.okay()) {
+      CounterExampleMap.clear();
+      ConstructCounterExample(newS);
+      if (stats && print_nodes) {
+	PrintSATModel(newS);
+      }
+      //check if the counterexample is good or not
+      ComputeFormulaMap.clear();
+      if(counterexample_checking_during_refinement)
+	bvdiv_exception_occured = false;
+      ASTNode orig_result = ComputeFormulaUsingModel(orig_input);
+      if(!(ASTTrue == orig_result || ASTFalse == orig_result))
+      	FatalError("TopLevelSat: Original input must compute to true or false against model");
+      
+//       if(!arrayread_refinement && !(ASTTrue == orig_result)) {
+// 	print_counterexample = true;
+// 	PrintCounterExample(true);
+//       	FatalError("counterexample bogus : arrayread_refinement is switched off: " 
+//       		   "EITHER all LA axioms have not been added OR bitblaster() or ToCNF()"
+// 		   "or satsolver() or counterexamplechecker() have a bug");
+//       }
+
+      // if the counterexample is indeed a good one, then return
+      // invalid
+      if(ASTTrue == orig_result) {
+	CheckCounterExample(newS.okay());
+	PrintOutput(false);
+	PrintCounterExample(newS.okay());
+	PrintCounterExample_InOrder(newS.okay());
+	return 0;	
+      }
+      // counterexample is bogus: flag it
+      else {
+	if(stats && print_nodes) {
+	  cout << "Supposedly bogus one: \n";
+	  bool tmp = print_counterexample;
+	  print_counterexample = true;
+	  PrintCounterExample(true);
+	  print_counterexample = tmp;
+	}
+
+	return 2;
+      }
+    }
+    else {
+      PrintOutput(true);
+      return -100;
+    }
+  } //end of CALLSAT_ResultCheck
+
+
+  //FUNCTION: this function accepts a boolvector and returns a BVConst   
+  ASTNode BeevMgr::BoolVectoBVConst(hash_map<unsigned,bool> * w, unsigned int l) {    
+    unsigned len = w->size();
+    if(l < len)
+      FatalError("BoolVectorBVConst : length of bitvector does not match hash_map size:",ASTUndefined,l);
+    std::string cc;
+    for(unsigned int jj = 0; jj < l; jj++) {
+      if((*w)[jj] == true)
+	cc += '1';
+      else if((*w)[jj] == false)
+	cc += '0';
+      else 
+	cc += '0';
+    }
+    return CreateBVConst(cc.c_str(),2);
+  }
+
+  void BeevMgr::PrintActivityLevels_Of_SATVars(char * init_msg, MINISAT::Solver& newS) {
+    if(!print_sat_varorder)
+      return;
+
+    ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();   
+    ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
+   
+    cout << init_msg;
+    cout << ": Printing activity levels of variables\n";
+    for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
+      cout << (it->second) << "  :  ";
+      (it->first).PL_Print(cout,0);
+      cout << "   :   ";
+      cout << newS.returnActivity(it->second) << endl;
+    }
+  }
+
+  //this function biases the activity levels of MINISAT variables.
+  void BeevMgr::ChangeActivityLevels_Of_SATVars(MINISAT::Solver& newS) {
+    if(!variable_activity_optimize)
+      return;
+
+    ASTtoSATMap::iterator itbegin = _ASTNode_to_SATVar.begin();   
+    ASTtoSATMap::iterator itend = _ASTNode_to_SATVar.end();
+   
+    unsigned int index=1;
+    double base = 2;
+    for(ASTtoSATMap::iterator it=itbegin;it!=itend;it++){
+      ASTNode n = it->first;
+
+      if(BVGETBIT == n.GetKind() || NOT == n.GetKind()) {
+      	if(BVGETBIT == n.GetKind())
+      	  index = GetUnsignedConst(n[1]);
+      	else if (NOT == n.GetKind() && BVGETBIT == n[0].GetKind())
+      	  index = GetUnsignedConst(n[0][1]);
+      	else 
+      	  index = 0;
+	double initial_activity = pow(base,(double)index);
+	newS.updateInitialActivity(it->second,initial_activity);
+      } 
+      else {
+	double initial_activity = pow(base,pow(base,(double)index));
+	newS.updateInitialActivity(it->second,initial_activity);	
+      }    
+    }
+  }
+
+  //This function prints the output of the STP solver
+  void BeevMgr::PrintOutput(bool true_iff_valid) {
+    //self-explanatory
+    if(true_iff_valid) {
+      ValidFlag = true;
+      if(print_output) {
+	if(smtlib_parser_enable)
+	  cout << "unsat\n";
+	else
+	  cout << "Valid.\n";
+      }
+    }
+    else {
+      ValidFlag = false;
+      if(print_output) {
+	if(smtlib_parser_enable)
+	  cout << "sat\n";
+	else
+	  cout << "Invalid.\n";
+      }
+    }
+  }
+}; //end of namespace BEEV
diff --git a/stp/AST/Transform.cpp b/stp/AST/Transform.cpp
new file mode 100644
index 00000000..598b831e
--- /dev/null
+++ b/stp/AST/Transform.cpp
@@ -0,0 +1,492 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "AST.h"
+#include <stdlib.h>
+#include <stdio.h>
+namespace BEEV {  
+  
+  //Translates signed BVDIV/BVMOD into unsigned variety
+  ASTNode BeevMgr::TranslateSignedDivMod(const ASTNode& in) {
+    if(!(SBVMOD == in.GetKind() || SBVDIV == in.GetKind())) {
+      FatalError("TranslateSignedDivMod: input must be signed DIV/MOD\n",in);
+    }
+
+    ASTNode dividend = in[0];
+    ASTNode divisor  = in[1];      
+    unsigned len = in.GetValueWidth();
+    if(SBVMOD == in.GetKind()) {
+      //if(TopBit(dividend)==1) 
+      //
+      //then -BVMOD(-dividend,abs(divisor)) 
+      //
+      //else BVMOD(dividend,abs(divisor))
+
+      //create the condition for the dividend
+      ASTNode hi1  = CreateBVConst(32,len-1);
+      ASTNode one  = CreateOneConst(1);
+      ASTNode cond = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1));
+
+      //create the condition and conditional for the divisor
+      ASTNode cond_divisor = CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1));
+      ASTNode pos_divisor  = CreateTerm(ITE,len,cond_divisor,CreateTerm(BVUMINUS,len,divisor),divisor);
+
+      //create the modulus term for each case
+      ASTNode modnode = CreateTerm(BVMOD,len,dividend,pos_divisor);
+      ASTNode minus_modnode = CreateTerm(BVMOD,len,CreateTerm(BVUMINUS,len,dividend),pos_divisor);
+      minus_modnode = CreateTerm(BVUMINUS,len,minus_modnode);
+
+      //put everything together, simplify, and return
+      ASTNode n = CreateTerm(ITE,len,cond,minus_modnode,modnode);
+      return SimplifyTerm_TopLevel(n);
+    }
+    
+    //now handle the BVDIV case
+    //if topBit(dividend) is 1 and topBit(divisor) is 0
+    //
+    //then output is -BVDIV(-dividend,divisor)
+    //
+    //elseif topBit(dividend) is 0 and topBit(divisor) is 1
+    //
+    //then output is -BVDIV(dividend,-divisor)
+    //
+    //elseif topBit(dividend) is 1 and topBit(divisor) is 1
+    //
+    // then output is BVDIV(-dividend,-divisor)
+    //
+    //else simply output BVDIV(dividend,divisor)
+    ASTNode hi1 = CreateBVConst(32,len-1);
+    ASTNode zero = CreateZeroConst(1);
+    ASTNode one = CreateOneConst(1);
+    ASTNode divnode = CreateTerm(BVDIV, len, dividend, divisor);
+
+    ASTNode cond1 = CreateNode(AND,
+			       CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+			       CreateNode(EQ,one, CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+    ASTNode minus_divnode1 = CreateTerm(BVDIV,len,
+					dividend,
+					CreateTerm(BVUMINUS,len,divisor));
+    minus_divnode1 = CreateTerm(BVUMINUS,len,minus_divnode1);
+
+    ASTNode cond2 = CreateNode(AND,
+			       CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+			       CreateNode(EQ,zero,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+    ASTNode minus_divnode2 = CreateTerm(BVDIV,len,
+					CreateTerm(BVUMINUS,len,dividend),
+					divisor);
+    minus_divnode2 = CreateTerm(BVUMINUS,len,minus_divnode2);
+
+    ASTNode cond3 = CreateNode(AND,
+			       CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,dividend,hi1,hi1)),
+			       CreateNode(EQ,one,CreateTerm(BVEXTRACT,1,divisor,hi1,hi1)));
+    ASTNode minus_divnode3 = CreateTerm(BVDIV,len,
+					CreateTerm(BVUMINUS,len,dividend),
+					CreateTerm(BVUMINUS,len,divisor));
+    ASTNode n = CreateTerm(ITE,len,
+			   cond1,
+			   minus_divnode1,
+			   CreateTerm(ITE,len,
+				      cond2,
+				      minus_divnode2,
+				      CreateTerm(ITE,len,
+						 cond3,
+						 minus_divnode3,
+						 divnode)));
+  return SimplifyTerm_TopLevel(n);
+  }//end of TranslateSignedDivMod()
+
+  ASTNode BeevMgr::TransformFormula(const ASTNode& form) {
+    ASTNode result;
+
+    ASTNode simpleForm = form;
+    Kind k = simpleForm.GetKind();
+    if(!(is_Form_kind(k) && BOOLEAN_TYPE == simpleForm.GetType())) {
+      //FIXME: "You have inputted a NON-formula"?
+      FatalError("TransformFormula: You have input a NON-formula",simpleForm);
+    }
+
+    ASTNodeMap::iterator iter;
+    if((iter = TransformMap.find(simpleForm)) != TransformMap.end())
+      return iter->second;
+
+    switch(k) {
+    case TRUE:
+    case FALSE: {
+      result = simpleForm;
+      break;
+    }
+    case NOT: {
+      ASTVec c;
+      c.push_back(TransformFormula(simpleForm[0]));
+      result = CreateNode(NOT,c);      
+      break;
+    }
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVSLT:
+    case BVSLE:
+    case BVSGT:
+    case BVSGE:      
+    case NEQ: {
+      ASTVec c;
+      c.push_back(TransformTerm(simpleForm[0]));      
+      c.push_back(TransformTerm(simpleForm[1]));
+      result = CreateNode(k,c);
+      break;
+    }
+    case EQ: {
+      ASTNode term1 = TransformTerm(simpleForm[0]);      
+      ASTNode term2 = TransformTerm(simpleForm[1]);
+      result = CreateSimplifiedEQ(term1,term2);     
+      break;
+    }
+    case AND:
+    case OR: 
+    case NAND:
+    case NOR:
+    case IFF:
+    case XOR:
+    case ITE:
+    case IMPLIES: {
+      ASTVec vec;
+      ASTNode o;
+      for (ASTVec::const_iterator it = simpleForm.begin(),itend=simpleForm.end(); it != itend; it++){
+	o = TransformFormula(*it);	
+	vec.push_back(o);
+      }
+
+      result = CreateNode(k, vec);
+      break;
+    }
+    default:
+      if(k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType())
+	result = simpleForm;      
+      else {
+	cerr << "The input is: " << simpleForm << endl;
+	cerr << "The valuewidth of input is : " << simpleForm.GetValueWidth() << endl;
+	FatalError("TransformFormula: Illegal kind: ",ASTUndefined, k);
+      }
+      break;    
+    } 
+    //BVTypeCheck(result);
+    TransformMap[simpleForm] = result;
+    return result;
+  } //End of TransformFormula
+
+  ASTNode BeevMgr::TransformTerm(const ASTNode& inputterm) {
+    ASTNode result;
+    ASTNode term = inputterm;
+
+    Kind k = term.GetKind();
+    if(!is_Term_kind(k))
+      FatalError("TransformTerm: Illegal kind: You have input a nonterm:", inputterm, k);
+    ASTNodeMap::iterator iter;
+    if((iter = TransformMap.find(term)) != TransformMap.end())
+      return iter->second;
+    switch(k) {
+    case SYMBOL: {
+      // ASTNodeMap::iterator itsym;
+//       if((itsym = CounterExampleMap.find(term)) != CounterExampleMap.end())	
+//       	result = itsym->second;
+//       else
+	result = term;
+      break;
+    }
+    case BVCONST:
+      result = term;
+      break;
+    case WRITE:
+      FatalError("TransformTerm: this kind is not supported",term);
+      break;
+    case READ:
+      result = TransformArray(term);
+      break;
+    case ITE: {
+      ASTNode cond = term[0];
+      ASTNode thn  = term[1];
+      ASTNode els  = term[2];
+      cond = TransformFormula(cond);
+      thn = TransformTerm(thn);
+      els = TransformTerm(els);
+      //result = CreateTerm(ITE,term.GetValueWidth(),cond,thn,els);
+      result = CreateSimplifiedTermITE(cond,thn,els);
+      result.SetIndexWidth(term.GetIndexWidth());
+      break;
+    }
+    default: {
+      ASTVec c = term.GetChildren();
+      ASTVec::iterator it = c.begin();
+      ASTVec::iterator itend = c.end();
+      unsigned width = term.GetValueWidth();
+      unsigned indexwidth = term.GetIndexWidth();
+      ASTVec o;
+      for(;it!=itend;it++) {
+	o.push_back(TransformTerm(*it));
+      }
+
+      result = CreateTerm(k,width,o);
+      result.SetIndexWidth(indexwidth);
+
+      if(SBVDIV == result.GetKind() || SBVMOD == result.GetKind()) {
+	result = TranslateSignedDivMod(result);
+      }
+      break;
+    }
+    }
+
+    TransformMap[term] = result;
+    if(term.GetValueWidth() != result.GetValueWidth())
+      FatalError("TransformTerm: result and input terms are of different length", result);
+    if(term.GetIndexWidth() != result.GetIndexWidth()) {
+      cerr << "TransformTerm: input term is : " << term << endl;
+      FatalError("TransformTerm: result and input terms have different index length", result);
+    }
+    return result;
+  } //End of TransformTerm
+
+  /* This function transforms Array Reads, Read over Writes, Read over
+   * ITEs into flattened form.
+   *
+   * Transform1: Suppose there are two array reads in the input
+   * Read(A,i) and Read(A,j) over the same array. Then Read(A,i) is
+   * replaced with a symbolic constant, say v1, and Read(A,j) is
+   * replaced with the following ITE:
+   *
+   * ITE(i=j,v1,v2)
+   *
+   * Transform2:
+   * 
+   * Transform3:
+   */
+  ASTNode BeevMgr::TransformArray(const ASTNode& term) {
+    ASTNode result = term;
+
+    unsigned int width = term.GetValueWidth();
+    Kind k = term.GetKind();
+    if (!is_Term_kind(k))
+      FatalError("TransformArray: Illegal kind: You have input a nonterm:", ASTUndefined, k);
+    ASTNodeMap::iterator iter;
+    if((iter = TransformMap.find(term)) != TransformMap.end())
+      return iter->second;
+
+    switch(k) {
+      //'term' is of the form READ(arrName, readIndex) 
+    case READ: {
+      ASTNode arrName = term[0];
+      switch (arrName.GetKind()) {
+      case SYMBOL: {
+	/* input is of the form: READ(A, readIndex)
+	 * 
+	 * output is of the from: A1, if this is the first READ over A
+         *                           
+	 *                        ITE(previous_readIndex=readIndex,A1,A2)
+	 *                        
+         *                        .....
+	 */
+
+	//  Recursively transform read index, which may also contain reads.
+	ASTNode readIndex = TransformTerm(term[1]);	
+	ASTNode processedTerm = CreateTerm(READ,width,arrName,readIndex);
+	
+	//check if the 'processedTerm' has a corresponding ITE construct
+	//already. if so, return it. else continue processing.
+	ASTNodeMap::iterator it;
+	if((it = _arrayread_ite.find(processedTerm)) != _arrayread_ite.end()) {
+	  result = it->second;	
+	  break;
+	}
+	//Constructing Symbolic variable corresponding to 'processedTerm'
+	ASTNode CurrentSymbol;
+	ASTNodeMap::iterator it1;
+	// First, check if read index is constant and it has a constant value in the substitution map.
+	if(CheckSubstitutionMap(processedTerm,CurrentSymbol)) {
+	  _arrayread_symbol[processedTerm] = CurrentSymbol;
+	}
+	// Check if it already has an abstract variable.
+	else if((it1 = _arrayread_symbol.find(processedTerm)) != _arrayread_symbol.end()) {
+	  CurrentSymbol = it1->second;
+	}
+	else {
+	  // Make up a new abstract variable.
+	  // FIXME: Make this into a method (there already may BE a method) and
+	  // get rid of the fixed-length buffer!
+	  //build symbolic name corresponding to array read. The symbolic
+	  //name has 2 components: stringname, and a count
+	  const char * b = arrName.GetName();
+	  std::string c(b);
+	  char d[32];
+	  sprintf(d,"%d",_symbol_count++);
+	  std::string ccc(d);
+	  c += "array_" + ccc;
+	  
+	  CurrentSymbol = CreateSymbol(c.c_str());
+	  CurrentSymbol.SetValueWidth(processedTerm.GetValueWidth());
+	  CurrentSymbol.SetIndexWidth(processedTerm.GetIndexWidth());
+	  _arrayread_symbol[processedTerm] = CurrentSymbol;	  
+	}
+	
+	//list of array-read indices corresponding to arrName, seen while
+	//traversing the AST tree. we need this list to construct the ITEs
+	// Dill: we hope to make this irrelevant.  Harmless for now.
+	ASTVec readIndices = _arrayname_readindices[arrName];
+	
+	//construct the ITE structure for this array-read
+	ASTNode ite = CurrentSymbol;
+	_introduced_symbols.insert(CurrentSymbol);
+	BVTypeCheck(ite);
+	
+	if(arrayread_refinement) {
+	  // ite is really a variable here; it is an ite in the
+	  // else-branch
+	  result = ite;
+	}
+	else {
+	  // Full Seshia transform if we're not doing read refinement.
+	  //do not loop if the current readIndex is a BVCONST
+	  // if(BVCONST == term[1].GetKind() && !SeenNonConstReadIndex && optimize) {
+	  // 	    result = ite; 
+	  // 	  }
+	  // 	  else {	  
+	    //else part: SET the SeenNonConstReadIndex var, and do the hard work
+	    //SeenNonConstReadIndex = true;
+	    ASTVec::reverse_iterator it2=readIndices.rbegin();
+	    ASTVec::reverse_iterator it2end=readIndices.rend();
+	    for(;it2!=it2end;it2++) {
+	      ASTNode cond = CreateSimplifiedEQ(readIndex,*it2);
+	      if(ASTFalse == cond)
+		continue;
+	      
+	      ASTNode arrRead = CreateTerm(READ,width,arrName,*it2);
+	      //Good idea to TypeCheck internally constructed nodes
+	      BVTypeCheck(arrRead);
+	      
+	      ASTNode arrayreadSymbol = _arrayread_symbol[arrRead];
+	      if(arrayreadSymbol.IsNull())
+		FatalError("TransformArray:symbolic variable for processedTerm, p," 
+			   "does not exist:p = ",arrRead);
+	      ite = CreateSimplifiedTermITE(cond,arrayreadSymbol,ite);
+	    }
+	    result = ite;
+	    //}
+	}
+	
+	_arrayname_readindices[arrName].push_back(readIndex);	
+	//save the ite corresponding to 'processedTerm'
+	_arrayread_ite[processedTerm] = result;
+	break;
+      } //end of READ over a SYMBOL
+      case WRITE:{	
+	/* The input to this case is: READ((WRITE A i val) j)
+	 *
+	 * The output of this case is: ITE( (= i j) val (READ A i))
+	 */
+	
+	/* 1. arrName or term[0] is infact a WRITE(A,i,val) expression
+	 *
+	 * 2. term[1] is the read-index j
+	 *
+	 * 3. arrName[0] is the new arrName i.e. A. A can be either a
+              SYMBOL or a nested WRITE. no other possibility
+	 *
+	 * 4. arrName[1] is the WRITE index i.e. i
+	 *
+	 * 5. arrName[2] is the WRITE value i.e. val (val can inturn
+	 *    be an array read)
+	 */
+	ASTNode readIndex = TransformTerm(term[1]);
+	ASTNode writeIndex = TransformTerm(arrName[1]);
+	ASTNode writeVal = TransformTerm(arrName[2]);
+	
+	if(!(SYMBOL == arrName[0].GetKind() || 
+	     WRITE == arrName[0].GetKind())) 
+	  FatalError("TransformArray: An array write is being attempted on a non-array:",term);
+	if(ARRAY_TYPE != arrName[0].GetType())
+	  FatalError("TransformArray: An array write is being attempted on a non-array:",term);
+	
+	ASTNode cond = CreateSimplifiedEQ(writeIndex,readIndex);
+	//TypeCheck internally created node
+	BVTypeCheck(cond);
+	ASTNode readTerm = CreateTerm(READ,width,arrName[0],readIndex);
+	//TypeCheck internally created node
+	BVTypeCheck(readTerm);
+	ASTNode readPushedIn = TransformArray(readTerm);
+	//TypeCheck internally created node
+	BVTypeCheck(readPushedIn);
+	//result = CreateTerm(ITE, arrName[0].GetValueWidth(),cond,writeVal,readPushedIn);
+	result = CreateSimplifiedTermITE(cond,writeVal,readPushedIn);
+
+	//Good idea to typecheck terms created inside the system
+	BVTypeCheck(result);
+	break;
+      } //end of READ over a WRITE
+      case ITE: {
+	/* READ((ITE cond thn els) j) 
+	 *
+	 * is transformed into
+	 *
+	 * (ITE cond (READ thn j) (READ els j))
+	 */
+	
+	//(ITE cond thn els)
+	ASTNode term0 = term[0];
+	//READINDEX j
+	ASTNode j = TransformTerm(term[1]);
+	
+	ASTNode cond = term0[0];
+	//first array 
+	ASTNode t01  = term0[1];
+	//second array
+	ASTNode t02  = term0[2];
+	
+	cond = TransformFormula(cond);
+	ASTNode thn = TransformTerm(t01);
+	ASTNode els = TransformTerm(t02);
+	
+	if(!(t01.GetValueWidth() == t02.GetValueWidth() &&
+	     t01.GetValueWidth() == thn.GetValueWidth() &&
+	     t01.GetValueWidth() == els.GetValueWidth()))
+	  FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n",term);
+
+	if(!(t01.GetIndexWidth() == t02.GetIndexWidth() &&
+	     t01.GetIndexWidth() == thn.GetIndexWidth() &&
+	     t01.GetIndexWidth() == els.GetIndexWidth()))
+	  FatalError("TransformArray: length of THENbranch != length of ELSEbranch in the term t = \n",term);
+
+	//(READ thn j)
+	ASTNode thnRead = CreateTerm(READ,width,thn,j);
+	BVTypeCheck(thnRead);
+	thnRead = TransformArray(thnRead);
+	
+	//(READ els j)
+	ASTNode elsRead = CreateTerm(READ,width,els,j);
+	BVTypeCheck(elsRead);
+	elsRead = TransformArray(elsRead);
+	
+	//(ITE cond (READ thn j) (READ els j))
+	result = CreateSimplifiedTermITE(cond,thnRead,elsRead);
+	BVTypeCheck(result);
+      break;
+      }
+      default:
+	FatalError("TransformArray: The READ is NOT over SYMBOL/WRITE/ITE",term);
+	break;
+      } 
+      break;
+    } //end of READ switch
+    default:
+      FatalError("TransformArray: input term is of wrong kind: ",ASTUndefined);
+      break;
+    }
+    
+    TransformMap[term] = result;
+    return result;
+  } //end of TransformArray()  
+} //end of namespace BEEV
diff --git a/stp/AST/asttest.cpp b/stp/AST/asttest.cpp
new file mode 100644
index 00000000..57f3d20c
--- /dev/null
+++ b/stp/AST/asttest.cpp
@@ -0,0 +1,29 @@
+#include "AST.h"
+
+using namespace BEEV;
+
+int main()
+{
+
+  BeevMgr * bm = new BeevMgr();
+  ASTNode s1 = bm->CreateSymbol("foo");
+  s1 = bm->CreateSymbol("foo1");
+  s1 = bm->CreateSymbol("foo2");
+  ASTNode s2 = bm->CreateSymbol("bar");
+  cout << "s1" <<  s1 << endl;
+  cout << "s2" <<  s2 << endl;
+
+  ASTNode b1 = bm->CreateBVConst(5,12);
+  ASTNode b2 = bm->CreateBVConst(6,36);
+  cout << "b1: " <<  b1 << endl;
+  cout << "b2: " <<  b2 << endl;
+
+  ASTNode a1 = bm->CreateNode(EQ, s1, s2);
+  ASTNode a2 = bm->CreateNode(AND, s1, s2);
+  a1 = bm->CreateNode(OR, s1, s2);
+  ASTNode a3 = bm->CreateNode(IMPLIES, a1, a2);
+  ASTNode a4 = bm->CreateNode(IMPLIES, s1, a2);
+  cout << "a3" <<  a3 << endl;
+  cout << "a4" <<  a4 << endl;
+  return 0;
+}
diff --git a/stp/AST/bbtest.cpp b/stp/AST/bbtest.cpp
new file mode 100644
index 00000000..83aa6a4e
--- /dev/null
+++ b/stp/AST/bbtest.cpp
@@ -0,0 +1,96 @@
+#include "AST.h"
+
+using namespace BEEV;
+
+int main()
+{
+  const int size = 32;
+
+  BeevMgr *bm = new BeevMgr();
+  ASTNode s1 = bm->CreateSymbol("x");
+  s1.SetValueWidth(size);
+  cout << "s1" <<  s1 << endl;
+  ASTNode s2 = bm->CreateSymbol("y");
+  s2.SetValueWidth(size);
+  cout << "s2" <<  s2 << endl;
+  ASTNode s3 = bm->CreateSymbol("z");
+  s3.SetValueWidth(size);
+  cout << "s3" <<  s3 << endl;
+
+  ASTNode c1 = bm->CreateBVConst(size,0);
+  cout << "c1" <<  c1 << endl;
+  ASTVec bbc1 = bm->BBTerm(c1);
+  cout << "bitblasted c1 " << endl;
+  LispPrintVec(cout, bbc1, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode c2 = bm->CreateBVConst(size,1);
+  c2.SetValueWidth(size);
+  cout << "c2" <<  c2 << endl;
+  ASTVec bbc2 = bm->BBTerm(c2);
+  cout << "bitblasted c2 " << endl;
+  LispPrintVec(cout, bbc2, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode c3 = bm->CreateBVConst(size, 0xFFFFFFFF);
+  c3.SetValueWidth(size);
+  cout << "c3" <<  c3 << endl;
+  ASTVec bbc3 = bm->BBTerm(c3);
+  cout << "bitblasted c3 " << endl;
+  LispPrintVec(cout, bbc3, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode c4 = bm->CreateBVConst(size, 0xAAAAAAAA);
+  c4.SetValueWidth(size);
+  cout << "c4" <<  c4 << endl;
+  ASTVec bbc4 = bm->BBTerm(c4);
+  cout << "bitblasted c4 " << endl;
+  LispPrintVec(cout, bbc4, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+//   ASTNode b1 = bm->CreateBVConst(12);
+//   ASTNode b2 = bm->CreateBVConst(36);
+//   cout << "b1: " <<  b1 << endl;
+//   cout << "b2: " <<  b2 << endl;
+
+  ASTNode a1 = bm->CreateNode(BVPLUS, s1, s2);
+  a1.SetValueWidth(size);
+
+  ASTVec& bba1 = bm->BBTerm(a1);
+  cout << "bitblasted a1 " << endl;
+  LispPrintVec(cout, bba1, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode a2 = bm->CreateNode(BVPLUS, s1, s2, s3);
+  a1.SetValueWidth(2);
+
+  ASTVec& bba2 = bm->BBTerm(a2);
+  cout << "bitblasted a2 " << endl;
+  LispPrintVec(cout, bba2, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode a3 = bm->CreateNode(BVXOR, s1, s2);
+  a3.SetValueWidth(2);
+
+  ASTVec& bba3 = bm->BBTerm(a3);
+  cout << "bitblasted a3 " << endl;
+  LispPrintVec(cout, bba3, 0);
+  cout << endl;
+  bm->AlreadyPrintedSet.clear();
+
+  ASTNode a4 = bm->CreateNode(EQ, s1, s2);
+  ASTNode bba4 = bm->BBForm(a4);
+  cout << "bitblasted a4 " << endl << bba4 << endl;
+
+  ASTNode a5 = bm->CreateNode(BVLE, s1, s2);
+  ASTNode bba5 = bm->BBForm(a5);
+  cout << "bitblasted a5 " << endl << bba5 << endl;
+
+  return 0;
+}
diff --git a/stp/AST/cnftest.cpp b/stp/AST/cnftest.cpp
new file mode 100644
index 00000000..7ce270c8
--- /dev/null
+++ b/stp/AST/cnftest.cpp
@@ -0,0 +1,47 @@
+// -*- c++ -*-
+
+// Test program for CNF conversion.
+
+#include "AST.h"
+
+using namespace BEEV;
+
+int main()
+{
+  const int size = 1;
+  
+  BeevMgr *bm = new BeevMgr();
+  ASTNode s1 = bm->CreateSymbol("x");
+  s1.SetValueWidth(size);
+  
+  cout << "s1" <<  s1 << endl;
+  ASTNode s2 = bm->CreateSymbol("y");
+  s2.SetValueWidth(size);
+
+  cout << "s2" <<  s2 << endl;
+  ASTNode s3 = bm->CreateSymbol("z");
+  s3.SetValueWidth(size);
+  
+  cout << "s3" <<  s3 << endl;
+
+  ASTNode bbs1 = bm->BBForm(s1);
+  cout << "bitblasted s1" << endl << bbs1 << endl;
+  bm->PrintClauseList(cout, bm->ToCNF(bbs1));
+
+  ASTNode a2 = bm->CreateNode(AND, s1, s2);
+  ASTNode bba2 = bm->BBForm(a2);
+  cout << "bitblasted a2" << endl << bba2 << endl;
+  bm->PrintClauseList(cout, bm->ToCNF(bba2));
+
+  ASTNode a3 = bm->CreateNode(OR, s1, s2);
+  ASTNode bba3 = bm->BBForm(a3);
+  cout << "bitblasted a3" << endl << bba3 << endl;
+  bm->PrintClauseList(cout, bm->ToCNF(bba3));
+
+  ASTNode a4 = bm->CreateNode(EQ, s1, s2);
+  ASTNode bba4 = bm->BBForm(a4);
+  cout << "bitblasted a4 " << endl << bba4 << endl;
+
+  bm->PrintClauseList(cout, bm->ToCNF(bba4));
+
+}
diff --git a/stp/AST/genkinds.pl b/stp/AST/genkinds.pl
new file mode 100755
index 00000000..7944832b
--- /dev/null
+++ b/stp/AST/genkinds.pl
@@ -0,0 +1,123 @@
+#!/usr/bin/perl -w
+
+#AUTHORS: Vijay Ganesh, David L. Dill BEGIN DATE: November, 2005
+#LICENSE: Please view LICENSE file in the home dir of this Program
+#given a file containing kind names, one per line produces .h and .cpp
+#files for the kinds.
+
+#globals
+@kindnames = ();
+$minkids = 0;
+$maxkids = 0;
+@cat_bits = ();
+@category_names = ();
+%cat_index = ();
+
+$now = localtime time;
+
+sub read_kind_defs {
+    open(KFILE, "< ASTKind.kinds") || die "Cannot open .kinds file: $!\n";
+    @kindlines = <KFILE>;
+    close(KFILE)
+}
+
+# create lists of things indexed by kinds.
+sub split_fields {
+    my $kind_cat_bits;
+    # matches anything with three whitespace-delimited alphanumeric fields,
+    # followed by rest of line.  Automatically ignores lines beginning with '#' and blank lines.
+    for (@kindlines) {
+	if (/Categories:\s+(.*)/) {
+	    @category_names = split(/\s+/, $1);
+	    $i = 0;
+	    for (@category_names) {
+		$cat_index{$_} = $i++;
+		# print "cat_index{$_} = $i\n";
+	    }
+	}
+	elsif (/^(\w+)\s+(\w+)\s+(\w+|-)\s+(.*)/) {
+	    push(@kindnames, $1);
+	    push(@minkids, $2);
+	    push(@maxkids, $3);
+	    @kind_cats = split(/\s+/, $4);
+	    # build a bit vector of categories.
+	    $kind_cat_bits = 0;
+	    for (@kind_cats) {
+		$kind_cat_bits |= (1 << int($cat_index{$_}));
+	    }
+	    push(@cat_bits, $kind_cat_bits); 
+	}
+    }
+}
+
+sub gen_h_file {
+    open(HFILE, "> ASTKind.h") || die "Cannot open .h file: $!\n";
+
+    print HFILE 
+	"// -*- c++ -*-\n",
+	"#ifndef TESTKINDS_H\n",
+	"#define TESTKINDS_H\n",
+	"// Generated automatically by genkinds.pl from ASTKind.kinds $now.\n",
+	"// Do not edit\n",
+	"namespace BEEV {\n  typedef enum {\n";
+
+    for (@kindnames) {
+	print HFILE "    $_,\n";
+    }
+
+    print HFILE 
+	"} Kind;\n\n",
+	"extern unsigned char _kind_categories[];\n\n";
+
+    # For category named "cat", generate functions "bool is_cat_kind(k);"
+
+
+    for (@category_names) {
+	my $catname = $_;
+	my $kind_cat_bit = (1 << int($cat_index{$catname}));
+	print HFILE "inline bool is_", $catname, "_kind(Kind k) { return (_kind_categories[k] & $kind_cat_bit); }\n\n"
+    }
+
+    print HFILE
+	"extern const char *_kind_names[];\n\n",
+	"/** Prints symbolic name of kind */\n",
+	"inline ostream& operator<<(ostream &os, const Kind &kind) { os << _kind_names[kind]; return os; }\n",
+	"\n\n",
+	"};  // end namespace\n",
+	"\n\n#endif\n";
+
+    close(HFILE);
+}
+
+# generate the .cpp file
+
+sub gen_cpp_file {
+    open(CPPFILE, "> ASTKind.cpp") || die "Cannot open .h file: $!\n";
+
+    print CPPFILE
+	"// Generated automatically by genkinds.h from ASTKind.kinds $now.\n",
+	"// Do not edit\n",
+	"namespace BEEV {\n",
+	"const char * _kind_names[] =  {\n";
+    for (@kindnames) {
+	print CPPFILE "   \"$_\",\n";
+    }
+    print CPPFILE "};\n\n";
+
+    # category bits
+    print CPPFILE
+	"unsigned char _kind_categories[] = {\n";
+    for (@cat_bits) {
+	print CPPFILE "   $_,\n";
+    }
+    print CPPFILE 
+	"};\n",
+	"\n};  // end namespace\n";
+
+    close(CPPFILE);
+}
+
+&read_kind_defs;
+&split_fields;
+&gen_h_file;
+&gen_cpp_file;
diff --git a/stp/INSTALL b/stp/INSTALL
new file mode 100644
index 00000000..12cee121
--- /dev/null
+++ b/stp/INSTALL
@@ -0,0 +1,10 @@
+1. To install STP perform the following steps on your Unix/GNU-Linux/MacOS X commandline:
+
+./configure --with-prefix=$HOME (or another installation directory)
+make clean
+make
+make install
+
+2. To test the system after installation:
+
+make regressall
\ No newline at end of file
diff --git a/stp/LICENSE b/stp/LICENSE
new file mode 100644
index 00000000..41029509
--- /dev/null
+++ b/stp/LICENSE
@@ -0,0 +1,17 @@
+/*****************************************************************************/
+/*  AUTHORS:    Vijay Ganesh, David L. Dill             DATE: Nov 2005       */
+/*****************************************************************************/
+/* Copyright (C) 2005 by the Board of Trustees of Leland Stanford            */
+/* Junior University.                                                        */
+/*                                                                           */
+/* License to use, copy, modify, sell and/or distribute this software        */
+/* and its documentation for any purpose is hereby granted without           */
+/* royalty, subject to the terms and conditions defined in the \ref          */
+/* LICENSE file provided with this distribution.  In particular:             */
+/*                                                                           */
+/* - The above copyright notice and this permission notice must appear       */
+/* in all copies of the software and related documentation.                  */
+/*                                                                           */
+/* - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,               */
+/* EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.                           */
+/*****************************************************************************/
diff --git a/stp/Makefile b/stp/Makefile
new file mode 100644
index 00000000..f66644a5
--- /dev/null
+++ b/stp/Makefile
@@ -0,0 +1,64 @@
+ # STP (Simple Theorem Prover) top level makefile
+ #
+ # To make in debug mode, type 'make "CLFAGS=-ggdb"
+ # To make in optimized mode, type 'make "CFLAGS=-O2" 
+
+include Makefile.common
+
+BINARIES=bin/stp
+LIBS=AST/libast.a sat/libsatsolver.a simplifier/libsimplifier.a bitvec/libconsteval.a constantbv/libconstantbv.a c_interface/libcinterface.a
+DIRS=AST sat simplifier bitvec c_interface constantbv parser
+
+# NB: the TAGS target is a hack to get around this recursive make nonsense
+# we want all the source and header files generated before we make tags
+.PHONY: all
+all: lib/libstp.a bin/stp include/stp/c_interface.h
+
+AST/libast.a:
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+sat/libsatsolver.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+simplifier/libsimplifier.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+bitvec/libconsteval.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+constantbv/libconstantbv.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+c_interface/libcinterface.a: AST/libast.a
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+parser/parser: $(LIBS)
+	@$(MAKE) -q -C `dirname $@` || $(MAKE) -C `dirname $@`
+
+lib/libstp.a: parser/parser $(LIBS)
+	@mkdir -p lib
+	rm -f $@
+	@for dir in $(DIRS); do \
+		$(AR) rc $@ $$dir/*.o; \
+	done
+	$(RANLIB) $@
+
+bin/stp: parser/parser $(LIBS)
+	@mkdir -p bin
+	@cp parser/parser $@
+
+include/stp/c_interface.h: $(LIBS)
+	@mkdir -p include/stp
+	@cp c_interface/c_interface.h $@
+
+.PHONY: clean
+clean:
+	rm -rf *~
+	rm -rf *.a
+	rm -rf lib/*.a
+	rm -rf bin/*~
+	rm -rf bin/stp
+	rm -rf *.log
+	rm -f TAGS
+	$(MAKE) clean -C AST
+	$(MAKE) clean -C sat
+	$(MAKE) clean -C simplifier
+	$(MAKE) clean -C bitvec
+	$(MAKE) clean -C parser
+	$(MAKE) clean -C c_interface
+	$(MAKE) clean -C constantbv
+
diff --git a/stp/Makefile.common.in b/stp/Makefile.common.in
new file mode 100644
index 00000000..a88e35ed
--- /dev/null
+++ b/stp/Makefile.common.in
@@ -0,0 +1,16 @@
+# -*- Makefile -*-
+
+CFLAGS := @CFLAGS@
+CXXFLAGS := @CXXFLAGS@ -O2
+LDFLAGS := @LDFLAGS@ -lstdc++
+
+# use the darmin test as a proxy for detecting Mac OS X
+ifneq ($(shell uname -s), Darwin)
+  CFLAGS += -static
+endif
+
+CXXFLAGS += -Wall -DEXT_HASH_MAP
+
+LEX := flex
+YACC := bison -d -y --debug -v
+RANLIB := ranlib
diff --git a/stp/README b/stp/README
new file mode 100644
index 00000000..da0f9b96
--- /dev/null
+++ b/stp/README
@@ -0,0 +1,26 @@
+/********************************************************************
+ * PROGRAM NAME: STP (Simple Theorem Prover)	
+ *		
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *	
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+
+Install
+-------
+See INSTALL file in the home dir of this program
+
+Authors
+-------
+Vijay Ganesh, Stanford University, Stanford, CA, USA
+David L. Dill, Stanford University, Stanford, CA, USA
+Tim King, Stanford University, Stanford, CA, USA
+
+Makefiles and configuration scripts
+------------------------------------
+Cristian Cadar, Stanford University, Stanford, CA, USA
+Paul Twohey, Stanford University, Stanford, CA, USA
+Sergey Berezin, ATG Synopsys, Mountain View, CA, USA
+Clark Barrett, New York University, New York, NY, USA
diff --git a/stp/bitvec/Makefile b/stp/bitvec/Makefile
new file mode 100644
index 00000000..eb6e1121
--- /dev/null
+++ b/stp/bitvec/Makefile
@@ -0,0 +1,11 @@
+include ../Makefile.common
+
+SRCS = consteval.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libconsteval.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:	
+	rm -rf *.o *~ *.a .#*
diff --git a/stp/bitvec/consteval.cpp b/stp/bitvec/consteval.cpp
new file mode 100644
index 00000000..7cb8dfcb
--- /dev/null
+++ b/stp/bitvec/consteval.cpp
@@ -0,0 +1,1044 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+namespace BEEV {
+
+  //error printing
+  static void BVConstEvaluatorError(CONSTANTBV::ErrCode e, const ASTNode& t){
+    std::string ss("BVConstEvaluator:");
+    ss += (const char*)BitVector_Error(e);	
+    FatalError(ss.c_str(), t);
+  }
+
+#ifndef NATIVE_C_ARITH
+  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
+    ASTNode OutputNode;
+    Kind k = t.GetKind();
+
+    if(CheckSolverMap(t,OutputNode))
+      return OutputNode;
+    OutputNode = t;
+
+    unsigned int inputwidth = t.GetValueWidth();
+    unsigned int outputwidth = inputwidth;
+    CBV output = NULL;
+
+    CBV tmp0 = NULL;
+    CBV tmp1 = NULL;
+
+    //saving some typing. BVPLUS does not use these variables. if the
+    //input BVPLUS has two nodes, then we want to avoid setting these
+    //variables.
+    if(1 == t.Degree() ){
+      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+    }else if(2 == t.Degree() && k != BVPLUS ) {
+      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+      tmp1 = BVConstEvaluator(t[1]).GetBVConst();
+    }
+
+    switch(k) {
+    case UNDEFINED:
+    case READ:
+    case WRITE:
+    case SYMBOL:
+      FatalError("BVConstEvaluator: term is not a constant-term",t);
+      break;
+    case BVCONST:
+      //FIXME Handle this special case better
+      OutputNode = t;
+      break;
+    case BVNEG:{
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_Complement(output,tmp0);
+      OutputNode = CreateBVConst(output,outputwidth);
+      break;
+    }
+    case BVSX: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      //unsigned * out0 = BVConstEvaluator(t[0]).GetBVConst();
+      unsigned t0_width = t[0].GetValueWidth();
+      if(inputwidth == t0_width) {
+        CONSTANTBV::BitVector_Copy(output, tmp0);
+        OutputNode = CreateBVConst(output, outputwidth);    
+      }
+      else {
+        bool topbit_sign = (CONSTANTBV::BitVector_Sign(tmp0) < 0 );
+
+        if(topbit_sign){
+          CONSTANTBV::BitVector_Fill(output);
+        }
+        CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, 0, t0_width);
+        OutputNode = CreateBVConst(output, outputwidth);    
+      }
+      break;
+    }
+    case BVAND: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_Intersection(output,tmp0,tmp1);
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    case BVOR: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_Union(output,tmp0,tmp1);
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    case BVXOR: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::Set_ExclusiveOr(output,tmp0,tmp1);
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    case BVSUB: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      bool carry = false;
+      CONSTANTBV::BitVector_sub(output,tmp0,tmp1,&carry);
+      OutputNode = CreateBVConst(output, outputwidth);    
+      break;
+    }
+    case BVUMINUS: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CONSTANTBV::BitVector_Negate(output, tmp0);
+      OutputNode = CreateBVConst(output, outputwidth);    
+      break;
+    }
+    case BVEXTRACT: {
+      output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      tmp0 = BVConstEvaluator(t[0]).GetBVConst();
+      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+      unsigned int len = hi-low+1;
+
+      CONSTANTBV::BitVector_Destroy(output);
+      output = CONSTANTBV::BitVector_Create(len, false);
+      CONSTANTBV::BitVector_Interval_Copy(output, tmp0, 0, low, len);
+      outputwidth = len;
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    //FIXME Only 2 inputs?
+    case BVCONCAT: {
+       output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      unsigned t0_width = t[0].GetValueWidth();
+      unsigned t1_width = t[1].GetValueWidth();
+      CONSTANTBV::BitVector_Destroy(output);
+      
+      output = CONSTANTBV::BitVector_Concat(tmp0, tmp1);
+      outputwidth = t0_width + t1_width;
+      OutputNode = CreateBVConst(output, outputwidth);
+      
+      break;
+    }
+    case BVMULT: {
+       output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CBV tmp = CONSTANTBV::BitVector_Create(2*inputwidth,true);
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(tmp,tmp0,tmp1);
+      
+      if(0 != e) {
+        BVConstEvaluatorError(e,t);
+      }
+      //FIXME WHAT IS MY OUTPUT???? THE SECOND HALF of tmp?
+      //CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, inputwidth, inputwidth);
+      CONSTANTBV::BitVector_Interval_Copy(output, tmp, 0, 0, inputwidth);
+      OutputNode = CreateBVConst(output, outputwidth);
+      CONSTANTBV::BitVector_Destroy(tmp);
+      break;
+    }
+    case BVPLUS: {
+       output = CONSTANTBV::BitVector_Create(inputwidth,true);
+      bool carry = false;
+      ASTVec c = t.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	CBV kk = BVConstEvaluator(*it).GetBVConst();
+	CONSTANTBV::BitVector_add(output,output,kk,&carry);
+	carry = false;
+	//CONSTANTBV::BitVector_Destroy(kk);
+      }
+      OutputNode = CreateBVConst(output, outputwidth);
+      break;
+    }
+    //FIXME ANOTHER SPECIAL CASE
+    case SBVDIV:
+    case SBVMOD:{
+      OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
+      break;
+    }
+    case BVDIV: 
+    case BVMOD: {
+      CBV quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+      CBV remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+      
+      // tmp0 is dividend, tmp1 is the divisor
+      //All parameters to BitVector_Div_Pos must be distinct unlike BitVector_Divide
+      //FIXME the contents of the second parameter to Div_Pos is destroyed
+      //As tmp0 is currently the same as the copy belonging to an ASTNode t[0]
+      //this must be copied.
+      tmp0 = CONSTANTBV::BitVector_Clone(tmp0);      
+      CONSTANTBV::ErrCode e= CONSTANTBV::BitVector_Div_Pos(quotient,tmp0,tmp1,remainder);
+      CONSTANTBV::BitVector_Destroy(tmp0);
+      
+      if(0 != e) {
+	//error printing
+	if(counterexample_checking_during_refinement) {
+          output = CONSTANTBV::BitVector_Create(inputwidth,true);
+	  OutputNode = CreateBVConst(output, outputwidth);
+	  bvdiv_exception_occured = true;
+          
+          //  CONSTANTBV::BitVector_Destroy(output);
+	  break;
+	}
+	else {
+	  BVConstEvaluatorError(e,t);
+	}
+      } //end of error printing
+
+      //FIXME Not very standard in the current scheme
+      if(BVDIV == k){
+        OutputNode = CreateBVConst(quotient, outputwidth);
+        CONSTANTBV::BitVector_Destroy(remainder);
+      }else{
+        OutputNode = CreateBVConst(remainder, outputwidth);
+        CONSTANTBV::BitVector_Destroy(quotient);
+      }
+
+      break;
+    }
+    case ITE:
+      if(ASTTrue == t[0])
+	OutputNode = BVConstEvaluator(t[1]);
+      else if(ASTFalse == t[0])
+	OutputNode = BVConstEvaluator(t[2]);
+      else
+	FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
+      break;
+    case EQ: 
+      if(CONSTANTBV::BitVector_equal(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case NEQ:
+      if(!CONSTANTBV::BitVector_equal(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLT:
+      if(-1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVGT:
+      if(1 == CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(tmp0,tmp1);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    case BVSLT:
+      if(-1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSLE: {
+      signed int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGT:
+      if(1 == CONSTANTBV::BitVector_Compare(tmp0,tmp1))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSGE: {
+      int comp = CONSTANTBV::BitVector_Compare(tmp0,tmp1);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    default:
+      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+      break;
+    }
+/*
+    if(BVCONST != k){
+     cerr<<inputwidth<<endl;
+     cerr<<"------------------------"<<endl;
+     t.LispPrint(cerr);
+     cerr<<endl;
+     OutputNode.LispPrint(cerr);
+     cerr<<endl<<"------------------------"<<endl;
+    }
+*/
+    UpdateSolverMap(t,OutputNode);
+    //UpdateSimplifyMap(t,OutputNode,false);
+    return OutputNode;
+  }
+#else
+  //accepts 64 bit BVConst and sign extends it
+  static unsigned long long int SXBVConst64(const ASTNode& t) {
+    unsigned long long int c = t.GetBVConst();
+    unsigned int len = t.GetValueWidth();
+
+    unsigned long long int mask = 1;
+    mask = mask << len-1;
+
+    bool TopBit = (c & mask) ? true : false;
+    if(!TopBit) return c;
+    
+    unsigned long long int sign = 0xffffffffffffffffLL;
+    sign = sign << len-1;
+
+    return (c | sign);
+  }
+
+  //FIXME: Ideally I would like the ASTNodes to be able to operate on
+  //themselves (add, sub, concat, etc.) rather than doing a
+  //GetBVConst() and then do the operation externally. For now,
+  //this is the fastest path to completion.
+  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
+    //cerr << "inside begin bcconstevaluator: " << t << endl;
+
+    ASTNode OutputNode;
+    if(CheckSolverMap(t,OutputNode))
+      return OutputNode;
+    OutputNode = ASTUndefined;
+
+    Kind k = t.GetKind();
+    unsigned long long int output = 0;
+    unsigned inputwidth = t.GetValueWidth();
+    ASTNode t0 = ASTUndefined;
+    ASTNode t1 = ASTUndefined;
+    if(2 == t.Degree()) {
+      t0 = BVConstEvaluator(t[0]);
+      t1 = BVConstEvaluator(t[1]);
+    }
+    switch(k) {
+    case READ:
+    case UNDEFINED:
+    case WRITE:
+    case SYMBOL:
+      cerr << t;
+      FatalError("BVConstEvaluator: term is not a constant-term",t);
+      break;
+    case BVCONST:
+      return t;
+      break;
+    case BVNEG:
+      //compute bitwise negation in C
+      output = ~(BVConstEvaluator(t[0]).GetBVConst());
+      break;
+    case BVSX:
+      output = SXBVConst64(BVConstEvaluator(t[0]));    
+      break;
+    case BVAND:
+      output = t0.GetBVConst() & t1.GetBVConst();
+      break;
+    case BVOR:
+      output = t0.GetBVConst() | t1.GetBVConst();
+      break;
+    case BVXOR:
+      output = t0.GetBVConst() ^ t1.GetBVConst();
+      break;
+    case BVSUB:
+      output = t0.GetBVConst() - t1.GetBVConst();
+      break;
+    case BVUMINUS:
+      output = ~(BVConstEvaluator(t[0]).GetBVConst()) + 1;
+      break;
+    case BVEXTRACT: {
+      unsigned long long int val = BVConstEvaluator(t[0]).GetBVConst();
+      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+
+      if(!(0 <= hi <= 64))
+	FatalError("ConstantEvaluator: hi bit in BVEXTRACT is > 32bits",t);
+      if(!(0 <= low <= hi <= 64))
+	FatalError("ConstantEvaluator: low bit in BVEXTRACT is > 32bits or hi",t);
+
+      //64 bit mask.
+      unsigned long long int mask1 = 0xffffffffffffffffLL;
+      mask1 >>= 64-(hi+1);
+      
+      //extract val[hi:0]
+      val &= mask1;
+      //extract val[hi:low]
+      val >>= low;
+      output = val;
+      break;
+    }
+    case BVCONCAT: {
+      unsigned long long int q = BVConstEvaluator(t0).GetBVConst();
+      unsigned long long int r = BVConstEvaluator(t1).GetBVConst();
+
+      unsigned int qlen = t[0].GetValueWidth();
+      unsigned int rlen = t[1].GetValueWidth();
+      unsigned int slen = t.GetValueWidth();
+      if(!(0 <  qlen + rlen  <= 64))
+	FatalError("BVConstEvaluator:"
+		   "lengths of childnodes of BVCONCAT are > 64:",t);
+
+      //64 bit mask for q
+      unsigned long long int qmask = 0xffffffffffffffffLL;     
+      qmask >>= 64-qlen;
+      //zero the useless bits of q
+      q &= qmask;
+
+      //64 bit mask for r
+      unsigned long long int rmask = 0xffffffffffffffffLL;     
+      rmask >>= 64-rlen;
+      //zero the useless bits of r
+      r &= rmask;
+      
+      //concatenate
+      q <<= rlen;
+      q |= r;
+
+      //64 bit mask for output s
+      unsigned long long int smask = 0xffffffffffffffffLL;
+      smask >>= 64-slen;
+      
+      //currently q has the output
+      output = q;      
+      output &= smask;
+      break;
+    }
+    case BVMULT: {
+      output = t0.GetBVConst() * t1.GetBVConst();
+
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 - inputwidth);
+      output &= mask;
+      break;
+    }
+    case BVPLUS: {
+      ASTVec c = t.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
+	output += BVConstEvaluator(*it).GetBVConst();
+
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 -inputwidth);
+      output &= mask;
+      break;
+    }
+    case SBVDIV:
+    case SBVMOD: {
+      output = BVConstEvaluator(TranslateSignedDivMod(t)).GetBVConst();
+      break;
+    }
+    case BVDIV: {
+      if(0 == t1.GetBVConst()) {
+	//if denominator is 0 then 
+	//  (if refinement is ON then output is set to 0) 
+	//   (else produce a fatal error)
+	if(counterexample_checking_during_refinement) {
+	  output = 0;
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+	}
+      }
+
+      output = t0.GetBVConst() / t1.GetBVConst();
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 - inputwidth);
+      output &= mask;
+      break;
+    }
+    case BVMOD: {
+      if(0 == t1.GetBVConst()) {
+	//if denominator is 0 then 
+	//  (if refinement is ON then output is set to 0) 
+	//   (else produce a fatal error)
+	if(counterexample_checking_during_refinement) {
+	  output = 0;
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  FatalError("BVConstEvaluator: divide by zero not allowed:",t);
+	}
+      }
+
+      output = t0.GetBVConst() % t1.GetBVConst();
+      //64 bit mask
+      unsigned long long int mask = 0xffffffffffffffffLL;
+      mask = mask >> (64 - inputwidth);
+      output &= mask;
+      break;
+    }
+    case ITE:
+      if(ASTTrue == t[0])
+	OutputNode = BVConstEvaluator(t[1]);
+      else if(ASTFalse == t[0])
+	OutputNode = BVConstEvaluator(t[2]);
+      else
+	FatalError("BVConstEvaluator:" 
+		   "ITE condiional must be either TRUE or FALSE:",t);
+      break;
+    case EQ:
+      if(t0.GetBVConst() == t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case NEQ:
+      if(t0.GetBVConst() != t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+      break;
+    case BVLT: {
+      unsigned long long n0 = t0.GetBVConst();
+      unsigned long long n1 = t1.GetBVConst();
+      if(n0 < n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVLE:
+      if(t0.GetBVConst() <= t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGT:
+      if(t0.GetBVConst() > t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGE:
+      if(t0.GetBVConst() >= t1.GetBVConst())
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSLT: {
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 < n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSLE: {
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 <= n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGT: {   
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 > n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGE: {   
+      signed long long int n0 = SXBVConst64(t0);
+      signed long long int n1 = SXBVConst64(t1);
+      if(n0 >= n1)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    default:
+      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+      break;
+    }    
+   
+    if(ASTTrue  != OutputNode && ASTFalse != OutputNode)
+      OutputNode = CreateBVConst(inputwidth, output);
+    UpdateSolverMap(t,OutputNode);
+    //UpdateSimplifyMap(t,OutputNode,false);
+    return OutputNode;
+  } //End of BVConstEvaluator
+#endif
+//In the block below is the old string based version
+//It is included here as an easy reference while the current code is being worked on.
+
+/*
+  ASTNode BeevMgr::BVConstEvaluator(const ASTNode& t) {
+    ASTNode OutputNode;
+    Kind k = t.GetKind();
+
+    if(CheckSolverMap(t,OutputNode))
+      return OutputNode;
+    OutputNode = t;
+
+    unsigned int inputwidth = t.GetValueWidth();
+    unsigned * output = CONSTANTBV::BitVector_Create(inputwidth,true);
+    unsigned * One = CONSTANTBV::BitVector_Create(inputwidth,true);
+    CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(One, (unsigned char*)"1");
+    //error printing
+    if(0 != e) {
+      std::string ss("BVConstEvaluator:");
+      ss += (const char*)BitVector_Error(e);	
+      FatalError(ss.c_str(), t);
+    }
+
+    unsigned * Zero = CONSTANTBV::BitVector_Create(inputwidth,true);
+    unsigned int * iii = One;
+    unsigned int * jjj = Zero;
+
+    //saving some typing. BVPLUS does not use these variables. if the
+    //input BVPLUS has two nodes, then we want to avoid setting these
+    //variables.
+    if(2 == t.Degree() && k != BVPLUS && k != BVCONCAT) {
+      iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+      jjj = ConvertToCONSTANTBV(BVConstEvaluator(t[1]).GetBVConst());
+    }
+
+    char * cccc;
+    switch(k) {
+    case UNDEFINED:
+    case READ:
+    case WRITE:
+    case SYMBOL:
+      FatalError("BVConstEvaluator: term is not a constant-term",t);
+      break;
+    case BVCONST:
+      OutputNode = t;
+      break;
+    case BVNEG:{
+      //AARON
+      if (iii != One) free(iii);
+      //AARON
+
+      iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());     
+      CONSTANTBV::Set_Complement(output,iii);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+      break;
+    }
+    case BVSX: {
+      unsigned * out0 = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+      unsigned t0_width = t[0].GetValueWidth();
+      if(inputwidth == t0_width) {
+	cccc = (char *)CONSTANTBV::BitVector_to_Bin(out0);
+	OutputNode = CreateBVConst(cccc,2);
+
+	//AARON
+	free(cccc);
+	//AARON
+
+	CONSTANTBV::BitVector_Destroy(out0);     
+      }
+      else {
+	// FIXME: (Dill) I'm guessing that BitVector sign returns 1 if the
+	// number is positive, 0 if 0, and -1 if negative.  But I'm only
+	// guessing.
+	signed int topbit_sign = (CONSTANTBV::BitVector_Sign(out0) < 0);
+	//out1 is the sign-extension bits
+	unsigned * out1 =  CONSTANTBV::BitVector_Create(inputwidth-t0_width,true);      
+	if(topbit_sign)
+	  CONSTANTBV::BitVector_Fill(out1);
+
+	//AARON
+	CONSTANTBV::BitVector_Destroy(output);
+	//AARON
+
+	output = CONSTANTBV::BitVector_Concat(out1,out0);
+	cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+	OutputNode = CreateBVConst(cccc,2);
+
+	//AARON
+	free(cccc);
+	//AARON
+
+	CONSTANTBV::BitVector_Destroy(out0);
+	CONSTANTBV::BitVector_Destroy(out1);
+      }
+      break;
+    }
+    case BVAND: {
+      CONSTANTBV::Set_Intersection(output,iii,jjj);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+      
+      break;
+    }
+    case BVOR: {
+      CONSTANTBV::Set_Union(output,iii,jjj);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVXOR: {
+      CONSTANTBV::Set_ExclusiveOr(output,iii,jjj);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVSUB: {
+      bool carry = false;
+      CONSTANTBV::BitVector_sub(output,iii,jjj,&carry);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVUMINUS: {
+      bool carry = false;
+
+      //AARON
+      if (iii != One) free(iii);
+      //AARON
+
+      iii = ConvertToCONSTANTBV(BVConstEvaluator(t[0]).GetBVConst());
+      CONSTANTBV::Set_Complement(output,iii);
+      CONSTANTBV::BitVector_add(output,output,One,&carry);
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case BVEXTRACT: {
+      string s(BVConstEvaluator(t[0]).GetBVConst());
+      unsigned int hi = GetUnsignedConst(BVConstEvaluator(t[1]));
+      unsigned int low = GetUnsignedConst(BVConstEvaluator(t[2]));
+
+      //length of substr to chop
+      unsigned int len = hi-low+1;
+      //distance from MSB
+      hi = s.size()-1 - hi;      
+      string ss = s.substr(hi,len);
+      OutputNode = CreateBVConst(ss.c_str(),2);
+      break;
+    }
+    case BVCONCAT: {
+      string s(BVConstEvaluator(t[0]).GetBVConst());
+      string r(BVConstEvaluator(t[1]).GetBVConst());
+  
+      string q(s+r);
+      OutputNode = CreateBVConst(q.c_str(),2);
+      break;
+    }
+    case BVMULT: {
+      unsigned * output1 = CONSTANTBV::BitVector_Create(2*inputwidth,true);
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Multiply(output1,iii,jjj);
+      //error printing
+      if(0 != e) {
+	std::string ss("BVConstEvaluator:");
+	ss += (const char*)BitVector_Error(e);	
+	//destroy all the CONSTANTBV bitvectors
+	CONSTANTBV::BitVector_Destroy(iii);
+	CONSTANTBV::BitVector_Destroy(jjj);       
+	CONSTANTBV::BitVector_Destroy(One);
+	CONSTANTBV::BitVector_Destroy(Zero);
+	FatalError(ss.c_str(), t);
+      }
+
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output1);
+      std::string s(cccc);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      s = s.substr(inputwidth,inputwidth);
+      OutputNode = CreateBVConst(s.c_str(),2);
+      CONSTANTBV::BitVector_Destroy(output1);
+      break;
+    }
+    case BVPLUS: {
+      bool carry = false;
+      ASTVec c = t.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	unsigned int * kk = ConvertToCONSTANTBV(BVConstEvaluator(*it).GetBVConst());
+	CONSTANTBV::BitVector_add(output,output,kk,&carry);
+	carry = false;
+	CONSTANTBV::BitVector_Destroy(kk);
+      }
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(output);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      //AARON
+
+      break;
+    }
+    case SBVDIV:
+    case SBVMOD: {
+      OutputNode = BVConstEvaluator(TranslateSignedDivMod(t));
+      break;
+    }
+    case BVDIV: {      
+      unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+      unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+      // iii is dividend, jjj is the divisor
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
+
+      if(0 != e) {
+	//error printing
+	if(counterexample_checking_during_refinement) {
+	  OutputNode = CreateZeroConst(inputwidth);
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  std::string ss("BVConstEvaluator:");
+	  ss += (const char*)BitVector_Error(e);	
+	  //destroy all the CONSTANTBV bitvectors
+	  CONSTANTBV::BitVector_Destroy(iii);
+	  CONSTANTBV::BitVector_Destroy(jjj);       
+	  CONSTANTBV::BitVector_Destroy(One);
+	  CONSTANTBV::BitVector_Destroy(Zero);
+
+	  //AARON
+	  iii = jjj = One = Zero = NULL;
+	  //AARON
+
+	  FatalError(ss.c_str(), t);
+	}
+      } //end of error printing
+
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(quotient);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      CONSTANTBV::BitVector_Destroy(quotient);
+      CONSTANTBV::BitVector_Destroy(remainder);
+      //AARON
+
+      break;
+    }
+   case BVMOD: {
+      unsigned * quotient = CONSTANTBV::BitVector_Create(inputwidth,true);
+      unsigned * remainder = CONSTANTBV::BitVector_Create(inputwidth,true);
+      // iii is dividend, jjj is the divisor
+      CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_Div_Pos(quotient,iii,jjj,remainder);
+
+      if(0 != e) {
+	//error printing
+	if(counterexample_checking_during_refinement) {
+	  OutputNode = CreateZeroConst(inputwidth);
+	  bvdiv_exception_occured = true;
+	  break;
+	}
+	else {
+	  std::string ss("BVConstEvaluator:");
+	  ss += (const char*)BitVector_Error(e);
+	  //destroy all the CONSTANTBV bitvectors
+	  CONSTANTBV::BitVector_Destroy(iii);
+	  CONSTANTBV::BitVector_Destroy(jjj);       
+	  CONSTANTBV::BitVector_Destroy(One);
+	  CONSTANTBV::BitVector_Destroy(Zero);	
+
+	  //AARON
+	  iii = jjj = One = Zero = NULL;
+	  //AARON
+
+	  FatalError(ss.c_str(), t);
+	}
+      } //end of errory printing
+
+      cccc = (char *)CONSTANTBV::BitVector_to_Bin(remainder);
+      OutputNode = CreateBVConst(cccc,2);
+
+      //AARON
+      free(cccc);
+      CONSTANTBV::BitVector_Destroy(quotient);
+      CONSTANTBV::BitVector_Destroy(remainder);
+      //AARON
+
+      break;
+    }
+    case ITE:
+      if(ASTTrue == t[0])
+	OutputNode = BVConstEvaluator(t[1]);
+      else if(ASTFalse == t[0])
+	OutputNode = BVConstEvaluator(t[2]);
+      else
+	FatalError("BVConstEvaluator: ITE condiional must be either TRUE or FALSE:",t);
+      break;
+    case EQ: 
+      if(CONSTANTBV::BitVector_equal(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case NEQ:
+      if(!CONSTANTBV::BitVector_equal(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLT:
+      if(-1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVLE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVGT:
+      if(1 == CONSTANTBV::BitVector_Lexicompare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVGE: {
+      int comp = CONSTANTBV::BitVector_Lexicompare(iii,jjj);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    case BVSLT:
+      if(-1 == CONSTANTBV::BitVector_Compare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSLE: {
+      signed int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
+      if(comp <= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    }
+    case BVSGT:
+      if(1 == CONSTANTBV::BitVector_Compare(iii,jjj))
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    case BVSGE: {
+      int comp = CONSTANTBV::BitVector_Compare(iii,jjj);
+      if(comp >= 0)
+	OutputNode = ASTTrue;
+      else
+	OutputNode = ASTFalse;
+      break;
+    } 
+    default:
+      FatalError("BVConstEvaluator: The input kind is not supported yet:",t);
+      break;
+    }
+
+
+
+    // //destroy all the CONSTANTBV bitvectors
+//     CONSTANTBV::BitVector_Destroy(iii);
+//     CONSTANTBV::BitVector_Destroy(jjj);
+//     CONSTANTBV::BitVector_Destroy(output);
+
+//     if(k == BVNEG || k == BVUMINUS)
+//       CONSTANTBV::BitVector_Destroy(One);
+//     else if(k == BVAND   || k == BVOR  || k == BVXOR   || k == BVSUB || 
+// 	    k == BVMULT  || k == EQ    || k == NEQ     || k == BVLT  ||
+// 	    k == BVLE    || k == BVGT  || k == BVGE    || k == BVSLT ||
+// 	    k == BVSLE   || k == BVSGT || k == BVSGE) {
+//       CONSTANTBV::BitVector_Destroy(One);
+//       CONSTANTBV::BitVector_Destroy(Zero);
+//     }    
+
+    //AARON
+    if (output != NULL) CONSTANTBV::BitVector_Destroy(output);
+    if (One != NULL) CONSTANTBV::BitVector_Destroy(One);
+    if (Zero != NULL) CONSTANTBV::BitVector_Destroy(Zero);
+    if (iii != NULL && iii != One) CONSTANTBV::BitVector_Destroy(iii);
+    if (jjj != NULL && jjj != Zero) CONSTANTBV::BitVector_Destroy(jjj);
+    //AARON
+   
+    UpdateSolverMap(t,OutputNode);
+    //UpdateSimplifyMap(t,OutputNode,false);
+    return OutputNode;
+  }
+
+
+  unsigned int * ConvertToCONSTANTBV(const char * s) {
+    unsigned int length = strlen(s);
+    unsigned char * ccc = (unsigned char *)s;
+    unsigned *  iii = CONSTANTBV::BitVector_Create(length,true);
+    CONSTANTBV::ErrCode e = CONSTANTBV::BitVector_from_Bin(iii,ccc);
+    //error printing
+    if(0 != e) {
+      cerr << "ConverToCONSTANTBV: wrong bin value: " << BitVector_Error(e);      
+      FatalError("");
+    }
+    
+    return iii;
+  }
+*/
+}; //end of namespace BEEV
diff --git a/stp/c_interface/Makefile b/stp/c_interface/Makefile
new file mode 100644
index 00000000..cf6b09d1
--- /dev/null
+++ b/stp/c_interface/Makefile
@@ -0,0 +1,13 @@
+include ../Makefile.common
+
+SRCS = c_interface.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libcinterface.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:	
+	rm -rf *.o *~ *.a .#*
+
+c_interface.o: c_interface.h
diff --git a/stp/c_interface/c_interface.cpp b/stp/c_interface/c_interface.cpp
new file mode 100644
index 00000000..f4e53114
--- /dev/null
+++ b/stp/c_interface/c_interface.cpp
@@ -0,0 +1,1548 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+#include "c_interface.h"
+
+#include <cstdlib>
+#include <cassert>
+#include <ostream>
+#include <iostream>
+#include "fdstream.h"
+#include "../AST/AST.h"
+
+//These typedefs lower the effort of using the keyboard to type (too
+//many overloaded meanings of the word type)
+typedef BEEV::ASTNode  node;
+typedef BEEV::ASTNode* nodestar;
+typedef BEEV::BeevMgr* bmstar;
+typedef BEEV::ASTVec   nodelist;
+typedef BEEV::CompleteCounterExample* CompleteCEStar;
+BEEV::ASTVec *decls = NULL;
+//vector<BEEV::ASTNode *> created_exprs;
+bool cinterface_exprdelete_on = false;
+
+void vc_setFlags(char c) {
+  std::string helpstring = "Usage: stp [-option] [infile]\n\n";
+  helpstring +=  "-r  : switch refinement off (optimizations are ON by default)\n";
+  helpstring +=  "-w  : switch wordlevel solver off (optimizations are ON by default)\n";
+  helpstring +=  "-a  : switch optimizations off (optimizations are ON by default)\n";
+  helpstring +=  "-s  : print function statistics\n";
+  helpstring +=  "-v  : print nodes \n";
+  helpstring +=  "-c  : construct counterexample\n";
+  helpstring +=  "-d  : check counterexample\n";
+  helpstring +=  "-p  : print counterexample\n";
+  helpstring +=  "-h  : help\n";
+  
+  switch(c) {
+  case 'a' :
+    BEEV::optimize = false;
+    BEEV::wordlevel_solve = false;
+    break;
+  case 'b':
+    BEEV::print_STPinput_back = true;
+    break;
+  case 'c':
+    BEEV::construct_counterexample = true;
+    break;
+  case 'd':
+    BEEV::construct_counterexample = true;
+    BEEV::check_counterexample = true;
+    break;
+  case 'e':
+    BEEV::variable_activity_optimize = true;
+    break;
+  case 'f':
+    BEEV::smtlib_parser_enable = true;
+    break;
+  case 'h':
+    cout << helpstring;
+    BEEV::FatalError("");
+    break;
+  case 'l' :
+    BEEV::linear_search = true;
+    break;
+  case 'n':
+    BEEV::print_output = true;
+    break;
+  case 'p':
+    BEEV::print_counterexample = true;
+    break;
+  case 'q':
+    BEEV::print_arrayval_declaredorder = true;
+    break;
+  case 'r':
+    BEEV::arrayread_refinement = false;
+    break;
+  case 's' :
+    BEEV::stats = true;
+    break;
+  case 'u':
+    BEEV::arraywrite_refinement = true;
+    break;  
+  case 'v' :
+    BEEV::print_nodes = true;
+    break;
+  case 'w':
+    BEEV::wordlevel_solve = false;
+    break;
+  case 'x':
+    cinterface_exprdelete_on = true;
+    break;
+  case 'z':
+    BEEV::print_sat_varorder = true;
+    break;
+  default:
+    std::string s = "C_interface: vc_setFlags: Unrecognized commandline flag:\n";
+    s += helpstring;
+    BEEV::FatalError(s.c_str());
+    break;
+  }
+}
+
+//Create a validity Checker. This is the global BeevMgr
+VC vc_createValidityChecker(void) {
+  vc_setFlags('d');
+#ifdef NATIVE_C_ARITH
+#else
+  CONSTANTBV::ErrCode c = CONSTANTBV::BitVector_Boot(); 
+  if(0 != c) {
+    cout << CONSTANTBV::BitVector_Error(c) << endl;
+    return 0;
+  }
+#endif
+  bmstar bm = new BEEV::BeevMgr();
+  decls = new BEEV::ASTVec();
+  //created_exprs.clear();
+  return (VC)bm;
+}
+
+// Expr I/O
+void vc_printExpr(VC vc, Expr e) {
+  //do not print in lisp mode
+  //bmstar b = (bmstar)vc;
+  BEEV::ASTNode q = (*(nodestar)e);
+  //   b->Begin_RemoveWrites = true;
+  //   BEEV::ASTNode q = b->SimplifyFormula_TopLevel(*((nodestar)e),false);
+  //   b->Begin_RemoveWrites = false;    
+  q.PL_Print(cout);
+}
+
+void vc_printExprFile(VC vc, Expr e, int fd) {
+  fdostream os(fd);
+  ((nodestar)e)->PL_Print(os);
+  //os.flush();
+}
+
+static void vc_printVarDeclsToStream(VC vc, ostream &os) {
+  for(BEEV::ASTVec::iterator i = decls->begin(),iend=decls->end();i!=iend;i++) {
+    node a = *i;
+    switch(a.GetType()) {
+    case BEEV::BITVECTOR_TYPE:
+      a.PL_Print(os);
+      os << " : BITVECTOR(" << a.GetValueWidth() << ");" << endl;
+      break;
+    case BEEV::ARRAY_TYPE:
+      a.PL_Print(os);
+      os << " : ARRAY " << "BITVECTOR(" << a.GetIndexWidth() << ") OF ";
+      os << "BITVECTOR(" << a.GetValueWidth() << ");" << endl;
+      break;
+    case BEEV::BOOLEAN_TYPE:
+      a.PL_Print(os);
+      os << " : BOOLEAN;" << endl;
+      break;
+    default:
+      BEEV::FatalError("vc_printDeclsToStream: Unsupported type",a);
+      break;
+    }
+  }
+}
+
+void vc_printVarDecls(VC vc) {
+  vc_printVarDeclsToStream(vc, cout);
+}
+
+static void vc_printAssertsToStream(VC vc, ostream &os, int simplify_print) {
+  bmstar b = (bmstar)vc;
+  BEEV::ASTVec v = b->GetAsserts();
+  for(BEEV::ASTVec::iterator i=v.begin(),iend=v.end();i!=iend;i++) {
+    b->Begin_RemoveWrites = true;
+    BEEV::ASTNode q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(*i,false) : *i;
+    q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(q,false) : q;
+    b->Begin_RemoveWrites = false;
+    os << "ASSERT( ";
+    q.PL_Print(os);
+    os << ");" << endl;
+  }
+}
+
+void vc_printAsserts(VC vc, int simplify_print) {
+  vc_printAssertsToStream(vc, cout, simplify_print);
+}
+
+void vc_printQueryStateToBuffer(VC vc, Expr e, char **buf, unsigned long *len, int simplify_print){
+  assert(vc);
+  assert(e);
+  assert(buf);
+  assert(len);
+  bmstar b = (bmstar)vc;
+
+  // formate the state of the query
+  stringstream os;
+  vc_printVarDeclsToStream(vc, os);
+  os << "%----------------------------------------------------" << endl;
+  vc_printAssertsToStream(vc, os, simplify_print);
+  os << "%----------------------------------------------------" << endl;
+  os << "QUERY( ";
+  b->Begin_RemoveWrites = true;
+  BEEV::ASTNode q = (simplify_print == 1) ? b->SimplifyFormula_TopLevel(*((nodestar)e),false) : *(nodestar)e;
+  b->Begin_RemoveWrites = false;    
+  q.PL_Print(os);
+  os << " );" << endl;
+
+  // convert to a c buffer
+  string s = os.str();
+  const char *cstr = s.c_str();
+  unsigned long size = s.size() + 1; // number of chars + terminating null
+  *buf = (char *)malloc(size);
+  if (!(*buf)) {
+    fprintf(stderr, "malloc(%lu) failed.", size);
+    assert(*buf);
+  }
+  *len = size;
+  memcpy(*buf, cstr, size);
+}
+
+void vc_printCounterExampleToBuffer(VC vc, char **buf, unsigned long *len) {
+  assert(vc);
+  assert(buf);
+  assert(len);
+  bmstar b = (bmstar)vc;
+
+  // formate the state of the query
+  std::ostringstream os;
+  BEEV::print_counterexample = true;
+  os << "COUNTEREXAMPLE BEGIN: \n";
+  b->PrintCounterExample(true,os);
+  os << "COUNTEREXAMPLE END: \n";
+
+  // convert to a c buffer
+  string s = os.str();
+  const char *cstr = s.c_str();
+  unsigned long size = s.size() + 1; // number of chars + terminating null
+  *buf = (char *)malloc(size);
+  if (!(*buf)) {
+    fprintf(stderr, "malloc(%lu) failed.", size);
+    assert(*buf);
+  }
+  *len = size;
+  memcpy(*buf, cstr, size);
+}
+
+void vc_printExprToBuffer(VC vc, Expr e, char **buf, unsigned long * len) {
+  stringstream os;
+  //bmstar b = (bmstar)vc;
+  BEEV::ASTNode q = *((nodestar)e);
+  // b->Begin_RemoveWrites = true;
+  //   BEEV::ASTNode q = b->SimplifyFormula_TopLevel(*((nodestar)e),false);
+  //   b->Begin_RemoveWrites = false;    
+  q.PL_Print(os);
+  //((nodestar)e)->PL_Print(os);
+  string s = os.str();
+  const char * cstr = s.c_str();
+  unsigned long size = s.size() + 1; // number of chars + terminating null
+  *buf = (char *)malloc(size);
+  *len = size;
+  memcpy(*buf, cstr, size);
+}
+
+void vc_printQuery(VC vc){
+  ostream& os = std::cout;
+  bmstar b = (bmstar)vc;
+  os << "QUERY(";
+  //b->Begin_RemoveWrites = true;
+  //BEEV::ASTNode q = b->SimplifyFormula_TopLevel(b->GetQuery(),false);
+  BEEV::ASTNode q = b->GetQuery();
+  //b->Begin_RemoveWrites = false;    
+  q.PL_Print(os);
+  // b->GetQuery().PL_Print(os);
+  os << ");" << endl;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Array-related methods                                                   //
+/////////////////////////////////////////////////////////////////////////////
+//! Create an array type
+Type vc_arrayType(VC vc, Type typeIndex, Type typeData) {
+  bmstar b = (bmstar)vc;
+  nodestar ti = (nodestar)typeIndex;
+  nodestar td = (nodestar)typeData;
+
+  if(!(ti->GetKind() == BEEV::BITVECTOR && (*ti)[0].GetKind() == BEEV::BVCONST))
+    BEEV::FatalError("Tyring to build array whose indextype i is not a BITVECTOR, where i = ",*ti);
+  if(!(td->GetKind()  == BEEV::BITVECTOR && (*td)[0].GetKind() == BEEV::BVCONST))
+    BEEV::FatalError("Trying to build an array whose valuetype v is not a BITVECTOR. where a = ",*td);
+  nodestar output = new node(b->CreateNode(BEEV::ARRAY,(*ti)[0],(*td)[0]));
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return (Type)output;
+}
+
+//! Create an expression for the value of array at the given index
+Expr vc_readExpr(VC vc, Expr array, Expr index) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)array;
+  nodestar i = (nodestar)index;
+  
+  b->BVTypeCheck(*a);
+  b->BVTypeCheck(*i);
+  node o = b->CreateTerm(BEEV::READ,a->GetValueWidth(),*a,*i);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+// //! Array update; equivalent to "array WITH [index] := newValue"
+Expr vc_writeExpr(VC vc, Expr array, Expr index, Expr newValue) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)array;
+  nodestar i = (nodestar)index;
+  nodestar n = (nodestar)newValue;
+
+  b->BVTypeCheck(*a);
+  b->BVTypeCheck(*i);
+  b->BVTypeCheck(*n);
+  node o = b->CreateTerm(BEEV::WRITE,a->GetValueWidth(),*a,*i,*n);
+  o.SetIndexWidth(a->GetIndexWidth());
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Context-related methods                                                 //
+/////////////////////////////////////////////////////////////////////////////
+//! Assert a new formula in the current context.  
+/*! The formula must have Boolean type. */
+void vc_assertFormula(VC vc, Expr e) {
+  nodestar a = (nodestar)e;
+  bmstar b = (bmstar)vc;
+
+  if(!BEEV::is_Form_kind(a->GetKind()))
+    BEEV::FatalError("Trying to assert a NON formula: ",*a);
+
+  b->BVTypeCheck(*a);
+  b->AddAssert(*a);
+}
+
+//! Check validity of e in the current context.
+/*!  If the result is true, then the resulting context is the same as
+ * the starting context.  If the result is false, then the resulting
+ * context is a context in which e is false.  e must have Boolean
+ * type. */
+int vc_query(VC vc, Expr e) {
+  nodestar a = (nodestar)e;
+  bmstar b = (bmstar)vc;
+
+ if(!BEEV::is_Form_kind(a->GetKind()))
+    BEEV::FatalError("CInterface: Trying to QUERY a NON formula: ",*a);
+
+  b->BVTypeCheck(*a);
+  b->AddQuery(*a);
+
+  const BEEV::ASTVec v = b->GetAsserts();
+  node o;
+  if(!v.empty()) {
+    if(v.size()==1)
+      return b->TopLevelSAT(v[0],*a);
+    else 
+      return b->TopLevelSAT(b->CreateNode(BEEV::AND,v),*a);
+  }
+  else
+    return b->TopLevelSAT(b->CreateNode(BEEV::TRUE),*a);
+}
+
+void vc_push(VC vc) {
+  bmstar b = (bmstar)vc;
+  b->ClearAllCaches();
+  b->Push();
+}
+
+void vc_pop(VC vc) {
+  bmstar b = (bmstar)vc;
+  b->Pop();
+}
+
+void vc_printCounterExample(VC vc) {
+  bmstar b = (bmstar)vc;
+  BEEV::print_counterexample = true;    
+  cout << "COUNTEREXAMPLE BEGIN: \n";
+  b->PrintCounterExample(true);
+  cout << "COUNTEREXAMPLE END: \n";
+}
+
+// //! Return the counterexample after a failed query.
+// /*! This method should only be called after a query which returns
+//  * false.  It will try to return the simplest possible set of
+//  * assertions which are sufficient to make the queried expression
+//  * false.  The caller is responsible for freeing the array when
+//  * finished with it.
+//  */
+
+Expr vc_getCounterExample(VC vc, Expr e) {
+  nodestar a = (nodestar)e;
+  bmstar b = (bmstar)vc;    
+
+  bool t = false;
+  if(b->CounterExampleSize())
+    t = true;
+  nodestar output = new node(b->GetCounterExample(t, *a));  
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+int vc_counterexample_size(VC vc) {
+  bmstar b = (bmstar)vc;
+  return b->CounterExampleSize();
+}
+
+WholeCounterExample vc_getWholeCounterExample(VC vc) {
+  bmstar b = (bmstar)vc;
+  CompleteCEStar c = 
+    new BEEV::CompleteCounterExample(b->GetCompleteCounterExample(), b);
+  return c;
+}
+
+Expr vc_getTermFromCounterExample(VC vc, Expr e, CompleteCEStar cc) {
+  //bmstar b = (bmstar)vc;
+  nodestar n = (nodestar)e;
+  CompleteCEStar c = (CompleteCEStar)cc;
+
+  nodestar output = new node(c->GetCounterExample(*n));
+  return output;
+}
+
+int vc_getBVLength(VC vc, Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  if(BEEV::BITVECTOR_TYPE != e->GetType()) {
+    BEEV::FatalError("c_interface: vc_GetBVLength: Input expression must be a bit-vector");
+  }
+
+  return e->GetValueWidth();
+} // end of vc_getBVLength
+
+/////////////////////////////////////////////////////////////////////////////
+// Expr Creation methods                                                   //
+/////////////////////////////////////////////////////////////////////////////
+//! Create a variable with a given name and type 
+/*! The type cannot be a function type. */
+Expr vc_varExpr1(VC vc, char* name, 
+		int indexwidth, int valuewidth) {
+  bmstar b = (bmstar)vc;
+
+  node o = b->CreateSymbol(name);
+  o.SetIndexWidth(indexwidth);
+  o.SetValueWidth(valuewidth);
+  
+  nodestar output = new node(o);
+  ////if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  b->BVTypeCheck(*output);
+
+  //store the decls in a vector for printing purposes
+  decls->push_back(o);
+  return output;
+}
+
+Expr vc_varExpr(VC vc, char * name, Type type) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)type;
+
+  node o = b->CreateSymbol(name);
+  switch(a->GetKind()) {
+  case BEEV::BITVECTOR:
+    o.SetIndexWidth(0);
+    o.SetValueWidth(GetUnsignedConst((*a)[0]));
+    break;
+  case BEEV::ARRAY:
+    o.SetIndexWidth(GetUnsignedConst((*a)[0]));
+    o.SetValueWidth(GetUnsignedConst((*a)[1]));
+    break;
+  case BEEV::BOOLEAN:
+    o.SetIndexWidth(0);
+    o.SetValueWidth(0);
+    break;
+  default:
+    BEEV::FatalError("CInterface: vc_varExpr: Unsupported type",*a);
+    break;
+  }
+  nodestar output = new node(o);
+  ////if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  b->BVTypeCheck(*output);
+
+  //store the decls in a vector for printing purposes
+  decls->push_back(o);
+  return output;
+}
+
+//! Create an equality expression.  The two children must have the
+//same type.
+Expr vc_eqExpr(VC vc, Expr ccc0, Expr ccc1) {
+  bmstar b = (bmstar)vc;
+
+  nodestar a = (nodestar)ccc0;
+  nodestar aa = (nodestar)ccc1;
+  b->BVTypeCheck(*a);
+  b->BVTypeCheck(*aa);
+  node o = b->CreateNode(BEEV::EQ,*a,*aa);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_boolType(VC vc) {
+  bmstar b = (bmstar)vc;
+
+  node o = b->CreateNode(BEEV::BOOLEAN);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// BOOLEAN EXPR Creation methods                                           //
+/////////////////////////////////////////////////////////////////////////////
+// The following functions create Boolean expressions.  The children
+// provided as arguments must be of type Boolean.
+Expr vc_trueExpr(VC vc) {
+  bmstar b = (bmstar)vc;
+  node c = b->CreateNode(BEEV::TRUE);
+  
+  nodestar d = new node(c);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(d);
+  return d;
+}
+
+Expr vc_falseExpr(VC vc) {
+  bmstar b = (bmstar)vc;
+  node c = b->CreateNode(BEEV::FALSE);
+  
+  nodestar d = new node(c);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(d);
+  return d;
+}
+
+Expr vc_notExpr(VC vc, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  
+  node o = b->CreateNode(BEEV::NOT,*a);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_andExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+  
+  node o = b->CreateNode(BEEV::AND,*l,*r);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_orExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  node o = b->CreateNode(BEEV::OR,*l,*r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_andExprN(VC vc, Expr* cc, int n) {
+  bmstar b = (bmstar)vc;
+  nodestar * c = (nodestar *)cc;
+  nodelist d;
+  
+  for(int i =0; i < n; i++)
+    d.push_back(*c[i]);
+  
+  node o = b->CreateNode(BEEV::AND,d);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+
+Expr vc_orExprN(VC vc, Expr* cc, int n) {
+  bmstar b = (bmstar)vc;
+  nodestar * c = (nodestar *)cc;
+  nodelist d;
+  
+  for(int i =0; i < n; i++)
+    d.push_back(*c[i]);
+  
+  node o = b->CreateNode(BEEV::OR,d);
+  b->BVTypeCheck(o);
+
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_iteExpr(VC vc, Expr cond, Expr thenpart, Expr elsepart){
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)cond;
+  nodestar t = (nodestar)thenpart;
+  nodestar e = (nodestar)elsepart;
+  
+  b->BVTypeCheck(*c);
+  b->BVTypeCheck(*t);
+  b->BVTypeCheck(*e);
+  node o;
+  //if the user asks for a formula then produce a formula, else
+  //prodcue a term
+  if(BEEV::BOOLEAN_TYPE == t->GetType())
+    o = b->CreateNode(BEEV::ITE,*c,*t,*e);
+  else {
+    o = b->CreateTerm(BEEV::ITE,t->GetValueWidth(),*c,*t,*e);
+    o.SetIndexWidth(t->GetIndexWidth());
+  }
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_impliesExpr(VC vc, Expr antecedent, Expr consequent){
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)antecedent;
+  nodestar t = (nodestar)consequent;
+  
+  b->BVTypeCheck(*c);
+  b->BVTypeCheck(*t);
+  node o;
+
+  o = b->CreateNode(BEEV::IMPLIES,*c,*t);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_iffExpr(VC vc, Expr e0, Expr e1){
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)e0;
+  nodestar t = (nodestar)e1;
+  
+  b->BVTypeCheck(*c);
+  b->BVTypeCheck(*t);
+  node o;
+
+  o = b->CreateNode(BEEV::IFF,*c,*t);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_boolToBVExpr(VC vc, Expr form) {
+  bmstar b = (bmstar)vc;
+  nodestar c = (nodestar)form;
+  
+  b->BVTypeCheck(*c);
+  if(!is_Form_kind(c->GetKind()))
+    BEEV::FatalError("CInterface: vc_BoolToBVExpr: You have input a NON formula:",*c);
+  
+  node o;
+  node one = b->CreateOneConst(1); 
+  node zero = b->CreateZeroConst(1);  
+  o = b->CreateTerm(BEEV::ITE,1,*c,one,zero);
+
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// BITVECTOR EXPR Creation methods                                         //
+/////////////////////////////////////////////////////////////////////////////
+Type vc_bvType(VC vc, int num_bits) {
+  bmstar b = (bmstar)vc;
+  
+  if(!(0 < num_bits))
+    BEEV::FatalError("CInterface: number of bits in a bvtype must be a positive integer:", 
+		     b->CreateNode(BEEV::UNDEFINED));
+
+  node e = b->CreateBVConst(32, num_bits);
+  nodestar output = new node(b->CreateNode(BEEV::BITVECTOR,e));
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Type vc_bv32Type(VC vc) {
+  return vc_bvType(vc,32);
+}
+
+
+Expr vc_bvConstExprFromStr(VC vc, char* binary_repr) {
+  bmstar b = (bmstar)vc;
+
+  node n = b->CreateBVConst(binary_repr,2);
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvConstExprFromInt(VC vc,
+			   int n_bits, 
+			   unsigned int value) {
+  bmstar b = (bmstar)vc;
+
+  unsigned long long int v = (unsigned long long int)value;
+  node n = b->CreateBVConst(n_bits, v);
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvConstExprFromLL(VC vc,
+			  int n_bits, 
+			  unsigned long long value) {
+  bmstar b = (bmstar)vc;
+  
+  node n = b->CreateBVConst(n_bits, value);
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvConcatExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o =
+    b->CreateTerm(BEEV::BVCONCAT,
+		  l->GetValueWidth()+ r->GetValueWidth(),*l,*r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvPlusExpr(VC vc, int n_bits, Expr left, Expr right){
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVPLUS,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+
+Expr vc_bv32PlusExpr(VC vc, Expr left, Expr right) {
+  return vc_bvPlusExpr(vc, 32, left, right);
+}
+
+
+Expr vc_bvMinusExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVSUB,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+
+Expr vc_bv32MinusExpr(VC vc, Expr left, Expr right) {
+  return vc_bvMinusExpr(vc, 32, left, right);
+}
+
+
+Expr vc_bvMultExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVMULT,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvDivExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVDIV,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvModExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVMOD,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvDivExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::SBVDIV,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvModExpr(VC vc, int n_bits, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::SBVMOD,n_bits, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bv32MultExpr(VC vc, Expr left, Expr right) {
+  return vc_bvMultExpr(vc, 32, left, right);
+}
+
+
+// unsigned comparators
+Expr vc_bvLtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVLT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvLeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVLE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvGtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVGT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvGeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVGE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+// signed comparators
+Expr vc_sbvLtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSLT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvLeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSLE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvGtExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSGT, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_sbvGeExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateNode(BEEV::BVSGE, *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvUMinusExpr(VC vc, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  node o = b->CreateTerm(BEEV::BVUMINUS, a->GetValueWidth(), *a);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+// bitwise operations: these are terms not formulas
+Expr vc_bvAndExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVAND, (*l).GetValueWidth(), *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvOrExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVOR, (*l).GetValueWidth(), *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvXorExpr(VC vc, Expr left, Expr right) {
+  bmstar b = (bmstar)vc;
+  nodestar l = (nodestar)left;
+  nodestar r = (nodestar)right;
+
+  b->BVTypeCheck(*l);
+  b->BVTypeCheck(*r);
+  node o = b->CreateTerm(BEEV::BVXOR, (*l).GetValueWidth(), *l, *r);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvNotExpr(VC vc, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+
+  b->BVTypeCheck(*a);
+  node o = b->CreateTerm(BEEV::BVNEG, a->GetValueWidth(), *a);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvLeftShiftExpr(VC vc, int sh_amt, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  //convert leftshift to bvconcat
+  if(0 != sh_amt) {
+    node len = b->CreateBVConst(sh_amt, 0);
+    node o = b->CreateTerm(BEEV::BVCONCAT, a->GetValueWidth() + sh_amt, *a, len);
+    b->BVTypeCheck(o);
+    nodestar output = new node(o);
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+  else
+    return a;
+}
+
+Expr vc_bvRightShiftExpr(VC vc, int sh_amt, Expr ccc) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+  
+  unsigned int w = a->GetValueWidth();  
+  //the amount by which you are rightshifting
+  //is less-than/equal-to the length of input
+  //bitvector  
+  if(0 < (unsigned)sh_amt && (unsigned)sh_amt <= w) {
+    node len = b->CreateBVConst(sh_amt, 0);
+    node hi = b->CreateBVConst(32,w-1);
+    node low = b->CreateBVConst(32,sh_amt);
+    node extract = b->CreateTerm(BEEV::BVEXTRACT,w-sh_amt,*a,hi,low);
+
+    node n = b->CreateTerm(BEEV::BVCONCAT, w,len, extract);
+    b->BVTypeCheck(n);
+    nodestar output = new node(n);
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+  else if(sh_amt == 0)
+    return a;
+  else {
+    if(0== w)
+      BEEV::FatalError("CInterface: vc_bvRightShiftExpr: cannot have a bitvector of length 0:",*a);
+    nodestar output = new node(b->CreateBVConst(w,0));
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+}
+
+/* Same as vc_bvLeftShift only that the answer in 32 bits long */
+Expr vc_bv32LeftShiftExpr(VC vc, int sh_amt, Expr child) {
+  return vc_bvExtract(vc, vc_bvLeftShiftExpr(vc, sh_amt, child), 31, 0);
+}
+
+/* Same as vc_bvRightShift only that the answer in 32 bits long */
+Expr vc_bv32RightShiftExpr(VC vc, int sh_amt, Expr child) {
+  return vc_bvExtract(vc, vc_bvRightShiftExpr(vc, sh_amt, child), 31, 0);
+}
+
+
+Expr vc_bvVar32LeftShiftExpr(VC vc, Expr sh_amt, Expr child) {
+  Expr ifpart;
+  Expr thenpart;
+  Expr elsepart = vc_trueExpr(vc);
+  Expr ite = vc_trueExpr(vc);
+
+  for(int count=32; count >= 0; count--){
+    if(count != 32) {
+      ifpart = vc_eqExpr(vc, sh_amt, 
+			 vc_bvConstExprFromInt(vc, 32, count));
+      thenpart = vc_bvExtract(vc,
+			      vc_bvLeftShiftExpr(vc, count, child),
+			      31, 0);
+
+      ite = vc_iteExpr(vc,ifpart,thenpart,elsepart);
+      elsepart = ite;
+    } 
+    else
+      elsepart = vc_bvConstExprFromInt(vc,32, 0);    
+  }  
+  return ite;  
+}
+
+Expr vc_bvVar32DivByPowOfTwoExpr(VC vc, Expr child, Expr rhs) {
+  Expr ifpart;
+  Expr thenpart;
+  Expr elsepart = vc_trueExpr(vc);
+  Expr ite = vc_trueExpr(vc);
+
+  for(int count=32; count >= 0; count--){
+    if(count != 32) {
+      ifpart = vc_eqExpr(vc, rhs, 
+			 vc_bvConstExprFromInt(vc, 32, 1 << count));      
+      thenpart = vc_bvRightShiftExpr(vc, count, child);      
+      ite = vc_iteExpr(vc,ifpart,thenpart,elsepart);
+      elsepart = ite;
+    } else {
+      elsepart = vc_bvConstExprFromInt(vc,32, 0);
+    }    
+  }  
+  return ite;  
+}
+
+Expr vc_bvVar32RightShiftExpr(VC vc, Expr sh_amt, Expr child) {
+  Expr ifpart;
+  Expr thenpart;
+  Expr elsepart = vc_trueExpr(vc);
+  Expr ite = vc_trueExpr(vc);
+
+  for(int count=32; count >= 0; count--){
+    if(count != 32) {
+      ifpart = vc_eqExpr(vc, sh_amt, 
+			 vc_bvConstExprFromInt(vc, 32, count));      
+      thenpart = vc_bvRightShiftExpr(vc, count, child);      
+      ite = vc_iteExpr(vc,ifpart,thenpart,elsepart);
+      elsepart = ite;
+    } else {
+      elsepart = vc_bvConstExprFromInt(vc,32, 0);
+    }    
+  }  
+  return ite;  
+}
+
+Expr vc_bvExtract(VC vc, Expr ccc, int hi_num, int low_num) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  node hi = b->CreateBVConst(32,hi_num);
+  node low = b->CreateBVConst(32,low_num);
+  node o = b->CreateTerm(BEEV::BVEXTRACT,hi_num-low_num+1,*a,hi,low);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+Expr vc_bvBoolExtract(VC vc, Expr ccc, int bit_num) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  b->BVTypeCheck(*a);
+
+  node bit = b->CreateBVConst(32,bit_num);
+  //node o = b->CreateNode(BEEV::BVGETBIT,*a,bit);  
+  node zero = b->CreateBVConst(1,0);
+  node oo = b->CreateTerm(BEEV::BVEXTRACT,1,*a,bit,bit);
+  node o = b->CreateNode(BEEV::EQ,oo,zero);
+  b->BVTypeCheck(o);
+  nodestar output = new node(o);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output; 
+}
+
+Expr vc_bvSignExtend(VC vc, Expr ccc, int nbits) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)ccc;
+  
+  //width of the expr which is being sign extended. nbits is the
+  //resulting length of the signextended expr
+  b->BVTypeCheck(*a);
+  
+  unsigned exprlen = a->GetValueWidth();
+  unsigned outputlen = nbits;
+  node n;
+  if(exprlen >= outputlen) {
+    //extract
+    node hi = b->CreateBVConst(32,outputlen-1);
+    node low = b->CreateBVConst(32,0);
+    n = b->CreateTerm(BEEV::BVEXTRACT,nbits,*a,hi,low);
+    b->BVTypeCheck(n);
+  }
+  else {
+    //sign extend
+    BEEV::ASTNode width = b->CreateBVConst(32,nbits);
+    n = b->CreateTerm(BEEV::BVSX,nbits,*a, width);
+  }
+
+  b->BVTypeCheck(n);
+  nodestar output = new node(n);
+  //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+  return output;
+}
+
+//! Return an int from a constant bitvector expression
+int getBVInt(Expr e) {
+  //bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BVCONST != a->GetKind())
+    BEEV::FatalError("CInterface: getBVInt: Attempting to extract int value from a NON-constant BITVECTOR: ",*a);
+  return (int)GetUnsignedConst(*a);
+}
+
+//! Return an unsigned int from a constant bitvector expression
+unsigned int getBVUnsigned(Expr e) {
+  //bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BVCONST != a->GetKind())
+    BEEV::FatalError("getBVUnsigned: Attempting to extract int value from a NON-constant BITVECTOR: ",*a);
+  return (unsigned int)GetUnsignedConst(*a);
+}
+
+//! Return an unsigned long long int from a constant bitvector expression
+unsigned long long int getBVUnsignedLongLong(Expr e) {
+  //bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BVCONST != a->GetKind())
+    BEEV::FatalError("getBVUnsigned: Attempting to extract int value from a NON-constant BITVECTOR: ",*a);
+#ifdef NATIVE_C_ARITH
+  return (unsigned long long int)a->GetBVConst();
+#else
+  unsigned* bv = a->GetBVConst();
+
+  char * str_bv  = (char *)CONSTANTBV::BitVector_to_Bin(bv);
+  unsigned long long int tmp = strtoull(str_bv,NULL,2);
+  CONSTANTBV::BitVector_Dispose((unsigned char *)str_bv);
+  return tmp;
+#endif
+}
+
+
+Expr vc_simplify(VC vc, Expr e) {
+  bmstar b = (bmstar)vc;
+  nodestar a = (nodestar)e;
+
+  if(BEEV::BOOLEAN_TYPE == a->GetType()) {
+    nodestar output = new node(b->SimplifyFormula_TopLevel(*a,false));
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    b->Begin_RemoveWrites = true;
+    output = new node(b->SimplifyFormula_TopLevel(*output,false));
+    b->Begin_RemoveWrites = false;
+    return output;    
+  }
+  else {
+    nodestar output = new node(b->SimplifyTerm(*a));
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    b->Begin_RemoveWrites = true;
+    output = new node(b->SimplifyTerm(*output));
+    b->Begin_RemoveWrites = false;
+    return output;
+  }
+}
+
+/* C pointer support: C interface to support C memory arrays in CVCL */
+Expr vc_bvCreateMemoryArray(VC vc, char * arrayName) {
+  Type bv8  = vc_bvType(vc,8);
+  Type bv32 = vc_bvType(vc,32);
+  
+  Type malloced_mem0 = vc_arrayType(vc,bv32,bv8);
+  return vc_varExpr(vc, arrayName, malloced_mem0);
+}
+
+Expr vc_bvReadMemoryArray(VC vc, 
+			  Expr array, 
+			  Expr byteIndex, int numOfBytes) {
+  if(!(numOfBytes > 0))
+    BEEV::FatalError("numOfBytes must be greater than 0");
+
+  if(numOfBytes == 1)
+    return vc_readExpr(vc,array,byteIndex);
+  else {
+    int count = 1;
+    Expr a = vc_readExpr(vc,array,byteIndex);
+    while(--numOfBytes > 0) {
+      Expr b = vc_readExpr(vc,array,
+			   /*vc_simplify(vc, */
+				       vc_bvPlusExpr(vc, 32, 
+						     byteIndex,
+						     vc_bvConstExprFromInt(vc,32,count)))/*)*/;
+      a = vc_bvConcatExpr(vc,b,a);
+      count++;
+    }
+    return a;
+  }    
+}
+
+Expr vc_bvWriteToMemoryArray(VC vc, 
+			     Expr array, Expr byteIndex, 
+			     Expr element, int numOfBytes) {
+  if(!(numOfBytes > 0))
+    BEEV::FatalError("numOfBytes must be greater than 0");
+	    
+  int newBitsPerElem = numOfBytes*8;
+  if(numOfBytes == 1)
+    return vc_writeExpr(vc, array, byteIndex, element);
+  else {
+    int count = 1;
+    int hi = newBitsPerElem - 1;
+    int low = newBitsPerElem - 8;
+    int low_elem = 0;
+    int hi_elem = low_elem + 7;
+    Expr c = vc_bvExtract(vc, element, hi_elem, low_elem);
+    Expr newarray = vc_writeExpr(vc, array, byteIndex, c);
+    while(--numOfBytes > 0) {
+      hi = low-1;
+      low = low-8;      
+
+      low_elem = low_elem + 8;
+      hi_elem = low_elem + 7;
+
+      c = vc_bvExtract(vc, element, hi_elem, low_elem);
+      newarray = 
+	vc_writeExpr(vc, newarray,
+		     vc_bvPlusExpr(vc, 32, byteIndex, vc_bvConstExprFromInt(vc,32,count)),
+		     c);
+      count++;
+    }
+    return newarray;
+  }    
+}
+
+Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value){
+  return vc_bvConstExprFromInt(vc, 32, value);
+}
+
+
+#if 0
+static char *val_to_binary_str(unsigned nbits, unsigned long long val) {
+        char s[65];
+
+	assert(nbits < sizeof s);
+        strcpy(s, "");
+        while(nbits-- > 0) {
+                if((val >> nbits) & 1)
+                        strcat(s, "1");
+                else
+                        strcat(s, "0");
+        }
+        return strdup(s);
+}
+#endif
+
+char* exprString(Expr e){
+  stringstream ss;
+  ((nodestar)e)->PL_Print(ss,0);
+  string s = ss.str();
+  char *copy = strdup(s.c_str());
+  return copy;
+}
+
+char* typeString(Type t){
+  stringstream ss;
+  ((nodestar)t)->PL_Print(ss,0);
+
+  string s = ss.str();
+  char *copy = strdup(s.c_str());
+  return copy;
+}
+
+Expr getChild(Expr e, int i){
+  nodestar a = (nodestar)e;
+
+  BEEV::ASTVec c = a->GetChildren();
+  if(0 <=  (unsigned)i && (unsigned)i < c.size()) {
+    BEEV::ASTNode o = c[i];
+    nodestar output = new node(o);
+    //if(cinterface_exprdelete_on) created_exprs.push_back(output);
+    return output;
+  }
+  else 
+    BEEV::FatalError("getChild: Error accessing childNode in expression: ",*a);
+  return a;
+}
+
+void vc_registerErrorHandler(void (*error_hdlr)(const char* err_msg)) {
+  BEEV::vc_error_hdlr = error_hdlr;
+}
+
+
+int vc_getHashQueryStateToBuffer(VC vc, Expr query) {
+  assert(vc);
+  assert(query);
+  bmstar b = (bmstar)vc;
+  nodestar qry = (nodestar)query;
+  BEEV::ASTVec v = b->GetAsserts(); 
+  BEEV::ASTNode out = b->CreateNode(BEEV::AND,b->CreateNode(BEEV::NOT,*qry),v);
+  return out.Hash();
+}
+
+Type vc_getType(VC vc, Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  switch(e->GetType()) {
+  case BEEV::BOOLEAN_TYPE:
+    return vc_boolType(vc);
+    break;      
+  case BEEV::BITVECTOR_TYPE:
+    return vc_bvType(vc,e->GetValueWidth());
+    break;
+  case BEEV::ARRAY_TYPE: {
+    Type typeindex = vc_bvType(vc,e->GetIndexWidth());
+    Type typedata = vc_bvType(vc,e->GetValueWidth());
+    return vc_arrayType(vc,typeindex,typedata);
+    break;
+  }
+  default:
+    BEEV::FatalError("c_interface: vc_GetType: expression with bad typing: please check your expression construction");
+    return vc_boolType(vc);
+    break;
+  }
+}// end of vc_gettype()
+
+//!if e is TRUE then return 1; if e is FALSE then return 0; otherwise
+//return -1
+int vc_isBool(Expr e) {
+  nodestar input = (nodestar)e;
+  if(BEEV::TRUE == input->GetKind()) {
+    return 1;
+  }
+
+  if(BEEV::FALSE == input->GetKind()) {
+    return 0;
+  }
+
+  return -1;
+}
+
+void vc_Destroy(VC vc) {
+  bmstar b = (bmstar)vc;
+  // for(std::vector<BEEV::ASTNode *>::iterator it=created_exprs.begin(),
+  // 	itend=created_exprs.end();it!=itend;it++) {
+  //     BEEV::ASTNode * aaa = *it;
+  //     delete aaa;
+  //   }
+  delete decls;
+  delete b;
+}
+
+void vc_DeleteExpr(Expr e) {
+  nodestar input = (nodestar)e;
+  //bmstar b = (bmstar)vc;
+  delete input;
+}
+
+exprkind_t getExprKind(Expr e) {
+  nodestar input = (nodestar)e;
+  return (exprkind_t)(input->GetKind());  
+}
+
+int getDegree (Expr e) {
+  nodestar input = (nodestar)e;
+  return input->Degree();
+}
+
+int getBVLength(Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  if(BEEV::BITVECTOR_TYPE != e->GetType()) {
+    BEEV::FatalError("c_interface: vc_GetBVLength: Input expression must be a bit-vector");
+  }
+
+  return e->GetValueWidth();
+} 
+
+type_t getType (Expr ex) {
+  nodestar e = (nodestar)ex;
+    
+  return (type_t)(e->GetType());
+}
+
+int getVWidth (Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  return e->GetValueWidth();
+}
+
+int getIWidth (Expr ex) {
+  nodestar e = (nodestar)ex;
+
+  return e->GetIndexWidth();
+}
+
+void vc_printCounterExampleFile(VC vc, int fd) {
+  fdostream os(fd);
+  bmstar b = (bmstar)vc;
+  BEEV::print_counterexample = true;    
+  os << "COUNTEREXAMPLE BEGIN: \n";
+  b->PrintCounterExample(true, os);
+  os << "COUNTEREXAMPLE END: \n";
+}
+
+const char* exprName(Expr e){
+    return ((nodestar)e)->GetName();
+}
+
+int getExprID (Expr ex) {
+    BEEV::ASTNode q = (*(nodestar)ex);
+
+    return q.GetNodeNum();
+}
diff --git a/stp/c_interface/c_interface.h b/stp/c_interface/c_interface.h
new file mode 100644
index 00000000..a2fa8cd7
--- /dev/null
+++ b/stp/c_interface/c_interface.h
@@ -0,0 +1,401 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * License to use, copy, modify, sell and/or distribute this software
+ * and its documentation for any purpose is hereby granted without
+ * royalty, subject to the terms and conditions defined in the \ref
+ * LICENSE file provided with this distribution.  In particular:
+ *
+ * - The above copyright notice and this permission notice must appear
+ * in all copies of the software and related documentation.
+ *
+ * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
+ * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
+ ********************************************************************/
+// -*- c++ -*-
+#ifndef _cvcl__include__c_interface_h_
+#define _cvcl__include__c_interface_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+#ifdef STP_STRONG_TYPING
+#else
+  //This gives absolutely no pointer typing at compile-time. Most C
+  //users prefer this over stronger typing. User is the king. A
+  //stronger typed interface is in the works.
+  typedef void* VC;
+  typedef void* Expr;
+  typedef void* Type;
+  typedef void* WholeCounterExample;
+#endif
+
+  // o  : optimizations
+  // c  : check counterexample
+  // p  : print counterexample
+  // h  : help
+  // s  : stats
+  // v  : print nodes
+  void vc_setFlags(char c);
+  
+  //! Flags can be NULL
+  VC vc_createValidityChecker(void);
+  
+  // Basic types
+  Type vc_boolType(VC vc);
+  
+  //! Create an array type
+  Type vc_arrayType(VC vc, Type typeIndex, Type typeData);
+
+  /////////////////////////////////////////////////////////////////////////////
+  // Expr manipulation methods                                               //
+  /////////////////////////////////////////////////////////////////////////////
+
+  //! Create a variable with a given name and type 
+  /*! The type cannot be a function type. The var name can contain
+    only variables, numerals and underscore. If you use any other
+    symbol, you will get a segfault. */  
+  Expr vc_varExpr(VC vc, char * name, Type type);
+
+  //The var name can contain only variables, numerals and
+  //underscore. If you use any other symbol, you will get a segfault.
+  Expr vc_varExpr1(VC vc, char* name, 
+		  int indexwidth, int valuewidth);
+
+  //! Get the expression and type associated with a name.
+  /*!  If there is no such Expr, a NULL Expr is returned. */
+  //Expr vc_lookupVar(VC vc, char* name, Type* type);
+  
+  //! Get the type of the Expr.
+  Type vc_getType(VC vc, Expr e);
+  
+  int vc_getBVLength(VC vc, Expr e);
+
+  //! Create an equality expression.  The two children must have the same type.
+  Expr vc_eqExpr(VC vc, Expr child0, Expr child1);
+  
+  // Boolean expressions
+  
+  // The following functions create Boolean expressions.  The children
+  // provided as arguments must be of type Boolean (except for the
+  // function vc_iteExpr(). In the case of vc_iteExpr() the
+  // conditional must always be Boolean, but the ifthenpart
+  // (resp. elsepart) can be bit-vector or Boolean type. But, the
+  // ifthenpart and elsepart must be both of the same type)
+  Expr vc_trueExpr(VC vc);
+  Expr vc_falseExpr(VC vc);
+  Expr vc_notExpr(VC vc, Expr child);
+  Expr vc_andExpr(VC vc, Expr left, Expr right);
+  Expr vc_andExprN(VC vc, Expr* children, int numOfChildNodes);
+  Expr vc_orExpr(VC vc, Expr left, Expr right);
+  Expr vc_orExprN(VC vc, Expr* children, int numOfChildNodes);
+  Expr vc_impliesExpr(VC vc, Expr hyp, Expr conc);
+  Expr vc_iffExpr(VC vc, Expr left, Expr right);
+  //The output type of vc_iteExpr can be Boolean (formula-level ite)
+  //or bit-vector (word-level ite)
+  Expr vc_iteExpr(VC vc, Expr conditional, Expr ifthenpart, Expr elsepart);
+  
+  //Boolean to single bit BV Expression
+  Expr vc_boolToBVExpr(VC vc, Expr form);
+
+  // Arrays
+  
+  //! Create an expression for the value of array at the given index
+  Expr vc_readExpr(VC vc, Expr array, Expr index);
+
+  //! Array update; equivalent to "array WITH [index] := newValue"
+  Expr vc_writeExpr(VC vc, Expr array, Expr index, Expr newValue);
+  
+  // Expr I/O
+  //! Expr vc_parseExpr(VC vc, char* s);
+
+  //! Prints 'e' to stdout.
+  void vc_printExpr(VC vc, Expr e);
+
+  //! Prints 'e' into an open file descriptor 'fd'
+  void vc_printExprFile(VC vc, Expr e, int fd);
+
+  //! Prints state of 'vc' into malloc'd buffer '*buf' and stores the 
+  //  length into '*len'.  It is the responsibility of the caller to 
+  //  free the buffer.
+  //void vc_printStateToBuffer(VC vc, char **buf, unsigned long *len);
+
+  //! Prints 'e' to malloc'd buffer '*buf'.  Sets '*len' to the length of 
+  //  the buffer. It is the responsibility of the caller to free the buffer.
+  void vc_printExprToBuffer(VC vc, Expr e, char **buf, unsigned long * len);
+
+  //! Prints counterexample to stdout.
+  void vc_printCounterExample(VC vc);
+
+  //! Prints variable declarations to stdout.
+  void vc_printVarDecls(VC vc);
+
+  //! Prints asserts to stdout. The flag simplify_print must be set to
+  //"1" if you wish simplification to occur dring printing. It must be
+  //set to "0" otherwise
+  void vc_printAsserts(VC vc, int simplify_print);
+
+  //! Prints the state of the query to malloc'd buffer '*buf' and
+  //stores ! the length of the buffer to '*len'.  It is the
+  //responsibility of the caller to free the buffer. The flag
+  //simplify_print must be set to "1" if you wish simplification to
+  //occur dring printing. It must be set to "0" otherwise
+  void vc_printQueryStateToBuffer(VC vc, Expr e, 
+				  char **buf, unsigned long *len, int simplify_print);
+
+  //! Similar to vc_printQueryStateToBuffer()
+  void vc_printCounterExampleToBuffer(VC vc, char **buf,unsigned long *len);
+
+  //! Prints query to stdout.
+  void vc_printQuery(VC vc);
+
+  /////////////////////////////////////////////////////////////////////////////
+  // Context-related methods                                                 //
+  /////////////////////////////////////////////////////////////////////////////
+  
+  //! Assert a new formula in the current context.  
+  /*! The formula must have Boolean type. */
+  void vc_assertFormula(VC vc, Expr e);
+  
+  //! Simplify e with respect to the current context
+  Expr vc_simplify(VC vc, Expr e);
+
+  //! Check validity of e in the current context. e must be a FORMULA
+  //
+  //if returned 0 then input is INVALID. 
+  //
+  //if returned 1 then input is VALID
+  //
+  //if returned 2 then ERROR
+  int vc_query(VC vc, Expr e);
+  
+  //! Return the counterexample after a failed query.
+  Expr vc_getCounterExample(VC vc, Expr e);
+
+  //! get size of counterexample, i.e. the number of variables/array
+  //locations in the counterexample.
+  int vc_counterexample_size(VC vc);
+  
+  //! Checkpoint the current context and increase the scope level
+  void vc_push(VC vc);
+  
+  //! Restore the current context to its state at the last checkpoint
+  void vc_pop(VC vc);
+  
+  //! Return an int from a constant bitvector expression
+  int getBVInt(Expr e);
+  //! Return an unsigned int from a constant bitvector expression
+  unsigned int getBVUnsigned(Expr e);
+  //! Return an unsigned long long int from a constant bitvector expressions
+  unsigned long long int getBVUnsignedLongLong(Expr e);
+  
+  /**************************/
+  /* BIT VECTOR OPERATIONS  */
+  /**************************/
+  Type vc_bvType(VC vc, int no_bits);
+  Type vc_bv32Type(VC vc);
+  
+  Expr vc_bvConstExprFromStr(VC vc, char* binary_repr);
+  Expr vc_bvConstExprFromInt(VC vc, int n_bits, unsigned int value);
+  Expr vc_bvConstExprFromLL(VC vc, int n_bits, unsigned long long value);
+  Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value);
+  
+  Expr vc_bvConcatExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvPlusExpr(VC vc, int n_bits, Expr left, Expr right);
+  Expr vc_bv32PlusExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvMinusExpr(VC vc, int n_bits, Expr left, Expr right);
+  Expr vc_bv32MinusExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvMultExpr(VC vc, int n_bits, Expr left, Expr right);
+  Expr vc_bv32MultExpr(VC vc, Expr left, Expr right);
+  // left divided by right i.e. left/right
+  Expr vc_bvDivExpr(VC vc, int n_bits, Expr left, Expr right);
+  // left modulo right i.e. left%right
+  Expr vc_bvModExpr(VC vc, int n_bits, Expr left, Expr right);
+  // signed left divided by right i.e. left/right
+  Expr vc_sbvDivExpr(VC vc, int n_bits, Expr left, Expr right);
+  // signed left modulo right i.e. left%right
+  Expr vc_sbvModExpr(VC vc, int n_bits, Expr left, Expr right);
+  
+  Expr vc_bvLtExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvLeExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvGtExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvGeExpr(VC vc, Expr left, Expr right);
+  
+  Expr vc_sbvLtExpr(VC vc, Expr left, Expr right);
+  Expr vc_sbvLeExpr(VC vc, Expr left, Expr right);
+  Expr vc_sbvGtExpr(VC vc, Expr left, Expr right);
+  Expr vc_sbvGeExpr(VC vc, Expr left, Expr right);
+  
+  Expr vc_bvUMinusExpr(VC vc, Expr child);
+
+  // bitwise operations: these are terms not formulas  
+  Expr vc_bvAndExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvOrExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvXorExpr(VC vc, Expr left, Expr right);
+  Expr vc_bvNotExpr(VC vc, Expr child);
+  
+  Expr vc_bvLeftShiftExpr(VC vc, int sh_amt, Expr child);
+  Expr vc_bvRightShiftExpr(VC vc, int sh_amt, Expr child);
+  /* Same as vc_bvLeftShift only that the answer in 32 bits long */
+  Expr vc_bv32LeftShiftExpr(VC vc, int sh_amt, Expr child);
+  /* Same as vc_bvRightShift only that the answer in 32 bits long */
+  Expr vc_bv32RightShiftExpr(VC vc, int sh_amt, Expr child);
+  Expr vc_bvVar32LeftShiftExpr(VC vc, Expr sh_amt, Expr child);
+  Expr vc_bvVar32RightShiftExpr(VC vc, Expr sh_amt, Expr child);
+  Expr vc_bvVar32DivByPowOfTwoExpr(VC vc, Expr child, Expr rhs);
+
+  Expr vc_bvExtract(VC vc, Expr child, int high_bit_no, int low_bit_no);
+  
+  //accepts a bitvector and position, and returns a boolean
+  //corresponding to that position. More precisely, it return the
+  //equation (x[bit_no:bit_no] = 0)
+  //FIXME  = 1 ?
+  Expr vc_bvBoolExtract(VC vc, Expr x, int bit_no);  
+  Expr vc_bvSignExtend(VC vc, Expr child, int nbits);
+  
+  /*C pointer support:  C interface to support C memory arrays in CVCL */
+  Expr vc_bvCreateMemoryArray(VC vc, char * arrayName);
+  Expr vc_bvReadMemoryArray(VC vc, 
+			  Expr array, Expr byteIndex, int numOfBytes);
+  Expr vc_bvWriteToMemoryArray(VC vc, 
+			       Expr array, Expr  byteIndex, 
+			       Expr element, int numOfBytes);
+  Expr vc_bv32ConstExprFromInt(VC vc, unsigned int value);
+  
+  // return a string representation of the Expr e. The caller is responsible
+  // for deallocating the string with free()
+  char* exprString(Expr e);
+  
+  // return a string representation of the Type t. The caller is responsible
+  // for deallocating the string with free()
+  char* typeString(Type t);
+
+  Expr getChild(Expr e, int i);
+
+  //1.if input expr is TRUE then the function returns 1;
+  //
+  //2.if input expr is FALSE then function returns 0;
+  //
+  //3.otherwise the function returns -1
+  int vc_isBool(Expr e);
+
+  /* Register the given error handler to be called for each fatal error.*/
+  void vc_registerErrorHandler(void (*error_hdlr)(const char* err_msg));
+
+  int vc_getHashQueryStateToBuffer(VC vc, Expr query);
+
+  //destroys the STP instance, and removes all the created expressions
+  void vc_Destroy(VC vc);
+
+  //deletes the expression e
+  void vc_DeleteExpr(Expr e);
+
+  //Get the whole counterexample from the current context
+  WholeCounterExample vc_getWholeCounterExample(VC vc);
+
+  //Get the value of a term expression from the CounterExample
+  Expr vc_getTermFromCounterExample(VC vc, Expr e, WholeCounterExample c);
+
+  //Kinds of Expr
+  enum exprkind_t{
+      UNDEFINED,
+      SYMBOL,
+      BVCONST,
+      BVNEG,
+      BVCONCAT,
+      BVOR,
+      BVAND,
+      BVXOR,
+      BVNAND,
+      BVNOR,
+      BVXNOR,
+      BVEXTRACT,
+      BVLEFTSHIFT,
+      BVRIGHTSHIFT,
+      BVSRSHIFT,
+      BVVARSHIFT,
+      BVPLUS,
+      BVSUB,
+      BVUMINUS,
+      BVMULTINVERSE,
+      BVMULT,
+      BVDIV,
+      BVMOD,
+      SBVDIV,
+      SBVMOD,
+      BVSX,
+      BOOLVEC,
+      ITE,
+      BVGETBIT,
+      BVLT,
+      BVLE,
+      BVGT,
+      BVGE,
+      BVSLT,
+      BVSLE,
+      BVSGT,
+      BVSGE,
+      EQ,
+      NEQ,
+      FALSE,
+      TRUE,
+      NOT,
+      AND,
+      OR,
+      NAND,
+      NOR,
+      XOR,
+      IFF,
+      IMPLIES,
+      READ,
+      WRITE,
+      ARRAY,
+      BITVECTOR,
+      BOOLEAN
+  };
+
+  // type of expression
+  enum type_t {
+      BOOLEAN_TYPE = 0,
+      BITVECTOR_TYPE,
+      ARRAY_TYPE,
+      UNKNOWN_TYPE
+  };
+
+  // get the kind of the expression
+  exprkind_t getExprKind (Expr e);
+
+  // get the number of children nodes
+  int getDegree (Expr e);
+
+  // get the bv length
+  int getBVLength(Expr e);
+
+  // get expression type
+  type_t getType (Expr e);
+
+  // get value bit width
+  int getVWidth (Expr e);
+
+  // get index bit width
+  int getIWidth (Expr e);
+
+  // Prints counterexample to an open file descriptor 'fd'
+  void vc_printCounterExampleFile(VC vc, int fd);
+
+  // get name of expression. must be a variable.
+  const char* exprName(Expr e);
+  
+  // get the node ID of an Expr.
+  int getExprID (Expr ex);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/stp/c_interface/fdstream.h b/stp/c_interface/fdstream.h
new file mode 100644
index 00000000..2cff613c
--- /dev/null
+++ b/stp/c_interface/fdstream.h
@@ -0,0 +1,186 @@
+/*! @brief The following code declares classes to read from and write to
+ * file descriptore or file handles.
+ *
+ * See
+ *      http://www.josuttis.com/cppcode
+ * for details and the latest version.
+ *
+ * - open:
+ *      - integrating BUFSIZ on some systems?
+ *      - optimized reading of multiple characters
+ *      - stream for reading AND writing
+ *      - i18n
+ *
+ * (C) Copyright Nicolai M. Josuttis 2001.
+ * Permission to copy, use, modify, sell and distribute this software
+ * is granted provided this copyright notice appears in all copies.
+ * This software is provided "as is" without express or implied
+ * warranty, and with no claim as to its suitability for any purpose.
+ *
+ * Version: Jul 28, 2002
+ * History:
+ *  Jul 28, 2002: bugfix memcpy() => memmove()
+ *                fdinbuf::underflow(): cast for return statements
+ *  Aug 05, 2001: first public version
+ */
+#ifndef BOOST_FDSTREAM_HPP
+#define BOOST_FDSTREAM_HPP
+
+#include <istream>
+#include <ostream>
+#include <streambuf>
+
+
+// for EOF:
+#include <cstdio>
+// for memmove():
+#include <cstring>
+
+
+// low-level read and write functions
+#ifdef _MSC_VER
+# include <io.h>
+#else
+# include <unistd.h>
+//extern "C" {
+//    int write (int fd, const char* buf, int num);
+//    int read (int fd, char* buf, int num);
+//}
+#endif
+
+
+// BEGIN namespace BOOST
+namespace std {
+
+
+/************************************************************
+ * fdostream
+ * - a stream that writes on a file descriptor
+ ************************************************************/
+
+
+class fdoutbuf : public std::streambuf {
+  protected:
+    int fd;    // file descriptor
+  public:
+    // constructor
+    fdoutbuf (int _fd) : fd(_fd) {
+    }
+  protected:
+    // write one character
+    virtual int_type overflow (int_type c) {
+        if (c != EOF) {
+            char z = c;
+            if (write (fd, &z, 1) != 1) {
+                return EOF;
+            }
+        }
+        return c;
+    }
+    // write multiple characters
+    virtual
+    std::streamsize xsputn (const char* s,
+                            std::streamsize num) {
+        return write(fd,s,num);
+    }
+};
+
+class fdostream : public std::ostream {
+  protected:
+    fdoutbuf buf;
+  public:
+    fdostream (int fd) : std::ostream(0), buf(fd) {
+        rdbuf(&buf);
+    }
+};
+
+
+/************************************************************
+ * fdistream
+ * - a stream that reads on a file descriptor
+ ************************************************************/
+
+class fdinbuf : public std::streambuf {
+  protected:
+    int fd;    // file descriptor
+  protected:
+    /* data buffer:
+     * - at most, pbSize characters in putback area plus
+     * - at most, bufSize characters in ordinary read buffer
+     */
+    static const int pbSize = 4;        // size of putback area
+    static const int bufSize = 1024;    // size of the data buffer
+    char buffer[bufSize+pbSize];        // data buffer
+
+  public:
+    /* constructor
+     * - initialize file descriptor
+     * - initialize empty data buffer
+     * - no putback area
+     * => force underflow()
+     */
+    fdinbuf (int _fd) : fd(_fd) {
+        setg (buffer+pbSize,     // beginning of putback area
+              buffer+pbSize,     // read position
+              buffer+pbSize);    // end position
+    }
+
+  protected:
+    // insert new characters into the buffer
+    virtual int_type underflow () {
+#ifndef _MSC_VER
+        using std::memmove;
+#endif
+
+        // is read position before end of buffer?
+        if (gptr() < egptr()) {
+            return traits_type::to_int_type(*gptr());
+        }
+
+        /* process size of putback area
+         * - use number of characters read
+         * - but at most size of putback area
+         */
+        int numPutback;
+        numPutback = gptr() - eback();
+        if (numPutback > pbSize) {
+            numPutback = pbSize;
+        }
+
+        /* copy up to pbSize characters previously read into
+         * the putback area
+         */
+        memmove (buffer+(pbSize-numPutback), gptr()-numPutback,
+                numPutback);
+
+        // read at most bufSize new characters
+        int num;
+        num = read (fd, buffer+pbSize, bufSize);
+        if (num <= 0) {
+            // ERROR or EOF
+            return EOF;
+        }
+
+        // reset buffer pointers
+        setg (buffer+(pbSize-numPutback),   // beginning of putback area
+              buffer+pbSize,                // read position
+              buffer+pbSize+num);           // end of buffer
+
+        // return next character
+        return traits_type::to_int_type(*gptr());
+    }
+};
+
+class fdistream : public std::istream {
+  protected:
+    fdinbuf buf;
+  public:
+    fdistream (int fd) : std::istream(0), buf(fd) {
+        rdbuf(&buf);
+    }
+};
+
+
+} // END namespace boost
+
+#endif /*BOOST_FDSTREAM_HPP*/
diff --git a/stp/constantbv/Makefile b/stp/constantbv/Makefile
new file mode 100644
index 00000000..cd94ad94
--- /dev/null
+++ b/stp/constantbv/Makefile
@@ -0,0 +1,13 @@
+include ../Makefile.common
+
+SRCS = constantbv.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libconstantbv.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:	
+	rm -rf *.o *~ *.a .#*
+
+constantbv.o: constantbv.h
diff --git a/stp/constantbv/constantbv.cpp b/stp/constantbv/constantbv.cpp
new file mode 100644
index 00000000..65698981
--- /dev/null
+++ b/stp/constantbv/constantbv.cpp
@@ -0,0 +1,3571 @@
+/*****************************************************************************/
+/*  AUTHOR:                                                                  */
+/*****************************************************************************/
+/*                                                                           */
+/*    Steffen Beyer                                                          */
+/*    mailto:sb@engelschall.com                                              */
+/*    http://www.engelschall.com/u/sb/download/                              */
+/*                                                                           */
+/*****************************************************************************/
+/*  COPYRIGHT:                                                               */
+/*****************************************************************************/
+/*                                                                           */
+/*    Copyright (c) 1995 - 2004 by Steffen Beyer.                            */
+/*    All rights reserved.                                                   */
+/*                                                                           */
+/*****************************************************************************/
+/*  LICENSE:                                                                 */
+/*****************************************************************************/
+/*                                                                           */
+/*    This library is free software; you can redistribute it and/or          */
+/*    modify it under the terms of the GNU Library General Public            */
+/*    License as published by the Free Software Foundation; either           */
+/*    version 2 of the License, || (at your option) any later version.       */
+/*                                                                           */
+/*    This library is distributed in the hope that it will be useful,        */
+/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*    MERCHANTABILITY || FITNESS FOR A PARTICULAR PURPOSE. See the GNU       */
+/*    Library General Public License for more details.                       */
+/*                                                                           */
+/*    You should have received a copy of the GNU Library General Public      */
+/*    License along with this library; if not, write to the                  */
+/*    Free Software Foundation, Inc.,                                        */
+/*    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                  */
+/*                                                                           */
+/*    || download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0      */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*  MODULE NAME:  constantbv.cpp                       MODULE TYPE:constantbv*/
+/*****************************************************************************/
+/*  MODULE IMPORTS:                                                          */
+/*****************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <limits.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <string.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <ctype.h>                                  /*  MODULE TYPE:  (sys)  */
+#include "constantbv.h"
+
+namespace CONSTANTBV {
+/*****************************************************************************/
+/*  MODULE IMPLEMENTATION:                                                   */
+/*****************************************************************************/
+    /**********************************************/
+    /* global implementation-intrinsic constants: */
+    /**********************************************/
+
+#define BIT_VECTOR_HIDDEN_WORDS 3
+
+    /*****************************************************************/
+    /* global machine-dependent constants (set by "BitVector_Boot"): */
+    /*****************************************************************/
+
+static unsigned int BITS;     /* = # of bits in machine word (must be power of 2)  */
+static unsigned int MODMASK;  /* = BITS - 1 (mask for calculating modulo BITS)     */
+static unsigned int LOGBITS;  /* = ld(BITS) (logarithmus dualis)                   */
+static unsigned int FACTOR;   /* = ld(BITS / 8) (ld of # of bytes)                 */
+
+static unsigned int LSB = 1;  /* = mask for least significant bit                  */
+static unsigned int MSB;      /* = mask for most significant bit                   */
+
+static unsigned int LONGBITS; /* = # of bits in unsigned long                      */
+
+static unsigned int LOG10;    /* = logarithm to base 10 of BITS - 1                */
+static unsigned int EXP10;    /* = largest possible power of 10 in signed int      */
+
+    /********************************************************************/
+    /* global bit mask table for fast access (set by "BitVector_Boot"): */
+    /********************************************************************/
+
+static unsigned int *  BITMASKTAB;
+
+    /*****************************/
+    /* global macro definitions: */
+    /*****************************/
+
+#define BIT_VECTOR_ZERO_WORDS(target,count) \
+    while (count-- > 0) *target++ = 0;
+
+#define BIT_VECTOR_FILL_WORDS(target,fill,count) \
+    while (count-- > 0) *target++ = fill;
+
+#define BIT_VECTOR_FLIP_WORDS(target,flip,count) \
+    while (count-- > 0) *target++ ^= flip;
+
+#define BIT_VECTOR_COPY_WORDS(target,source,count) \
+    while (count-- > 0) *target++ = *source++;
+
+#define BIT_VECTOR_BACK_WORDS(target,source,count) \
+    { target += count; source += count; while (count-- > 0) *--target = *--source; }
+
+#define BIT_VECTOR_CLR_BIT(address,index) \
+    *(address+(index>>LOGBITS)) &= ~ BITMASKTAB[index & MODMASK];
+
+#define BIT_VECTOR_SET_BIT(address,index) \
+    *(address+(index>>LOGBITS)) |= BITMASKTAB[index & MODMASK];
+
+#define BIT_VECTOR_TST_BIT(address,index) \
+    ((*(address+(index>>LOGBITS)) & BITMASKTAB[index & MODMASK]) != 0)
+
+#define BIT_VECTOR_FLP_BIT(address,index,mask) \
+    (mask = BITMASKTAB[index & MODMASK]), \
+    (((*(addr+(index>>LOGBITS)) ^= mask) & mask) != 0)
+
+#define BIT_VECTOR_DIGITIZE(type,value,digit) \
+    value = (type) ((digit = value) / 10); \
+    digit -= value * 10; \
+    digit += (type) '0';
+
+    /*********************************************************/
+    /* private low-level functions (potentially dangerous!): */
+    /*********************************************************/
+
+static unsigned int power10(unsigned int x) {
+    unsigned int y = 1;
+
+    while (x-- > 0) y *= 10;
+    return(y);
+}
+
+static void BIT_VECTOR_zro_words(unsigned int *  addr, unsigned int count) {
+    BIT_VECTOR_ZERO_WORDS(addr,count)
+}
+
+static void BIT_VECTOR_cpy_words(unsigned int *  target, 
+				 unsigned int *  source, unsigned int count) {
+    BIT_VECTOR_COPY_WORDS(target,source,count)
+}
+
+static void BIT_VECTOR_mov_words(unsigned int *  target, 
+				 unsigned int *  source, unsigned int count) {
+    if (target != source) {
+        if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count)
+        else                 BIT_VECTOR_BACK_WORDS(target,source,count)
+    }
+}
+
+static void BIT_VECTOR_ins_words(unsigned int *  addr, 
+				 unsigned int total, unsigned int count, boolean clear) {
+    unsigned int length;
+
+    if ((total > 0) && (count > 0)) {
+        if (count > total) count = total;
+        length = total - count;
+        if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length);
+        if (clear)      BIT_VECTOR_zro_words(addr,count);
+    }
+}
+
+static void BIT_VECTOR_del_words(unsigned int *  addr, 
+				 unsigned int total, unsigned int count, boolean clear) {
+    unsigned int length;
+
+    if ((total > 0) && (count > 0)) {
+        if (count > total) count = total;
+        length = total - count;
+        if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length);
+        if (clear)      BIT_VECTOR_zro_words(addr+length,count);
+    }
+}
+
+static void BIT_VECTOR_reverse(unsigned char * string, unsigned int length) {
+    unsigned char * last;
+    unsigned char  temp;
+
+    if (length > 1) {
+        last = string + length - 1;
+        while (string < last) {
+            temp = *string;
+            *string = *last;
+            *last = temp;
+            string++;
+            last--;
+        }
+    }
+}
+
+static unsigned int BIT_VECTOR_int2str(unsigned char * string, unsigned int value) {
+    unsigned int  length;
+    unsigned int  digit;
+    unsigned char * work;
+
+    work = string;
+    if (value > 0) {
+        length = 0;
+        while (value > 0) {
+            BIT_VECTOR_DIGITIZE(unsigned int,value,digit)
+            *work++ = (unsigned char) digit;
+            length++;
+        }
+        BIT_VECTOR_reverse(string,length);
+    }
+    else {
+        length = 1;
+        *work++ = (unsigned char) '0';
+    }
+    return(length);
+}
+
+static unsigned int BIT_VECTOR_str2int(unsigned char * string, unsigned int *value) {
+    unsigned int  length;
+    unsigned int  digit;
+
+    *value = 0;
+    length = 0;
+    digit = (unsigned int) *string++;
+    /* separate because isdigit() is likely a macro! */
+    while (isdigit((int)digit) != 0) {
+        length++;
+        digit -= (unsigned int) '0';
+        if (*value) *value *= 10;
+        *value += digit;
+        digit = (unsigned int) *string++;
+    }
+    return(length);
+}
+
+    /********************************************/
+    /* routine to convert error code to string: */
+    /********************************************/
+
+unsigned char * BitVector_Error(ErrCode error) {
+    switch (error) {
+        case ErrCode_Ok:   return( (unsigned char *)     NULL     ); break;
+        case ErrCode_Type: return( (unsigned char *) ERRCODE_TYPE ); break;
+        case ErrCode_Bits: return( (unsigned char *) ERRCODE_BITS ); break;
+        case ErrCode_Word: return( (unsigned char *) ERRCODE_WORD ); break;
+        case ErrCode_Long: return( (unsigned char *) ERRCODE_LONG ); break;
+        case ErrCode_Powr: return( (unsigned char *) ERRCODE_POWR ); break;
+        case ErrCode_Loga: return( (unsigned char *) ERRCODE_LOGA ); break;
+        case ErrCode_Null: return( (unsigned char *) ERRCODE_NULL ); break;
+        case ErrCode_Indx: return( (unsigned char *) ERRCODE_INDX ); break;
+        case ErrCode_Ordr: return( (unsigned char *) ERRCODE_ORDR ); break;
+        case ErrCode_Size: return( (unsigned char *) ERRCODE_SIZE ); break;
+        case ErrCode_Pars: return( (unsigned char *) ERRCODE_PARS ); break;
+        case ErrCode_Ovfl: return( (unsigned char *) ERRCODE_OVFL ); break;
+        case ErrCode_Same: return( (unsigned char *) ERRCODE_SAME ); break;
+        case ErrCode_Expo: return( (unsigned char *) ERRCODE_EXPO ); break;
+        case ErrCode_Zero: return( (unsigned char *) ERRCODE_ZERO ); break;
+        default:           return( (unsigned char *) ERRCODE_OOPS ); break;
+    }
+}
+
+    /*****************************************/
+    /* automatic self-configuration routine: */
+    /*****************************************/
+
+    /*******************************************************/
+    /*                                                     */
+    /*   MUST be called once prior to any other function   */
+    /*   to initialize the machine dependent constants     */
+    /*   of this package! (But call only ONCE, or you      */
+    /*   will suffer memory leaks!)                        */
+    /*                                                     */
+    /*******************************************************/
+
+ErrCode BitVector_Boot(void) {
+    unsigned long longsample = 1L;
+    unsigned int sample = LSB;
+    unsigned int lsb;
+
+    if (sizeof(unsigned int) > sizeof(size_t)) return(ErrCode_Type);
+
+    BITS = 1;
+    while (sample <<= 1) BITS++;    /* determine # of bits in a machine word */
+
+    if (BITS != (sizeof(unsigned int) << 3)) return(ErrCode_Bits);
+
+    if (BITS < 16) return(ErrCode_Word);
+
+    LONGBITS = 1;
+    while (longsample <<= 1) LONGBITS++;  /* = # of bits in an unsigned long */
+
+    if (BITS > LONGBITS) return(ErrCode_Long);
+
+    LOGBITS = 0;
+    sample = BITS;
+    lsb = (sample & LSB);
+    while ((sample >>= 1) && (! lsb)) {
+        LOGBITS++;
+        lsb = (sample & LSB);
+    }
+
+    if (sample) return(ErrCode_Powr);      /* # of bits is not a power of 2! */
+
+    if (BITS != (LSB << LOGBITS)) return(ErrCode_Loga);
+
+    MODMASK = BITS - 1;
+    FACTOR = LOGBITS - 3;  /* ld(BITS / 8) = ld(BITS) - ld(8) = ld(BITS) - 3 */
+    MSB = (LSB << MODMASK);
+
+    BITMASKTAB = (unsigned int * ) malloc((size_t) (BITS << FACTOR));
+
+    if (BITMASKTAB == NULL) return(ErrCode_Null);
+
+    for ( sample = 0; sample < BITS; sample++ ) {
+        BITMASKTAB[sample] = (LSB << sample);
+    }
+
+    LOG10 = (unsigned int) (MODMASK * 0.30103); /* = (BITS - 1) * ( ln 2 / ln 10 ) */
+    EXP10 = power10(LOG10);
+
+    return(ErrCode_Ok);
+}
+
+unsigned int BitVector_Size(unsigned int bits) {          /* bit vector size (# of words)  */
+    unsigned int size;
+
+    size = bits >> LOGBITS;
+    if (bits & MODMASK) size++;
+    return(size);
+}
+
+unsigned int BitVector_Mask(unsigned int bits)           /* bit vector mask (unused bits) */
+{
+    unsigned int mask;
+
+    mask = bits & MODMASK;
+    if (mask) mask = (unsigned int) ~(~0L << mask); else mask = (unsigned int) ~0L;
+    return(mask);
+}
+
+unsigned char * BitVector_Version(void)
+{
+    return((unsigned char *)"6.4");
+}
+
+unsigned int BitVector_Word_Bits(void)
+{
+    return(BITS);
+}
+
+unsigned int BitVector_Long_Bits(void)
+{
+    return(LONGBITS);
+}
+
+/********************************************************************/
+/*                                                                  */
+/*  WARNING: Do not "free()" constant character strings, i.e.,      */
+/*           don't call "BitVector_Dispose()" for strings returned  */
+/*           by "BitVector_Error()" or "BitVector_Version()"!       */
+/*                                                                  */
+/*  ONLY call this function for strings allocated with "malloc()",  */
+/*  i.e., the strings returned by the functions "BitVector_to_*()"  */
+/*  and "BitVector_Block_Read()"!                                   */
+/*                                                                  */
+/********************************************************************/
+
+void BitVector_Dispose(unsigned char * string)                      /* free string   */
+{
+    if (string != NULL) free((void *) string);
+}
+
+void BitVector_Destroy(unsigned int *  addr)                        /* free bitvec   */
+{
+    if (addr != NULL)
+    {
+        addr -= BIT_VECTOR_HIDDEN_WORDS;
+        free((void *) addr);
+    }
+}
+
+void BitVector_Destroy_List(unsigned int *  *  list, unsigned int count)      /* free list     */
+{
+    unsigned int *  *  slot;
+
+    if (list != NULL)
+    {
+        slot = list;
+        while (count-- > 0)
+        {
+            BitVector_Destroy(*slot++);
+        }
+        free((void *) list);
+    }
+}
+
+unsigned int *  BitVector_Create(unsigned int bits, boolean clear)         /* malloc        */
+{
+    unsigned int  size;
+    unsigned int  mask;
+    unsigned int  bytes;
+    unsigned int *  addr;
+    unsigned int *  zero;
+
+    size = BitVector_Size(bits);
+    mask = BitVector_Mask(bits);
+    bytes = (size + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+    addr = (unsigned int * ) malloc((size_t) bytes);
+    if (addr != NULL)
+    {
+        *addr++ = bits;
+        *addr++ = size;
+        *addr++ = mask;
+        if (clear)
+        {
+            zero = addr;
+            BIT_VECTOR_ZERO_WORDS(zero,size)
+        }
+    }
+    return(addr);
+}
+
+unsigned int *  *  BitVector_Create_List(unsigned int bits, boolean clear, unsigned int count)
+{
+    unsigned int *  *  list = NULL;
+    unsigned int *  *  slot;
+    unsigned int *  addr;
+    unsigned int   i;
+
+    if (count > 0)
+    {
+        list = (unsigned int *  * ) malloc(sizeof(unsigned int * ) * count);
+        if (list != NULL)
+        {
+            slot = list;
+            for ( i = 0; i < count; i++ )
+            {
+                addr = BitVector_Create(bits,clear);
+                if (addr == NULL)
+                {
+                    BitVector_Destroy_List(list,i);
+                    return(NULL);
+                }
+                *slot++ = addr;
+            }
+        }
+    }
+    return(list);
+}
+
+unsigned int *  BitVector_Resize(unsigned int *  oldaddr, unsigned int bits)       /* realloc       */
+{
+    unsigned int  bytes;
+    unsigned int  oldsize;
+    unsigned int  oldmask;
+    unsigned int  newsize;
+    unsigned int  newmask;
+    unsigned int *  newaddr;
+    unsigned int *  source;
+    unsigned int *  target;
+
+    oldsize = size_(oldaddr);
+    oldmask = mask_(oldaddr);
+    newsize = BitVector_Size(bits);
+    newmask = BitVector_Mask(bits);
+    if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask;
+    if (newsize <= oldsize)
+    {
+        newaddr = oldaddr;
+        bits_(newaddr) = bits;
+        size_(newaddr) = newsize;
+        mask_(newaddr) = newmask;
+        if (newsize > 0) *(newaddr+newsize-1) &= newmask;
+    }
+    else
+    {
+        bytes = (newsize + BIT_VECTOR_HIDDEN_WORDS) << FACTOR;
+        newaddr = (unsigned int * ) malloc((size_t) bytes);
+        if (newaddr != NULL)
+        {
+            *newaddr++ = bits;
+            *newaddr++ = newsize;
+            *newaddr++ = newmask;
+            target = newaddr;
+            source = oldaddr;
+            newsize -= oldsize;
+            BIT_VECTOR_COPY_WORDS(target,source,oldsize)
+            BIT_VECTOR_ZERO_WORDS(target,newsize)
+        }
+        BitVector_Destroy(oldaddr);
+    }
+    return(newaddr);
+}
+
+unsigned int *  BitVector_Shadow(unsigned int *  addr)     /* makes new, same size but empty */
+{
+    return( BitVector_Create(bits_(addr),true) );
+}
+
+unsigned int *  BitVector_Clone(unsigned int *  addr)               /* makes exact duplicate */
+{
+    unsigned int  bits;
+    unsigned int *  twin;
+
+    bits = bits_(addr);
+    twin = BitVector_Create(bits,false);
+    if ((twin != NULL) && (bits > 0))
+        BIT_VECTOR_cpy_words(twin,addr,size_(addr));
+    return(twin);
+}
+
+unsigned int *  BitVector_Concat(unsigned int *  X, unsigned int *  Y)      /* returns concatenation */
+{
+    /* BEWARE that X = most significant part, Y = least significant part! */
+
+    unsigned int  bitsX;
+    unsigned int  bitsY;
+    unsigned int  bitsZ;
+    unsigned int *  Z;
+
+    bitsX = bits_(X);
+    bitsY = bits_(Y);
+    bitsZ = bitsX + bitsY;
+    Z = BitVector_Create(bitsZ,false);
+    if ((Z != NULL) && (bitsZ > 0))
+    {
+        BIT_VECTOR_cpy_words(Z,Y,size_(Y));
+        BitVector_Interval_Copy(Z,X,bitsY,0,bitsX);
+        *(Z+size_(Z)-1) &= mask_(Z);
+    }
+    return(Z);
+}
+
+void BitVector_Copy(unsigned int *  X, unsigned int *  Y)                           /* X = Y */
+{
+    unsigned int  sizeX = size_(X);
+    unsigned int  sizeY = size_(Y);
+    unsigned int  maskX = mask_(X);
+    unsigned int  maskY = mask_(Y);
+    unsigned int  fill  = 0;
+    unsigned int *  lastX;
+    unsigned int *  lastY;
+
+    if ((X != Y) && (sizeX > 0))
+    {
+        lastX = X + sizeX - 1;
+        if (sizeY > 0)
+        {
+            lastY = Y + sizeY - 1;
+            if ( (*lastY & (maskY & ~ (maskY >> 1))) == 0 ) *lastY &= maskY;
+            else
+            {
+                fill = (unsigned int) ~0L;
+                *lastY |= ~ maskY;
+            }
+            while ((sizeX > 0) && (sizeY > 0))
+            {
+                *X++ = *Y++;
+                sizeX--;
+                sizeY--;
+            }
+            *lastY &= maskY;
+        }
+        while (sizeX-- > 0) *X++ = fill;
+        *lastX &= maskX;
+    }
+}
+
+void BitVector_Empty(unsigned int *  addr)                        /* X = {}  clr all */
+{
+    unsigned int size = size_(addr);
+
+    BIT_VECTOR_ZERO_WORDS(addr,size)
+}
+
+void BitVector_Fill(unsigned int *  addr)                         /* X = ~{} set all */
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+    unsigned int fill = (unsigned int) ~0L;
+
+    if (size > 0)
+    {
+        BIT_VECTOR_FILL_WORDS(addr,fill,size)
+        *(--addr) &= mask;
+    }
+}
+
+void BitVector_Flip(unsigned int *  addr)                         /* X = ~X flip all */
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+    unsigned int flip = (unsigned int) ~0L;
+
+    if (size > 0)
+    {
+        BIT_VECTOR_FLIP_WORDS(addr,flip,size)
+        *(--addr) &= mask;
+    }
+}
+
+void BitVector_Primes(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int *  work;
+    unsigned int  temp;
+    unsigned int  i,j;
+
+    if (size > 0)
+    {
+        temp = 0xAAAA;
+        i = BITS >> 4;
+        while (--i > 0)
+        {
+            temp <<= 16;
+            temp |= 0xAAAA;
+        }
+        i = size;
+        work = addr;
+        *work++ = temp ^ 0x0006;
+        while (--i > 0) *work++ = temp;
+        for ( i = 3; (j = i * i) < bits; i += 2 )
+        {
+            for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j)
+        }
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+void BitVector_Reverse(unsigned int *  X, unsigned int *  Y)
+{
+    unsigned int bits = bits_(X);
+    unsigned int mask;
+    unsigned int bit;
+    unsigned int value;
+
+    if (bits > 0)
+    {
+        if (X == Y) BitVector_Interval_Reverse(X,0,bits-1);
+        else if (bits == bits_(Y))
+        {
+/*          mask = mask_(Y);  */
+/*          mask &= ~ (mask >> 1);  */
+            mask = BITMASKTAB[(bits-1) & MODMASK];
+            Y += size_(Y) - 1;
+            value = 0;
+            bit = LSB;
+            while (bits-- > 0)
+            {
+                if ((*Y & mask) != 0)
+                {
+                    value |= bit;
+                }
+                if (! (mask >>= 1))
+                {
+                    Y--;
+                    mask = MSB;
+                }
+                if (! (bit <<= 1))
+                {
+                    *X++ = value;
+                    value = 0;
+                    bit = LSB;
+                }
+            }
+            if (bit > LSB) *X = value;
+        }
+    }
+}
+
+void BitVector_Interval_Empty(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{                                                  /* X = X \ [lower..upper] */
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lobase;
+    unsigned int  hibase;
+    unsigned int  lomask;
+    unsigned int  himask;
+    unsigned int  diff;
+
+    if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper))
+    {
+        lobase = lower >> LOGBITS;
+        hibase = upper >> LOGBITS;
+        diff = hibase - lobase;
+        loaddr = addr + lobase;
+        hiaddr = addr + hibase;
+
+        lomask = (unsigned int)   (~0L << (lower & MODMASK));
+        himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1);
+
+        if (diff == 0)
+        {
+            *loaddr &= ~ (lomask & himask);
+        }
+        else
+        {
+            *loaddr++ &= ~ lomask;
+            while (--diff > 0)
+            {
+                *loaddr++ = 0;
+            }
+            *hiaddr &= ~ himask;
+        }
+    }
+}
+
+void BitVector_Interval_Fill(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{                                                  /* X = X + [lower..upper] */
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int  fill = (unsigned int) ~0L;
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lobase;
+    unsigned int  hibase;
+    unsigned int  lomask;
+    unsigned int  himask;
+    unsigned int  diff;
+
+    if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper))
+    {
+        lobase = lower >> LOGBITS;
+        hibase = upper >> LOGBITS;
+        diff = hibase - lobase;
+        loaddr = addr + lobase;
+        hiaddr = addr + hibase;
+
+        lomask = (unsigned int)   (~0L << (lower & MODMASK));
+        himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1);
+
+        if (diff == 0)
+        {
+            *loaddr |= (lomask & himask);
+        }
+        else
+        {
+            *loaddr++ |= lomask;
+            while (--diff > 0)
+            {
+                *loaddr++ = fill;
+            }
+            *hiaddr |= himask;
+        }
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+void BitVector_Interval_Flip(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{                                                  /* X = X ^ [lower..upper] */
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int  flip = (unsigned int) ~0L;
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lobase;
+    unsigned int  hibase;
+    unsigned int  lomask;
+    unsigned int  himask;
+    unsigned int  diff;
+
+    if ((size > 0) && (lower < bits) && (upper < bits) && (lower <= upper))
+    {
+        lobase = lower >> LOGBITS;
+        hibase = upper >> LOGBITS;
+        diff = hibase - lobase;
+        loaddr = addr + lobase;
+        hiaddr = addr + hibase;
+
+        lomask = (unsigned int)   (~0L << (lower & MODMASK));
+        himask = (unsigned int) ~((~0L << (upper & MODMASK)) << 1);
+
+        if (diff == 0)
+        {
+            *loaddr ^= (lomask & himask);
+        }
+        else
+        {
+            *loaddr++ ^= lomask;
+            while (--diff > 0)
+            {
+                *loaddr++ ^= flip;
+            }
+            *hiaddr ^= himask;
+        }
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+void BitVector_Interval_Reverse(unsigned int *  addr, unsigned int lower, unsigned int upper)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int *  loaddr;
+    unsigned int *  hiaddr;
+    unsigned int  lomask;
+    unsigned int  himask;
+
+    if ((bits > 0) && (lower < bits) && (upper < bits) && (lower < upper))
+    {
+        loaddr = addr + (lower >> LOGBITS);
+        hiaddr = addr + (upper >> LOGBITS);
+        lomask = BITMASKTAB[lower & MODMASK];
+        himask = BITMASKTAB[upper & MODMASK];
+        for ( bits = upper - lower + 1; bits > 1; bits -= 2 )
+        {
+            if (((*loaddr & lomask) != 0) ^ ((*hiaddr & himask) != 0))
+            {
+                *loaddr ^= lomask;  /* swap bits only if they differ! */
+                *hiaddr ^= himask;
+            }
+            if (! (lomask <<= 1))
+            {
+                lomask = LSB;
+                loaddr++;
+            }
+            if (! (himask >>= 1))
+            {
+                himask = MSB;
+                hiaddr--;
+            }
+        }
+    }
+}
+
+boolean BitVector_interval_scan_inc(unsigned int *  addr, unsigned int start,
+                                    unsigned int * min, unsigned int * max)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  offset;
+    unsigned int  bitmask;
+    unsigned int  value;
+    boolean empty;
+
+    if ((size == 0) || (start >= bits_(addr))) return(false);
+
+    *min = start;
+    *max = start;
+
+    offset = start >> LOGBITS;
+
+    *(addr+size-1) &= mask;
+
+    addr += offset;
+    size -= offset;
+
+    bitmask = BITMASKTAB[start & MODMASK];
+    mask = ~ (bitmask | (bitmask - 1));
+
+    value = *addr++;
+    if ((value & bitmask) == 0)
+    {
+        value &= mask;
+        if (value == 0)
+        {
+            offset++;
+            empty = true;
+            while (empty && (--size > 0))
+            {
+                if ((value = *addr++)) empty = false; else offset++;
+            }
+            if (empty) return(false);
+        }
+        start = offset << LOGBITS;
+        bitmask = LSB;
+        mask = value;
+        while (! (mask & LSB))
+        {
+            bitmask <<= 1;
+            mask >>= 1;
+            start++;
+        }
+        mask = ~ (bitmask | (bitmask - 1));
+        *min = start;
+        *max = start;
+    }
+    value = ~ value;
+    value &= mask;
+    if (value == 0)
+    {
+        offset++;
+        empty = true;
+        while (empty && (--size > 0))
+        {
+            if ((value = ~ *addr++)) empty = false; else offset++;
+        }
+        if (empty) value = LSB;
+    }
+    start = offset << LOGBITS;
+    while (! (value & LSB))
+    {
+        value >>= 1;
+        start++;
+    }
+    *max = --start;
+    return(true);
+}
+
+boolean BitVector_interval_scan_dec(unsigned int *  addr, unsigned int start,
+                                    unsigned int * min, unsigned int * max)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int offset;
+    unsigned int bitmask;
+    unsigned int value;
+    boolean empty;
+
+    if ((size == 0) || (start >= bits_(addr))) return(false);
+
+    *min = start;
+    *max = start;
+
+    offset = start >> LOGBITS;
+
+    if (offset >= size) return(false);
+
+    *(addr+size-1) &= mask;
+
+    addr += offset;
+    size = ++offset;
+
+    bitmask = BITMASKTAB[start & MODMASK];
+    mask = (bitmask - 1);
+
+    value = *addr--;
+    if ((value & bitmask) == 0)
+    {
+        value &= mask;
+        if (value == 0)
+        {
+            offset--;
+            empty = true;
+            while (empty && (--size > 0))
+            {
+                if ((value = *addr--)) empty = false; else offset--;
+            }
+            if (empty) return(false);
+        }
+        start = offset << LOGBITS;
+        bitmask = MSB;
+        mask = value;
+        while (! (mask & MSB))
+        {
+            bitmask >>= 1;
+            mask <<= 1;
+            start--;
+        }
+        mask = (bitmask - 1);
+        *max = --start;
+        *min = start;
+    }
+    value = ~ value;
+    value &= mask;
+    if (value == 0)
+    {
+        offset--;
+        empty = true;
+        while (empty && (--size > 0))
+        {
+            if ((value = ~ *addr--)) empty = false; else offset--;
+        }
+        if (empty) value = MSB;
+    }
+    start = offset << LOGBITS;
+    while (! (value & MSB))
+    {
+        value <<= 1;
+        start--;
+    }
+    *min = start;
+    return(true);
+}
+
+void BitVector_Interval_Copy(unsigned int *  X, unsigned int *  Y, unsigned int Xoffset,
+                             unsigned int Yoffset, unsigned int length)
+{
+    unsigned int  bitsX = bits_(X);
+    unsigned int  bitsY = bits_(Y);
+    unsigned int  source = 0;        /* silence compiler warning */
+    unsigned int  target = 0;        /* silence compiler warning */
+    unsigned int  s_lo_base;
+    unsigned int  s_hi_base;
+    unsigned int  s_lo_bit;
+    unsigned int  s_hi_bit;
+    unsigned int  s_base;
+    unsigned int  s_lower = 0;       /* silence compiler warning */
+    unsigned int  s_upper = 0;       /* silence compiler warning */
+    unsigned int  s_bits;
+    unsigned int  s_min;
+    unsigned int  s_max;
+    unsigned int  t_lo_base;
+    unsigned int  t_hi_base;
+    unsigned int  t_lo_bit;
+    unsigned int  t_hi_bit;
+    unsigned int  t_base;
+    unsigned int  t_lower = 0;       /* silence compiler warning */
+    unsigned int  t_upper = 0;       /* silence compiler warning */
+    unsigned int  t_bits;
+    unsigned int  t_min;
+    unsigned int  mask;
+    unsigned int  bits;
+    unsigned int  select;
+    boolean ascending;
+    boolean notfirst;
+    unsigned int *  Z = X;
+
+    if ((length > 0) && (Xoffset < bitsX) && (Yoffset < bitsY))
+    {
+        if ((Xoffset + length) > bitsX) length = bitsX - Xoffset;
+        if ((Yoffset + length) > bitsY) length = bitsY - Yoffset;
+
+        ascending = (Xoffset <= Yoffset);
+
+        s_lo_base = Yoffset >> LOGBITS;
+        s_lo_bit = Yoffset & MODMASK;
+        Yoffset += --length;
+        s_hi_base = Yoffset >> LOGBITS;
+        s_hi_bit = Yoffset & MODMASK;
+
+        t_lo_base = Xoffset >> LOGBITS;
+        t_lo_bit = Xoffset & MODMASK;
+        Xoffset += length;
+        t_hi_base = Xoffset >> LOGBITS;
+        t_hi_bit = Xoffset & MODMASK;
+
+        if (ascending)
+        {
+            s_base = s_lo_base;
+            t_base = t_lo_base;
+        }
+        else
+        {
+            s_base = s_hi_base;
+            t_base = t_hi_base;
+        }
+        s_bits = 0;
+        t_bits = 0;
+        Y += s_base;
+        X += t_base;
+        notfirst = false;
+        while (true)
+        {
+            if (t_bits == 0)
+            {
+                if (notfirst)
+                {
+                    *X = target;
+                    if (ascending)
+                    {
+                        if (t_base == t_hi_base) break;
+                        t_base++;
+                        X++;
+                    }
+                    else
+                    {
+                        if (t_base == t_lo_base) break;
+                        t_base--;
+                        X--;
+                    }
+                }
+                select = ((t_base == t_hi_base) << 1) | (t_base == t_lo_base);
+                switch (select)
+                {
+                    case 0:
+                        t_lower = 0;
+                        t_upper = BITS - 1;
+                        t_bits = BITS;
+                        target = 0;
+                        break;
+                    case 1:
+                        t_lower = t_lo_bit;
+                        t_upper = BITS - 1;
+                        t_bits = BITS - t_lo_bit;
+                        mask = (unsigned int) (~0L << t_lower);
+                        target = *X & ~ mask;
+                        break;
+                    case 2:
+                        t_lower = 0;
+                        t_upper = t_hi_bit;
+                        t_bits = t_hi_bit + 1;
+                        mask = (unsigned int) ((~0L << t_upper) << 1);
+                        target = *X & mask;
+                        break;
+                    case 3:
+                        t_lower = t_lo_bit;
+                        t_upper = t_hi_bit;
+                        t_bits = t_hi_bit - t_lo_bit + 1;
+                        mask = (unsigned int) (~0L << t_lower);
+                        mask &= (unsigned int) ~((~0L << t_upper) << 1);
+                        target = *X & ~ mask;
+                        break;
+                }
+            }
+            if (s_bits == 0)
+            {
+                if (notfirst)
+                {
+                    if (ascending)
+                    {
+                        if (s_base == s_hi_base) break;
+                        s_base++;
+                        Y++;
+                    }
+                    else
+                    {
+                        if (s_base == s_lo_base) break;
+                        s_base--;
+                        Y--;
+                    }
+                }
+                source = *Y;
+                select = ((s_base == s_hi_base) << 1) | (s_base == s_lo_base);
+                switch (select)
+                {
+                    case 0:
+                        s_lower = 0;
+                        s_upper = BITS - 1;
+                        s_bits = BITS;
+                        break;
+                    case 1:
+                        s_lower = s_lo_bit;
+                        s_upper = BITS - 1;
+                        s_bits = BITS - s_lo_bit;
+                        break;
+                    case 2:
+                        s_lower = 0;
+                        s_upper = s_hi_bit;
+                        s_bits = s_hi_bit + 1;
+                        break;
+                    case 3:
+                        s_lower = s_lo_bit;
+                        s_upper = s_hi_bit;
+                        s_bits = s_hi_bit - s_lo_bit + 1;
+                        break;
+                }
+            }
+            notfirst = true;
+            if (s_bits > t_bits)
+            {
+                bits = t_bits - 1;
+                if (ascending)
+                {
+                    s_min = s_lower;
+                    s_max = s_lower + bits;
+                }
+                else
+                {
+                    s_max = s_upper;
+                    s_min = s_upper - bits;
+                }
+                t_min = t_lower;
+            }
+            else
+            {
+                bits = s_bits - 1;
+                if (ascending) t_min = t_lower;
+                else           t_min = t_upper - bits;
+                s_min = s_lower;
+                s_max = s_upper;
+            }
+            bits++;
+            mask = (unsigned int) (~0L << s_min);
+            mask &= (unsigned int) ~((~0L << s_max) << 1);
+            if (s_min == t_min) target |= (source & mask);
+            else
+            {
+                if (s_min < t_min) target |= (source & mask) << (t_min-s_min);
+                else               target |= (source & mask) >> (s_min-t_min);
+            }
+            if (ascending)
+            {
+                s_lower += bits;
+                t_lower += bits;
+            }
+            else
+            {
+                s_upper -= bits;
+                t_upper -= bits;
+            }
+            s_bits -= bits;
+            t_bits -= bits;
+        }
+        *(Z+size_(Z)-1) &= mask_(Z);
+    }
+}
+
+
+unsigned int *  BitVector_Interval_Substitute(unsigned int *  X, unsigned int *  Y,
+                                      unsigned int Xoffset, unsigned int Xlength,
+                                      unsigned int Yoffset, unsigned int Ylength)
+{
+    unsigned int Xbits = bits_(X);
+    unsigned int Ybits = bits_(Y);
+    unsigned int limit;
+    unsigned int diff;
+
+    if ((Xoffset <= Xbits) && (Yoffset <= Ybits))
+    {
+        limit = Xoffset + Xlength;
+        if (limit > Xbits)
+        {
+            limit = Xbits;
+            Xlength = Xbits - Xoffset;
+        }
+        if ((Yoffset + Ylength) > Ybits)
+        {
+            Ylength = Ybits - Yoffset;
+        }
+        if (Xlength == Ylength)
+        {
+            if ((Ylength > 0) && ((X != Y) || (Xoffset != Yoffset)))
+            {
+                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+            }
+        }
+        else /* Xlength != Ylength */
+        {
+            if (Xlength > Ylength)
+            {
+                diff = Xlength - Ylength;
+                if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,false);
+                if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL);
+            }
+            else /* Ylength > Xlength  ==>  Ylength > 0 */
+            {
+                diff = Ylength - Xlength;
+                if (X != Y)
+                {
+                    if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+                    if (limit < Xbits) BitVector_Insert(X,limit,diff,false);
+                    BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                }
+                else /* in-place */
+                {
+                    if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL);
+                    if (limit >= Xbits)
+                    {
+                        BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                    }
+                    else /* limit < Xbits */
+                    {
+                        BitVector_Insert(X,limit,diff,false);
+                        if ((Yoffset+Ylength) <= limit)
+                        {
+                            BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                        }
+                        else /* overlaps or lies above critical area */
+                        {
+                            if (limit <= Yoffset)
+                            {
+                                Yoffset += diff;
+                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                            }
+                            else /* Yoffset < limit */
+                            {
+                                Xlength = limit - Yoffset;
+                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength);
+                                Yoffset = Xoffset + Ylength; /* = limit + diff */
+                                Xoffset += Xlength;
+                                Ylength -= Xlength;
+                                BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return(X);
+}
+
+boolean BitVector_is_empty(unsigned int *  addr)                    /* X == {} ?     */
+{
+    unsigned int  size = size_(addr);
+    boolean r = true;
+
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while (r && (size-- > 0)) r = ( *addr++ == 0 );
+    }
+    return(r);
+}
+
+boolean BitVector_is_full(unsigned int *  addr)                     /* X == ~{} ?    */
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean r = false;
+    unsigned int *  last;
+
+    if (size > 0)
+    {
+        r = true;
+        last = addr + size - 1;
+        *last |= ~ mask;
+        while (r && (size-- > 0)) r = ( ~ *addr++ == 0 );
+        *last &= mask;
+    }
+    return(r);
+}
+
+boolean BitVector_equal(unsigned int *  X, unsigned int *  Y)               /* X == Y ?      */
+{
+    unsigned int  size = size_(X);
+    unsigned int  mask = mask_(X);
+    boolean r = false;
+
+    if (bits_(X) == bits_(Y))
+    {
+        r = true;
+        if (size > 0)
+        {
+            *(X+size-1) &= mask;
+            *(Y+size-1) &= mask;
+            while (r && (size-- > 0)) r = (*X++ == *Y++);
+        }
+    }
+    return(r);
+}
+
+/* X <,=,> Y ?     : unsigned     */
+signed int BitVector_Lexicompare(unsigned int *  X, unsigned int *  Y) {
+    unsigned int  bitsX = bits_(X);
+    unsigned int  bitsY = bits_(Y);
+    unsigned int  size  = size_(X);
+    boolean r = true;
+
+    if (bitsX == bitsY) {
+        if (size > 0) {
+            X += size;
+            Y += size;
+            while (r && (size-- > 0)) r = (*(--X) == *(--Y));
+        }
+        if (r) return((signed int) 0);
+        else {
+            if (*X < *Y) return((signed int) -1); else return((signed int) 1);
+        }
+    }
+    else {
+        if (bitsX < bitsY) return((signed int) -1); else return((signed int) 1);
+    }
+}
+
+signed int BitVector_Compare(unsigned int *  X, unsigned int *  Y)               /* X <,=,> Y ?   */
+{                                                           /*   signed      */
+    unsigned int  bitsX = bits_(X);
+    unsigned int  bitsY = bits_(Y);
+    unsigned int  size  = size_(X);
+    unsigned int  mask  = mask_(X);
+    unsigned int  sign;
+    boolean r = true;
+
+    if (bitsX == bitsY)
+    {
+        if (size > 0)
+        {
+            X += size;
+            Y += size;
+            mask &= ~ (mask >> 1);
+            if ((sign = (*(X-1) & mask)) != (*(Y-1) & mask))
+            {
+                if (sign) return((signed int) -1); else return((signed int) 1);
+            }
+            while (r && (size-- > 0)) r = (*(--X) == *(--Y));
+        }
+        if (r) return((signed int) 0);
+        else
+        {
+            if (*X < *Y) return((signed int) -1); else return((signed int) 1);
+        }
+    }
+    else
+    {
+        if (bitsX < bitsY) return((signed int) -1); else return((signed int) 1);
+    }
+}
+
+size_t BitVector_Hash(unsigned int * addr)
+{
+  unsigned int  bits = bits_(addr);
+  unsigned int  size = size_(addr);
+  unsigned int  value;
+  unsigned int  count;
+  unsigned int  digit;
+  unsigned int  length;
+    
+  size_t result = 0;
+
+  length = bits >> 2;
+  if (bits & 0x0003) length++;
+  if (size > 0)
+    {
+      *(addr+size-1) &= mask_(addr);
+      while ((size-- > 0) && (length > 0))
+        {
+          value = *addr++;
+          count = BITS >> 2;
+          while ((count-- > 0) && (length > 0))
+            {
+              digit = value & 0x000F;
+              if (digit > 9) digit += (unsigned int) 'A' - 10;
+              else           digit += (unsigned int) '0';
+              result = 5*result + digit; length--;
+              if ((count > 0) && (length > 0)) value >>= 4;
+            }
+        }
+    }
+  return result;
+}
+
+
+unsigned char * BitVector_to_Hex(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  size = size_(addr);
+    unsigned int  value;
+    unsigned int  count;
+    unsigned int  digit;
+    unsigned int  length;
+    unsigned char * string;
+
+    length = bits >> 2;
+    if (bits & 0x0003) length++;
+    string = (unsigned char *) malloc((size_t) (length+1));
+    if (string == NULL) return(NULL);
+    string += length;
+    *string = (unsigned char) '\0';
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while ((size-- > 0) && (length > 0))
+        {
+            value = *addr++;
+            count = BITS >> 2;
+            while ((count-- > 0) && (length > 0))
+            {
+                digit = value & 0x000F;
+                if (digit > 9) digit += (unsigned int) 'A' - 10;
+                else           digit += (unsigned int) '0';
+                *(--string) = (unsigned char) digit; length--;
+                if ((count > 0) && (length > 0)) value >>= 4;
+            }
+        }
+    }
+    return(string);
+}
+
+ErrCode BitVector_from_Hex(unsigned int *  addr, unsigned char * string)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean ok = true;
+    unsigned int  length;
+    unsigned int  value;
+    unsigned int  count;
+    int     digit;
+
+    if (size > 0)
+    {
+        length = strlen((char *) string);
+        string += length;
+        while (size-- > 0)
+        {
+            value = 0;
+            for ( count = 0; (ok && (length > 0) && (count < BITS)); count += 4 )
+            {
+                digit = (int) *(--string); length--;
+                /* separate because toupper() is likely a macro! */
+                digit = toupper(digit);
+                if ((ok = (isxdigit(digit) != 0)))
+                {
+		  if (digit >= (int) 'A') digit -= (int) 'A' - 10;
+		  else                    digit -= (int) '0';
+		  value |= (((unsigned int) digit) << count);
+                }
+            }
+            *addr++ = value;
+        }
+        *(--addr) &= mask;
+    }
+    if (ok) return(ErrCode_Ok);
+    else    return(ErrCode_Pars);
+}
+
+unsigned char * BitVector_to_Bin(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  value;
+    unsigned int  count;
+    unsigned int  digit;
+    unsigned int  length;
+    unsigned char * string;
+
+    length = bits_(addr);
+    string = (unsigned char *) malloc((size_t) (length+1));
+    if (string == NULL) return(NULL);
+    string += length;
+    *string = (unsigned char) '\0';
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while (size-- > 0)
+        {
+            value = *addr++;
+            count = BITS;
+            if (count > length) count = length;
+            while (count-- > 0)
+            {
+                digit = value & 0x0001;
+                digit += (unsigned int) '0';
+                *(--string) = (unsigned char) digit; length--;
+                if (count > 0) value >>= 1;
+            }
+        }
+    }
+    return(string);
+}
+
+ErrCode BitVector_from_Bin(unsigned int *  addr, unsigned char * string)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean ok = true;
+    unsigned int  length;
+    unsigned int  value;
+    unsigned int  count;
+    int     digit;
+
+    if (size > 0)
+    {
+        length = strlen((char *) string);
+        string += length;
+        while (size-- > 0)
+        {
+            value = 0;
+            for ( count = 0; (ok && (length > 0) && (count < BITS)); count++ )
+            {
+                digit = (int) *(--string); length--;
+                switch (digit)
+                {
+                    case (int) '0':
+                        break;
+                    case (int) '1':
+                        value |= BITMASKTAB[count];
+                        break;
+                    default:
+                        ok = false;
+                        break;
+                }
+            }
+            *addr++ = value;
+        }
+        *(--addr) &= mask;
+    }
+    if (ok) return(ErrCode_Ok);
+    else    return(ErrCode_Pars);
+}
+
+unsigned char * BitVector_to_Dec(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  length;
+    unsigned int  digits;
+    unsigned int  count;
+    unsigned int  q;
+    unsigned int  r;
+    boolean loop;
+    unsigned char * result;
+    unsigned char * string;
+    unsigned int *  quot;
+    unsigned int *  rest;
+    unsigned int *  temp;
+    unsigned int *  base;
+    signed int   sign;
+
+    length = (unsigned int) (bits / 3.3);        /* digits = bits * ln(2) / ln(10) */
+    length += 2; /* compensate for truncating & provide space for minus sign */
+    result = (unsigned char *) malloc((size_t) (length+1));    /* remember the '\0'! */
+    if (result == NULL) return(NULL);
+    string = result;
+    sign = BitVector_Sign(addr);
+    if ((bits < 4) || (sign == 0))
+    {
+        if (bits > 0) digits = *addr; else digits = (unsigned int) 0;
+        if (sign < 0) digits = ((unsigned int)(-((signed int)digits))) & mask_(addr);
+        *string++ = (unsigned char) digits + (unsigned char) '0';
+        digits = 1;
+    }
+    else
+    {
+        quot = BitVector_Create(bits,false);
+        if (quot == NULL)
+        {
+            BitVector_Dispose(result);
+            return(NULL);
+        }
+        rest = BitVector_Create(bits,false);
+        if (rest == NULL)
+        {
+            BitVector_Dispose(result);
+            BitVector_Destroy(quot);
+            return(NULL);
+        }
+        temp = BitVector_Create(bits,false);
+        if (temp == NULL)
+        {
+            BitVector_Dispose(result);
+            BitVector_Destroy(quot);
+            BitVector_Destroy(rest);
+            return(NULL);
+        }
+        base = BitVector_Create(bits,true);
+        if (base == NULL)
+        {
+            BitVector_Dispose(result);
+            BitVector_Destroy(quot);
+            BitVector_Destroy(rest);
+            BitVector_Destroy(temp);
+            return(NULL);
+        }
+        if (sign < 0) BitVector_Negate(quot,addr);
+        else           BitVector_Copy(quot,addr);
+        digits = 0;
+        *base = EXP10;
+        loop = (bits >= BITS);
+        do
+        {
+            if (loop)
+            {
+                BitVector_Copy(temp,quot);
+                if (BitVector_Div_Pos(quot,temp,base,rest))
+                {
+                    BitVector_Dispose(result); /* emergency exit */
+                    BitVector_Destroy(quot);
+                    BitVector_Destroy(rest);   /* should never occur */
+                    BitVector_Destroy(temp);   /* under normal operation */
+                    BitVector_Destroy(base);
+                    return(NULL);
+                }
+                loop = ! BitVector_is_empty(quot);
+                q = *rest;
+            }
+            else q = *quot;
+            count = LOG10;
+            while (((loop && (count-- > 0)) || ((! loop) && (q != 0))) &&
+                (digits < length))
+            {
+                if (q != 0)
+                {
+                    BIT_VECTOR_DIGITIZE(unsigned int,q,r)
+                }
+                else r = (unsigned int) '0';
+                *string++ = (unsigned char) r;
+                digits++;
+            }
+        }
+        while (loop && (digits < length));
+        BitVector_Destroy(quot);
+        BitVector_Destroy(rest);
+        BitVector_Destroy(temp);
+        BitVector_Destroy(base);
+    }
+    if ((sign < 0) && (digits < length))
+    {
+        *string++ = (unsigned char) '-';
+        digits++;
+    }
+    *string = (unsigned char) '\0';
+    BIT_VECTOR_reverse(result,digits);
+    return(result);
+}
+
+ErrCode BitVector_from_Dec(unsigned int *  addr, unsigned char * string)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(addr);
+    unsigned int  mask = mask_(addr);
+    boolean init = (bits > BITS);
+    boolean minus;
+    boolean shift;
+    boolean carry;
+    unsigned int *  term;
+    unsigned int *  base;
+    unsigned int *  prod;
+    unsigned int *  rank;
+    unsigned int *  temp;
+    unsigned int  accu;
+    unsigned int  powr;
+    unsigned int  count;
+    unsigned int  length;
+    int     digit;
+
+    if (bits > 0)
+    {
+        length = strlen((char *) string);
+        if (length == 0) return(ErrCode_Pars);
+        digit = (int) *string;
+        if ((minus = (digit == (int) '-')) ||
+                     (digit == (int) '+'))
+        {
+            string++;
+            if (--length == 0) return(ErrCode_Pars);
+        }
+        string += length;
+        term = BitVector_Create(BITS,false);
+        if (term == NULL)
+        {
+            return(ErrCode_Null);
+        }
+        base = BitVector_Create(BITS,false);
+        if (base == NULL)
+        {
+            BitVector_Destroy(term);
+            return(ErrCode_Null);
+        }
+        prod = BitVector_Create(bits,init);
+        if (prod == NULL)
+        {
+            BitVector_Destroy(term);
+            BitVector_Destroy(base);
+            return(ErrCode_Null);
+        }
+        rank = BitVector_Create(bits,init);
+        if (rank == NULL)
+        {
+            BitVector_Destroy(term);
+            BitVector_Destroy(base);
+            BitVector_Destroy(prod);
+            return(ErrCode_Null);
+        }
+        temp = BitVector_Create(bits,false);
+        if (temp == NULL)
+        {
+            BitVector_Destroy(term);
+            BitVector_Destroy(base);
+            BitVector_Destroy(prod);
+            BitVector_Destroy(rank);
+            return(ErrCode_Null);
+        }
+        BitVector_Empty(addr);
+        *base = EXP10;
+        shift = false;
+        while ((! error) && (length > 0))
+        {
+            accu = 0;
+            powr = 1;
+            count = LOG10;
+            while ((! error) && (length > 0) && (count-- > 0))
+            {
+                digit = (int) *(--string); length--;
+                /* separate because isdigit() is likely a macro! */
+                if (isdigit(digit) != 0)
+                {
+                    accu += ((unsigned int) digit - (unsigned int) '0') * powr;
+                    powr *= 10;
+                }
+                else error = ErrCode_Pars;
+            }
+            if (! error)
+            {
+                if (shift)
+                {
+                    *term = accu;
+                    BitVector_Copy(temp,rank);
+                    error = BitVector_Mul_Pos(prod,temp,term,false);
+                }
+                else
+                {
+                    *prod = accu;
+                    if ((! init) && ((accu & ~ mask) != 0)) error = ErrCode_Ovfl;
+                }
+                if (! error)
+                {
+                    carry = false;
+                    BitVector_compute(addr,addr,prod,false,&carry);
+                    /* ignores sign change (= overflow) but ! */
+                    /* numbers too large (= carry) for resulting bit vector */
+                    if (carry) error = ErrCode_Ovfl;
+                    else
+                    {
+                        if (length > 0)
+                        {
+                            if (shift)
+                            {
+                                BitVector_Copy(temp,rank);
+                                error = BitVector_Mul_Pos(rank,temp,base,false);
+                            }
+                            else
+                            {
+                                *rank = *base;
+                                shift = true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        BitVector_Destroy(term);
+        BitVector_Destroy(base);
+        BitVector_Destroy(prod);
+        BitVector_Destroy(rank);
+        BitVector_Destroy(temp);
+        if (! error && minus)
+        {
+            BitVector_Negate(addr,addr);
+            if ((*(addr + size_(addr) - 1) & mask & ~ (mask >> 1)) == 0)
+                error = ErrCode_Ovfl;
+        }
+    }
+    return(error);
+}
+
+unsigned char * BitVector_to_Enum(unsigned int *  addr)
+{
+    unsigned int  bits = bits_(addr);
+    unsigned int  sample;
+    unsigned int  length;
+    unsigned int  digits;
+    unsigned int  factor;
+    unsigned int  power;
+    unsigned int  start;
+    unsigned int  min;
+    unsigned int  max;
+    unsigned char * string;
+    unsigned char * target;
+    boolean comma;
+
+    if (bits > 0)
+    {
+        sample = bits - 1;  /* greatest possible index */
+        length = 2;         /* account for index 0 && terminating '\0' */
+        digits = 1;         /* account for intervening dashes && commas */
+        factor = 1;
+        power = 10;
+        while (sample >= (power-1))
+        {
+            length += ++digits * factor * 6;  /* 9,90,900,9000,... (9*2/3 = 6) */
+            factor = power;
+            power *= 10;
+        }
+        if (sample > --factor)
+        {
+            sample -= factor;
+            factor = (unsigned int) ( sample / 3 );
+            factor = (factor << 1) + (sample - (factor * 3));
+            length += ++digits * factor;
+        }
+    }
+    else length = 1;
+    string = (unsigned char *) malloc((size_t) length);
+    if (string == NULL) return(NULL);
+    start = 0;
+    comma = false;
+    target = string;
+    while ((start < bits) && BitVector_interval_scan_inc(addr,start,&min,&max))
+    {
+        start = max + 2;
+        if (comma) *target++ = (unsigned char) ',';
+        if (min == max)
+        {
+            target += BIT_VECTOR_int2str(target,min);
+        }
+        else
+        {
+            if (min+1 == max)
+            {
+                target += BIT_VECTOR_int2str(target,min);
+                *target++ = (unsigned char) ',';
+                target += BIT_VECTOR_int2str(target,max);
+            }
+            else
+            {
+                target += BIT_VECTOR_int2str(target,min);
+                *target++ = (unsigned char) '-';
+                target += BIT_VECTOR_int2str(target,max);
+            }
+        }
+        comma = true;
+    }
+    *target = (unsigned char) '\0';
+    return(string);
+}
+
+ErrCode BitVector_from_Enum(unsigned int *  addr, unsigned char * string)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(addr);
+    unsigned int  state = 1;
+    unsigned int  token;
+    unsigned int  index = 0;
+    unsigned int  start = 0;         /* silence compiler warning */
+
+    if (bits > 0)
+    {
+        BitVector_Empty(addr);
+        while ((! error) && (state != 0))
+        {
+            token = (unsigned int) *string;
+            /* separate because isdigit() is likely a macro! */
+            if (isdigit((int)token) != 0)
+            {
+                string += BIT_VECTOR_str2int(string,&index);
+                if (index < bits) token = (unsigned int) '0';
+                else error = ErrCode_Indx;
+            }
+            else string++;
+            if (! error)
+            switch (state)
+            {
+                case 1:
+                    switch (token)
+                    {
+                        case (unsigned int) '0':
+                            state = 2;
+                            break;
+                        case (unsigned int) '\0':
+                            state = 0;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 2:
+                    switch (token)
+                    {
+                        case (unsigned int) '-':
+                            start = index;
+                            state = 3;
+                            break;
+                        case (unsigned int) ',':
+                            BIT_VECTOR_SET_BIT(addr,index)
+                            state = 5;
+                            break;
+                        case (unsigned int) '\0':
+                            BIT_VECTOR_SET_BIT(addr,index)
+                            state = 0;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 3:
+                    switch (token)
+                    {
+                        case (unsigned int) '0':
+                            if (start < index)
+                                BitVector_Interval_Fill(addr,start,index);
+                            else if (start == index)
+                                BIT_VECTOR_SET_BIT(addr,index)
+                            else error = ErrCode_Ordr;
+                            state = 4;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 4:
+                    switch (token)
+                    {
+                        case (unsigned int) ',':
+                            state = 5;
+                            break;
+                        case (unsigned int) '\0':
+                            state = 0;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+                case 5:
+                    switch (token)
+                    {
+                        case (unsigned int) '0':
+                            state = 2;
+                            break;
+                        default:
+                            error = ErrCode_Pars;
+                            break;
+                    }
+                    break;
+            }
+        }
+    }
+    return(error);
+}
+
+void BitVector_Bit_Off(unsigned int *  addr, unsigned int index)           /* X = X \ {x}   */
+{
+    if (index < bits_(addr)) BIT_VECTOR_CLR_BIT(addr,index)
+}
+
+void BitVector_Bit_On(unsigned int *  addr, unsigned int index)            /* X = X + {x}   */
+{
+    if (index < bits_(addr)) BIT_VECTOR_SET_BIT(addr,index)
+}
+
+boolean BitVector_bit_flip(unsigned int *  addr, unsigned int index)   /* X=(X+{x})\(X*{x}) */
+{
+    unsigned int mask;
+
+    if (index < bits_(addr)) return( BIT_VECTOR_FLP_BIT(addr,index,mask) );
+    else                     return( false );
+}
+
+boolean BitVector_bit_test(unsigned int *  addr, unsigned int index)       /* {x} in X ?    */
+{
+    if (index < bits_(addr)) return( BIT_VECTOR_TST_BIT(addr,index) );
+    else                     return( false );
+}
+
+void BitVector_Bit_Copy(unsigned int *  addr, unsigned int index, boolean bit)
+{
+    if (index < bits_(addr))
+    {
+        if (bit) BIT_VECTOR_SET_BIT(addr,index)
+        else     BIT_VECTOR_CLR_BIT(addr,index)
+    }
+}
+
+void BitVector_LSB(unsigned int *  addr, boolean bit)
+{
+    if (bits_(addr) > 0)
+    {
+        if (bit) *addr |= LSB;
+        else     *addr &= ~ LSB;
+    }
+}
+
+void BitVector_MSB(unsigned int *  addr, boolean bit)
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+
+    if (size-- > 0)
+    {
+        if (bit) *(addr+size) |= mask & ~ (mask >> 1);
+        else     *(addr+size) &= ~ mask | (mask >> 1);
+    }
+}
+
+boolean BitVector_lsb_(unsigned int *  addr)
+{
+    if (size_(addr) > 0) return( (*addr & LSB) != 0 );
+    else                 return( false );
+}
+
+boolean BitVector_msb_(unsigned int *  addr)
+{
+    unsigned int size = size_(addr);
+    unsigned int mask = mask_(addr);
+
+    if (size-- > 0)
+        return( (*(addr+size) & (mask & ~ (mask >> 1))) != 0 );
+    else
+        return( false );
+}
+
+boolean BitVector_rotate_left(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_in;
+    boolean carry_out = false;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        carry_in = ((*(addr+size-1) & msb) != 0);
+        while (size-- > 1)
+        {
+            carry_out = ((*addr & MSB) != 0);
+            *addr <<= 1;
+            if (carry_in) *addr |= LSB;
+            carry_in = carry_out;
+            addr++;
+        }
+        carry_out = ((*addr & msb) != 0);
+        *addr <<= 1;
+        if (carry_in) *addr |= LSB;
+        *addr &= mask;
+    }
+    return(carry_out);
+}
+
+boolean BitVector_rotate_right(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_in;
+    boolean carry_out = false;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        carry_in = ((*addr & LSB) != 0);
+        addr += size-1;
+        *addr &= mask;
+        carry_out = ((*addr & LSB) != 0);
+        *addr >>= 1;
+        if (carry_in) *addr |= msb;
+        carry_in = carry_out;
+        addr--;
+        size--;
+        while (size-- > 0)
+        {
+            carry_out = ((*addr & LSB) != 0);
+            *addr >>= 1;
+            if (carry_in) *addr |= MSB;
+            carry_in = carry_out;
+            addr--;
+        }
+    }
+    return(carry_out);
+}
+
+boolean BitVector_shift_left(unsigned int *  addr, boolean carry_in)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_out = carry_in;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        while (size-- > 1)
+        {
+            carry_out = ((*addr & MSB) != 0);
+            *addr <<= 1;
+            if (carry_in) *addr |= LSB;
+            carry_in = carry_out;
+            addr++;
+        }
+        carry_out = ((*addr & msb) != 0);
+        *addr <<= 1;
+        if (carry_in) *addr |= LSB;
+        *addr &= mask;
+    }
+    return(carry_out);
+}
+
+boolean BitVector_shift_right(unsigned int *  addr, boolean carry_in)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  msb;
+    boolean carry_out = carry_in;
+
+    if (size > 0)
+    {
+        msb = mask & ~ (mask >> 1);
+        addr += size-1;
+        *addr &= mask;
+        carry_out = ((*addr & LSB) != 0);
+        *addr >>= 1;
+        if (carry_in) *addr |= msb;
+        carry_in = carry_out;
+        addr--;
+        size--;
+        while (size-- > 0)
+        {
+            carry_out = ((*addr & LSB) != 0);
+            *addr >>= 1;
+            if (carry_in) *addr |= MSB;
+            carry_in = carry_out;
+            addr--;
+        }
+    }
+    return(carry_out);
+}
+
+void BitVector_Move_Left(unsigned int *  addr, unsigned int bits)
+{
+    unsigned int count;
+    unsigned int words;
+
+    if (bits > 0)
+    {
+        count = bits & MODMASK;
+        words = bits >> LOGBITS;
+        if (bits >= bits_(addr)) BitVector_Empty(addr);
+        else
+        {
+            while (count-- > 0) BitVector_shift_left(addr,0);
+            BitVector_Word_Insert(addr,0,words,true);
+        }
+    }
+}
+
+void BitVector_Move_Right(unsigned int *  addr, unsigned int bits)
+{
+    unsigned int count;
+    unsigned int words;
+
+    if (bits > 0)
+    {
+        count = bits & MODMASK;
+        words = bits >> LOGBITS;
+        if (bits >= bits_(addr)) BitVector_Empty(addr);
+        else
+        {
+            while (count-- > 0) BitVector_shift_right(addr,0);
+            BitVector_Word_Delete(addr,0,words,true);
+        }
+    }
+}
+
+void BitVector_Insert(unsigned int *  addr, unsigned int offset, unsigned int count, boolean clear)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int last;
+
+    if ((count > 0) && (offset < bits))
+    {
+        last = offset + count;
+        if (last < bits)
+        {
+            BitVector_Interval_Copy(addr,addr,last,offset,(bits-last));
+        }
+        else last = bits;
+        if (clear) BitVector_Interval_Empty(addr,offset,(last-1));
+    }
+}
+
+void BitVector_Delete(unsigned int *  addr, unsigned int offset, unsigned int count, boolean clear)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int last;
+
+    if ((count > 0) && (offset < bits))
+    {
+        last = offset + count;
+        if (last < bits)
+        {
+            BitVector_Interval_Copy(addr,addr,offset,last,(bits-last));
+        }
+        else count = bits - offset;
+        if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1));
+    }
+}
+
+boolean BitVector_increment(unsigned int *  addr)                   /* X++           */
+{
+    unsigned int  size  = size_(addr);
+    unsigned int  mask  = mask_(addr);
+    unsigned int *  last  = addr + size - 1;
+    boolean carry = true;
+
+    if (size > 0)
+    {
+        *last |= ~ mask;
+        while (carry && (size-- > 0))
+        {
+            carry = (++(*addr++) == 0);
+        }
+        *last &= mask;
+    }
+    return(carry);
+}
+
+boolean BitVector_decrement(unsigned int *  addr)                   /* X--           */
+{
+    unsigned int  size  = size_(addr);
+    unsigned int  mask  = mask_(addr);
+    unsigned int *  last  = addr + size - 1;
+    boolean carry = true;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        while (carry && (size-- > 0))
+        {
+            carry = (*addr == 0);
+            --(*addr++);
+        }
+        *last &= mask;
+    }
+    return(carry);
+}
+
+boolean BitVector_compute(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean minus, boolean *carry)
+{
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+    unsigned int vv = 0;
+    unsigned int cc;
+    unsigned int mm;
+    unsigned int yy;
+    unsigned int zz;
+    unsigned int lo;
+    unsigned int hi;
+
+    if (size > 0)
+    {
+        if (minus) cc = (*carry == 0);
+        else       cc = (*carry != 0);
+        /* deal with (size-1) least significant full words first: */
+        while (--size > 0)
+        {
+            yy = *Y++;
+            if (minus) zz = (unsigned int) ~ ( Z ? *Z++ : 0 );
+            else       zz = (unsigned int)     ( Z ? *Z++ : 0 );
+            lo = (yy & LSB) + (zz & LSB) + cc;
+            hi = (yy >> 1) + (zz >> 1) + (lo >> 1);
+            cc = ((hi & MSB) != 0);
+            *X++ = (hi << 1) | (lo & LSB);
+        }
+        /* deal with most significant word (may be used only partially): */
+        yy = *Y & mask;
+        if (minus) zz = (unsigned int) ~ ( Z ? *Z : 0 );
+        else       zz = (unsigned int)     ( Z ? *Z : 0 );
+        zz &= mask;
+        if (mask == LSB) /* special case, only one bit used */
+        {
+            vv = cc;
+            lo = yy + zz + cc;
+            cc = (lo >> 1);
+            vv ^= cc;
+            *X = lo & LSB;
+        }
+        else
+        {
+            if (~ mask) /* not all bits are used, but more than one */
+            {
+                mm = (mask >> 1);
+                vv = (yy & mm) + (zz & mm) + cc;
+                mm = mask & ~ mm;
+                lo = yy + zz + cc;
+                cc = (lo >> 1);
+                vv ^= cc;
+                vv &= mm;
+                cc &= mm;
+                *X = lo & mask;
+            }
+            else /* other special case, all bits are used */
+            {
+                mm = ~ MSB;
+                lo = (yy & mm) + (zz & mm) + cc;
+                vv = lo & MSB;
+                hi = ((yy & MSB) >> 1) + ((zz & MSB) >> 1) + (vv >> 1);
+                cc = hi & MSB;
+                vv ^= cc;
+                *X = (hi << 1) | (lo & mm);
+            }
+        }
+        if (minus) *carry = (cc == 0);
+        else       *carry = (cc != 0);
+    }
+    return(vv != 0);
+}
+
+boolean BitVector_add(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean *carry)
+{
+    return(BitVector_compute(X,Y,Z,false,carry));
+}
+
+boolean BitVector_sub(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean *carry)
+{
+    return(BitVector_compute(X,Y,Z,true,carry));
+}
+
+boolean BitVector_inc(unsigned int *  X, unsigned int *  Y)
+{
+    boolean carry = true;
+
+    return(BitVector_compute(X,Y,NULL,false,&carry));
+}
+
+boolean BitVector_dec(unsigned int *  X, unsigned int *  Y)
+{
+    boolean carry = true;
+
+    return(BitVector_compute(X,Y,NULL,true,&carry));
+}
+
+void BitVector_Negate(unsigned int *  X, unsigned int *  Y)
+{
+    unsigned int  size  = size_(X);
+    unsigned int  mask  = mask_(X);
+    boolean carry = true;
+
+    if (size > 0)
+    {
+        while (size-- > 0)
+        {
+            *X = ~ *Y++;
+            if (carry)
+            {
+                carry = (++(*X) == 0);
+            }
+            X++;
+        }
+        *(--X) &= mask;
+    }
+}
+
+void BitVector_Absolute(unsigned int *  X, unsigned int *  Y)
+{
+    unsigned int size = size_(Y);
+    unsigned int mask = mask_(Y);
+
+    if (size > 0)
+    {
+        if (*(Y+size-1) & (mask & ~ (mask >> 1))) BitVector_Negate(X,Y);
+        else                                             BitVector_Copy(X,Y);
+    }
+}
+
+// FIXME:  What the hell does the return value of this mean?
+// It returns 0, 1, or -1 under mysterious circumstances.
+signed int BitVector_Sign(unsigned int *  addr)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int *  last = addr + size - 1;
+    boolean r    = true;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        while (r && (size-- > 0)) r = ( *addr++ == 0 );
+    }
+    if (r) return((signed int) 0);
+    else
+    {
+        if (*last & (mask & ~ (mask >> 1))) return((signed int) -1);
+        else                                      return((signed int)  1);
+    }
+}
+
+ErrCode BitVector_Mul_Pos(unsigned int *  X, unsigned int *  Y, unsigned int *  Z, boolean strict)
+{
+    unsigned int  mask;
+    unsigned int  limit;
+    unsigned int  count;
+    signed long  last;
+    unsigned int *  sign;
+    boolean carry;
+    boolean overflow;
+    boolean ok = true;
+
+    /*
+       Requirements:
+         -  X, Y && Z must be distinct
+         -  X && Y must have equal sizes (whereas Z may be any size!)
+         -  Z should always contain the SMALLER of the two factors Y && Z
+       Constraints:
+         -  The contents of Y (&& of X, of course) are destroyed
+            (only Z is preserved!)
+    */
+
+    if ((X == Y) || (X == Z) || (Y == Z)) return(ErrCode_Same);
+    if (bits_(X) != bits_(Y)) return(ErrCode_Size);
+    BitVector_Empty(X);
+    if (BitVector_is_empty(Y)) return(ErrCode_Ok); /* exit also taken if bits_(Y)==0 */
+    if ((last = Set_Max(Z)) < 0L) return(ErrCode_Ok);
+    limit = (unsigned int) last;
+    sign = Y + size_(Y) - 1;
+    mask = mask_(Y);
+    *sign &= mask;
+    mask &= ~ (mask >> 1);
+    for ( count = 0; (ok && (count <= limit)); count++ )
+    {
+        if ( BIT_VECTOR_TST_BIT(Z,count) )
+        {
+            carry = false;
+            overflow = BitVector_compute(X,X,Y,false,&carry);
+            if (strict) ok = ! (carry || overflow);
+            else        ok = !  carry;
+        }
+        if (ok && (count < limit))
+        {
+            carry = BitVector_shift_left(Y,0);
+            if (strict)
+            {
+                overflow = ((*sign & mask) != 0);
+                ok = ! (carry || overflow);
+            }
+            else ok = ! carry;
+        }
+    }
+    if (ok) return(ErrCode_Ok); else return(ErrCode_Ovfl);
+}
+
+ErrCode BitVector_Multiply(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bit_x = bits_(X);
+    unsigned int  bit_y = bits_(Y);
+    unsigned int  bit_z = bits_(Z);
+    unsigned int  size;
+    unsigned int  mask;
+    unsigned int  msb;
+    unsigned int *  ptr_y;
+    unsigned int *  ptr_z;
+    boolean sgn_x;
+    boolean sgn_y;
+    boolean sgn_z;
+    boolean zero;
+    unsigned int *  A;
+    unsigned int *  B;
+
+    /*
+       Requirements:
+         -  Y && Z must have equal sizes
+         -  X must have at least the same size as Y && Z but may be larger (!)
+       Features:
+         -  The contents of Y && Z are preserved
+         -  X may be identical with Y or Z (or both!)
+            (in-place multiplication is possible!)
+    */
+
+    if ((bit_y != bit_z) || (bit_x < bit_y)) return(ErrCode_Size);
+    if (BitVector_is_empty(Y) || BitVector_is_empty(Z))
+    {
+        BitVector_Empty(X);
+    }
+    else
+    {
+        A = BitVector_Create(bit_y,false);
+        if (A == NULL) return(ErrCode_Null);
+        B = BitVector_Create(bit_z,false);
+        if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+        size  = size_(Y);
+        mask  = mask_(Y);
+        msb   = (mask & ~ (mask >> 1));
+        sgn_y = (((*(Y+size-1) &= mask) & msb) != 0);
+        sgn_z = (((*(Z+size-1) &= mask) & msb) != 0);
+        sgn_x = sgn_y ^ sgn_z;
+        if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+        if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+        ptr_y = A + size;
+        ptr_z = B + size;
+        zero = true;
+        while (zero && (size-- > 0))
+        {
+            zero &= (*(--ptr_y) == 0);
+            zero &= (*(--ptr_z) == 0);
+        }
+        if (*ptr_y > *ptr_z)
+        {
+            if (bit_x > bit_y)
+            {
+                A = BitVector_Resize(A,bit_x);
+                if (A == NULL) { BitVector_Destroy(B); return(ErrCode_Null); }
+            }
+            error = BitVector_Mul_Pos(X,A,B,true);
+        }
+        else
+        {
+            if (bit_x > bit_z)
+            {
+                B = BitVector_Resize(B,bit_x);
+                if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+            }
+            error = BitVector_Mul_Pos(X,B,A,true);
+        }
+        if ((! error) && sgn_x) BitVector_Negate(X,X);
+        BitVector_Destroy(A);
+        BitVector_Destroy(B);
+    }
+    return(error);
+}
+
+ErrCode BitVector_Div_Pos(unsigned int *  Q, unsigned int *  X, unsigned int *  Y, unsigned int *  R)
+{
+    unsigned int  bits = bits_(Q);
+    unsigned int  mask;
+    unsigned int *  addr;
+    signed long  last;
+    boolean flag;
+    boolean copy = false; /* flags whether valid rest is in R (0) || X (1) */
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+         -  Q, X, Y && R must all be distinct bit vectors
+         -  Y must be non-zero (of course!)
+       Constraints:
+         -  The contents of X (&& Q && R, of course) are destroyed
+            (only Y is preserved!)
+    */
+
+    if ((bits != bits_(X)) || (bits != bits_(Y)) || (bits != bits_(R)))
+        return(ErrCode_Size);
+    if ((Q == X) || (Q == Y) || (Q == R) || (X == Y) || (X == R) || (Y == R))
+        return(ErrCode_Same);
+    if (BitVector_is_empty(Y))
+        return(ErrCode_Zero);
+
+    BitVector_Empty(R);
+    BitVector_Copy(Q,X);
+    if ((last = Set_Max(Q)) < 0L) return(ErrCode_Ok);
+    bits = (unsigned int) ++last;
+    while (bits-- > 0)
+    {
+        addr = Q + (bits >> LOGBITS);
+        mask = BITMASKTAB[bits & MODMASK];
+        flag = ((*addr & mask) != 0);
+        if (copy)
+        {
+            BitVector_shift_left(X,flag);
+            flag = false;
+            BitVector_compute(R,X,Y,true,&flag);
+        }
+        else
+        {
+            BitVector_shift_left(R,flag);
+            flag = false;
+            BitVector_compute(X,R,Y,true,&flag);
+        }
+        if (flag) *addr &= ~ mask;
+        else
+        {
+            *addr |= mask;
+            copy = ! copy;
+        }
+    }
+    if (copy) BitVector_Copy(R,X);
+    return(ErrCode_Ok);
+}
+
+ErrCode BitVector_Divide(unsigned int *  Q, unsigned int *  X, unsigned int *  Y, unsigned int *  R)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(Q);
+    unsigned int  size = size_(Q);
+    unsigned int  mask = mask_(Q);
+    unsigned int  msb = (mask & ~ (mask >> 1));
+    boolean sgn_q;
+    boolean sgn_x;
+    boolean sgn_y;
+    unsigned int *  A;
+    unsigned int *  B;
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+         -  Q && R must be two distinct bit vectors
+         -  Y must be non-zero (of course!)
+       Features:
+         -  The contents of X && Y are preserved
+         -  Q may be identical with X || Y (or both)
+            (in-place division is possible!)
+         -  R may be identical with X || Y (or both)
+            (but not identical with Q!)
+    */
+
+    if ((bits != bits_(X)) || (bits != bits_(Y)) || (bits != bits_(R)))
+        return(ErrCode_Size);
+    if (Q == R)
+        return(ErrCode_Same);
+    if (BitVector_is_empty(Y))
+        return(ErrCode_Zero);
+
+    if (BitVector_is_empty(X))
+    {
+        BitVector_Empty(Q);
+        BitVector_Empty(R);
+    }
+    else
+    {
+        A = BitVector_Create(bits,false);
+        if (A == NULL) return(ErrCode_Null);
+        B = BitVector_Create(bits,false);
+        if (B == NULL) { BitVector_Destroy(A); return(ErrCode_Null); }
+        size--;
+        sgn_x = (((*(X+size) &= mask) & msb) != 0);
+        sgn_y = (((*(Y+size) &= mask) & msb) != 0);
+        sgn_q = sgn_x ^ sgn_y;
+        if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+        if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+        if (! (error = BitVector_Div_Pos(Q,A,B,R)))
+        {
+            if (sgn_q) BitVector_Negate(Q,Q);
+            if (sgn_x) BitVector_Negate(R,R);
+        }
+        BitVector_Destroy(A);
+        BitVector_Destroy(B);
+    }
+    return(error);
+}
+
+ErrCode BitVector_GCD(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(X);
+    unsigned int  size = size_(X);
+    unsigned int  mask = mask_(X);
+    unsigned int  msb = (mask & ~ (mask >> 1));
+    boolean sgn_a;
+    boolean sgn_b;
+    boolean sgn_r;
+    unsigned int *  Q;
+    unsigned int *  R;
+    unsigned int *  A;
+    unsigned int *  B;
+    unsigned int *  T;
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+       Features:
+         -  The contents of Y && Z are preserved
+         -  X may be identical with Y || Z (or both)
+            (in-place is possible!)
+         -  GCD(0,z) == GCD(z,0) == z
+         -  negative values are h&&led correctly
+    */
+
+    if ((bits != bits_(Y)) || (bits != bits_(Z))) return(ErrCode_Size);
+    if (BitVector_is_empty(Y))
+    {
+        if (X != Z) BitVector_Copy(X,Z);
+        return(ErrCode_Ok);
+    }
+    if (BitVector_is_empty(Z))
+    {
+        if (X != Y) BitVector_Copy(X,Y);
+        return(ErrCode_Ok);
+    }
+    Q = BitVector_Create(bits,false);
+    if (Q == NULL)
+    {
+        return(ErrCode_Null);
+    }
+    R = BitVector_Create(bits,false);
+    if (R == NULL)
+    {
+        BitVector_Destroy(Q);
+        return(ErrCode_Null);
+    }
+    A = BitVector_Create(bits,false);
+    if (A == NULL)
+    {
+        BitVector_Destroy(Q);
+        BitVector_Destroy(R);
+        return(ErrCode_Null);
+    }
+    B = BitVector_Create(bits,false);
+    if (B == NULL)
+    {
+        BitVector_Destroy(Q);
+        BitVector_Destroy(R);
+        BitVector_Destroy(A);
+        return(ErrCode_Null);
+    }
+    size--;
+    sgn_a = (((*(Y+size) &= mask) & msb) != 0);
+    sgn_b = (((*(Z+size) &= mask) & msb) != 0);
+    if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y);
+    if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z);
+    while (! error)
+    {
+        if (! (error = BitVector_Div_Pos(Q,A,B,R)))
+        {
+            if (BitVector_is_empty(R)) break;
+            T = A; sgn_r = sgn_a;
+            A = B; sgn_a = sgn_b;
+            B = R; sgn_b = sgn_r;
+            R = T;
+        }
+    }
+    if (! error)
+    {
+        if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B);
+    }
+    BitVector_Destroy(Q);
+    BitVector_Destroy(R);
+    BitVector_Destroy(A);
+    BitVector_Destroy(B);
+    return(error);
+}
+
+ErrCode BitVector_GCD2(unsigned int *  U, unsigned int *  V, unsigned int *  W, unsigned int *  X, unsigned int *  Y)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits = bits_(U);
+    unsigned int  size = size_(U);
+    unsigned int  mask = mask_(U);
+    unsigned int  msb = (mask & ~ (mask >> 1));
+    boolean minus;
+    boolean carry;
+    boolean sgn_q;
+    boolean sgn_r;
+    boolean sgn_a;
+    boolean sgn_b;
+    boolean sgn_x;
+    boolean sgn_y;
+    unsigned int *  *  L;
+    unsigned int *  Q;
+    unsigned int *  R;
+    unsigned int *  A;
+    unsigned int *  B;
+    unsigned int *  T;
+    unsigned int *  X1;
+    unsigned int *  X2;
+    unsigned int *  X3;
+    unsigned int *  Y1;
+    unsigned int *  Y2;
+    unsigned int *  Y3;
+    unsigned int *  Z;
+
+    /*
+       Requirements:
+         -  All bit vectors must have equal sizes
+         -  U, V, && W must all be distinct bit vectors
+       Features:
+         -  The contents of X && Y are preserved
+         -  U, V && W may be identical with X || Y (or both,
+            provided that U, V && W are mutually distinct)
+            (i.e., in-place is possible!)
+         -  GCD(0,z) == GCD(z,0) == z
+         -  negative values are h&&led correctly
+    */
+
+    if ((bits != bits_(V)) ||
+        (bits != bits_(W)) ||
+        (bits != bits_(X)) ||
+        (bits != bits_(Y)))
+    {
+        return(ErrCode_Size);
+    }
+    if ((U == V) || (U == W) || (V == W))
+    {
+        return(ErrCode_Same);
+    }
+    if (BitVector_is_empty(X))
+    {
+        if (U != Y) BitVector_Copy(U,Y);
+        BitVector_Empty(V);
+        BitVector_Empty(W);
+        *W = 1;
+        return(ErrCode_Ok);
+    }
+    if (BitVector_is_empty(Y))
+    {
+        if (U != X) BitVector_Copy(U,X);
+        BitVector_Empty(V);
+        BitVector_Empty(W);
+        *V = 1;
+        return(ErrCode_Ok);
+    }
+    if ((L = BitVector_Create_List(bits,false,11)) == NULL)
+    {
+        return(ErrCode_Null);
+    }
+    Q  = L[0];
+    R  = L[1];
+    A  = L[2];
+    B  = L[3];
+    X1 = L[4];
+    X2 = L[5];
+    X3 = L[6];
+    Y1 = L[7];
+    Y2 = L[8];
+    Y3 = L[9];
+    Z  = L[10];
+    size--;
+    sgn_a = (((*(X+size) &= mask) & msb) != 0);
+    sgn_b = (((*(Y+size) &= mask) & msb) != 0);
+    if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X);
+    if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y);
+    BitVector_Empty(X1);
+    BitVector_Empty(X2);
+    *X1 = 1;
+    BitVector_Empty(Y1);
+    BitVector_Empty(Y2);
+    *Y2 = 1;
+    sgn_x = false;
+    sgn_y = false;
+    while (! error)
+    {
+        if ((error = BitVector_Div_Pos(Q,A,B,R)))
+        {
+            break;
+        }
+        if (BitVector_is_empty(R))
+        {
+            break;
+        }
+        sgn_q = sgn_a ^ sgn_b;
+
+        if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2);
+        if ((error = BitVector_Mul_Pos(X3,Z,Q,true)))
+        {
+            break;
+        }
+        minus = ! (sgn_x ^ sgn_q);
+        carry = 0;
+        if (BitVector_compute(X3,X1,X3,minus,&carry))
+        {
+            error = ErrCode_Ovfl;
+            break;
+        }
+        sgn_x = (((*(X3+size) &= mask) & msb) != 0);
+
+        if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2);
+        if ((error = BitVector_Mul_Pos(Y3,Z,Q,true)))
+        {
+            break;
+        }
+        minus = ! (sgn_y ^ sgn_q);
+        carry = 0;
+        if (BitVector_compute(Y3,Y1,Y3,minus,&carry))
+        {
+            error = ErrCode_Ovfl;
+            break;
+        }
+        sgn_y = (((*(Y3+size) &= mask) & msb) != 0);
+
+        T = A; sgn_r = sgn_a;
+        A = B; sgn_a = sgn_b;
+        B = R; sgn_b = sgn_r;
+        R = T;
+
+        T = X1;
+        X1 = X2;
+        X2 = X3;
+        X3 = T;
+
+        T = Y1;
+        Y1 = Y2;
+        Y2 = Y3;
+        Y3 = T;
+    }
+    if (! error)
+    {
+        if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B);
+        BitVector_Copy(V,X2);
+        BitVector_Copy(W,Y2);
+    }
+    BitVector_Destroy_List(L,11);
+    return(error);
+}
+
+ErrCode BitVector_Power(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)
+{
+    ErrCode error = ErrCode_Ok;
+    unsigned int  bits  = bits_(X);
+    boolean first = true;
+    signed long  last;
+    unsigned int  limit;
+    unsigned int  count;
+    unsigned int *  T;
+
+    /*
+       Requirements:
+         -  X must have at least the same size as Y but may be larger (!)
+         -  X may not be identical with Z
+         -  Z must be positive
+       Features:
+         -  The contents of Y && Z are preserved
+    */
+
+    if (X == Z) return(ErrCode_Same);
+    if (bits < bits_(Y)) return(ErrCode_Size);
+    if (BitVector_msb_(Z)) return(ErrCode_Expo);
+    if ((last = Set_Max(Z)) < 0L)
+    {
+        if (bits < 2) return(ErrCode_Ovfl);
+        BitVector_Empty(X);
+        *X |= LSB;
+        return(ErrCode_Ok);                             /* anything ^ 0 == 1 */
+    }
+    if (BitVector_is_empty(Y))
+    {
+        if (X != Y) BitVector_Empty(X);
+        return(ErrCode_Ok);                    /* 0 ^ anything ! zero == 0 */
+    }
+    T = BitVector_Create(bits,false);
+    if (T == NULL) return(ErrCode_Null);
+    limit = (unsigned int) last;
+    for ( count = 0; ((!error) && (count <= limit)); count++ )
+    {
+        if ( BIT_VECTOR_TST_BIT(Z,count) )
+        {
+            if (first)
+            {
+                first = false;
+                if (count) {             BitVector_Copy(X,T); }
+                else       { if (X != Y) BitVector_Copy(X,Y); }
+            }
+            else error = BitVector_Multiply(X,T,X); /* order important because T > X */
+        }
+        if ((!error) && (count < limit))
+        {
+            if (count) error = BitVector_Multiply(T,T,T);
+            else       error = BitVector_Multiply(T,Y,Y);
+        }
+    }
+    BitVector_Destroy(T);
+    return(error);
+}
+
+void BitVector_Block_Store(unsigned int *  addr, unsigned char * buffer, unsigned int length)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int  value;
+    unsigned int  count;
+
+    /* provide translation for independence of endian-ness: */
+    if (size > 0)
+    {
+        while (size-- > 0)
+        {
+            value = 0;
+            for ( count = 0; (length > 0) && (count < BITS); count += 8 )
+            {
+                value |= (((unsigned int) *buffer++) << count); length--;
+            }
+            *addr++ = value;
+        }
+        *(--addr) &= mask;
+    }
+}
+
+unsigned char * BitVector_Block_Read(unsigned int *  addr, unsigned int * length)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  value;
+    unsigned int  count;
+    unsigned char * buffer;
+    unsigned char * target;
+
+    /* provide translation for independence of endian-ness: */
+    *length = size << FACTOR;
+    buffer = (unsigned char *) malloc((size_t) ((*length)+1));
+    if (buffer == NULL) return(NULL);
+    target = buffer;
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        while (size-- > 0)
+        {
+            value = *addr++;
+            count = BITS >> 3;
+            while (count-- > 0)
+            {
+                *target++ = (unsigned char) (value & 0x00FF);
+                if (count > 0) value >>= 8;
+            }
+        }
+    }
+    *target = (unsigned char) '\0';
+    return(buffer);
+}
+
+void BitVector_Word_Store(unsigned int *  addr, unsigned int offset, unsigned int value)
+{
+    unsigned int size = size_(addr);
+
+    if (size > 0)
+    {
+        if (offset < size) *(addr+offset) = value;
+        *(addr+size-1) &= mask_(addr);
+    }
+}
+
+unsigned int BitVector_Word_Read(unsigned int *  addr, unsigned int offset)
+{
+    unsigned int size = size_(addr);
+
+    if (size > 0)
+    {
+        *(addr+size-1) &= mask_(addr);
+        if (offset < size) return( *(addr+offset) );
+    }
+    return( (unsigned int) 0 );
+}
+
+void BitVector_Word_Insert(unsigned int *  addr, unsigned int offset, unsigned int count,
+                           boolean clear)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int *  last = addr+size-1;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        if (offset > size) offset = size;
+        BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear);
+        *last &= mask;
+    }
+}
+
+void BitVector_Word_Delete(unsigned int *  addr, unsigned int offset, unsigned int count,
+                           boolean clear)
+{
+    unsigned int  size = size_(addr);
+    unsigned int  mask = mask_(addr);
+    unsigned int *  last = addr+size-1;
+
+    if (size > 0)
+    {
+        *last &= mask;
+        if (offset > size) offset = size;
+        BIT_VECTOR_del_words(addr+offset,size-offset,count,clear);
+        *last &= mask;
+    }
+}
+
+void BitVector_Chunk_Store(unsigned int *  addr, unsigned int chunksize, unsigned int offset,
+                           unsigned long value)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int mask;
+    unsigned int temp;
+
+    if ((chunksize > 0) && (offset < bits))
+    {
+        if (chunksize > LONGBITS) chunksize = LONGBITS;
+        if ((offset + chunksize) > bits) chunksize = bits - offset;
+        addr += offset >> LOGBITS;
+        offset &= MODMASK;
+        while (chunksize > 0)
+        {
+            mask = (unsigned int) (~0L << offset);
+            bits = offset + chunksize;
+            if (bits < BITS)
+            {
+                mask &= (unsigned int) ~(~0L << bits);
+                bits = chunksize;
+            }
+            else bits = BITS - offset;
+            temp = (unsigned int) (value << offset);
+            temp &= mask;
+            *addr &= ~ mask;
+            *addr++ |= temp;
+            value >>= bits;
+            chunksize -= bits;
+            offset = 0;
+        }
+    }
+}
+
+unsigned long BitVector_Chunk_Read(unsigned int *  addr, unsigned int chunksize, unsigned int offset)
+{
+    unsigned int bits = bits_(addr);
+    unsigned int chunkbits = 0;
+    unsigned long value = 0L;
+    unsigned long temp;
+    unsigned int mask;
+
+    if ((chunksize > 0) && (offset < bits))
+    {
+        if (chunksize > LONGBITS) chunksize = LONGBITS;
+        if ((offset + chunksize) > bits) chunksize = bits - offset;
+        addr += offset >> LOGBITS;
+        offset &= MODMASK;
+        while (chunksize > 0)
+        {
+            bits = offset + chunksize;
+            if (bits < BITS)
+            {
+                mask = (unsigned int) ~(~0L << bits);
+                bits = chunksize;
+            }
+            else
+            {
+                mask = (unsigned int) ~0L;
+                bits = BITS - offset;
+            }
+            temp = (unsigned long) ((*addr++ & mask) >> offset);
+            value |= temp << chunkbits;
+            chunkbits += bits;
+            chunksize -= bits;
+            offset = 0;
+        }
+    }
+    return(value);
+}
+
+    /*******************/
+    /* set operations: */
+    /*******************/
+
+void Set_Union(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)             /* X = Y + Z     */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ | *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_Intersection(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)      /* X = Y * Z     */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ & *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_Difference(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)        /* X = Y \ Z     */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ & ~ *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_ExclusiveOr(unsigned int *  X, unsigned int *  Y, unsigned int *  Z)       /* X=(Y+Z)\(Y*Z) */
+{
+    unsigned int bits = bits_(X);
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits == bits_(Y)) && (bits == bits_(Z)))
+    {
+        while (size-- > 0) *X++ = *Y++ ^ *Z++;
+        *(--X) &= mask;
+    }
+}
+
+void Set_Complement(unsigned int *  X, unsigned int *  Y)                   /* X = ~Y        */
+{
+    unsigned int size = size_(X);
+    unsigned int mask = mask_(X);
+
+    if ((size > 0) && (bits_(X) == bits_(Y)))
+    {
+        while (size-- > 0) *X++ = ~ *Y++;
+        *(--X) &= mask;
+    }
+}
+
+    /******************/
+    /* set functions: */
+    /******************/
+
+boolean Set_subset(unsigned int *  X, unsigned int *  Y)                    /* X subset Y ?  */
+{
+    unsigned int size = size_(X);
+    boolean r = false;
+
+    if ((size > 0) && (bits_(X) == bits_(Y)))
+    {
+        r = true;
+        while (r && (size-- > 0)) r = ((*X++ & ~ *Y++) == 0);
+    }
+    return(r);
+}
+
+unsigned int Set_Norm(unsigned int *  addr)                                /* = | X |       */
+{
+    unsigned char * byte;
+    unsigned int  bytes;
+    unsigned int   n;
+
+    byte = (unsigned char *) addr;
+    bytes = size_(addr) << FACTOR;
+    n = 0;
+    while (bytes-- > 0)
+    {
+        n += BitVector_BYTENORM[*byte++];
+    }
+    return(n);
+}
+
+unsigned int Set_Norm2(unsigned int *  addr)                               /* = | X |       */
+{
+    unsigned int  size = size_(addr);
+    unsigned int  w0,w1;
+    unsigned int   n,k;
+
+    n = 0;
+    while (size-- > 0)
+    {
+        k = 0;
+        w1 = ~ (w0 = *addr++);
+        while (w0 && w1)
+        {
+            w0 &= w0 - 1;
+            w1 &= w1 - 1;
+            k++;
+        }
+        if (w0 == 0) n += k;
+        else         n += BITS - k;
+    }
+    return(n);
+}
+
+unsigned int Set_Norm3(unsigned int *  addr)                               /* = | X |       */
+{
+    unsigned int  size  = size_(addr);
+    unsigned int   count = 0;
+    unsigned int  c;
+
+    while (size-- > 0)
+    {
+        c = *addr++;
+        while (c)
+        {
+            c &= c - 1;
+            count++;
+        }
+    }
+    return(count);
+}
+
+signed long Set_Min(unsigned int *  addr)                                /* = min(X)      */
+{
+    boolean empty = true;
+    unsigned int  size  = size_(addr);
+    unsigned int  i     = 0;
+    unsigned int  c     = 0;         /* silence compiler warning */
+
+    while (empty && (size-- > 0))
+    {
+        if ((c = *addr++)) empty = false; else i++;
+    }
+    if (empty) return((signed long) LONG_MAX);                  /* plus infinity  */
+    i <<= LOGBITS;
+    while (! (c & LSB))
+    {
+        c >>= 1;
+        i++;
+    }
+    return((signed long) i);
+}
+
+signed long Set_Max(unsigned int *  addr)                                /* = max(X)      */
+{
+    boolean empty = true;
+    unsigned int  size  = size_(addr);
+    unsigned int  i     = size;
+    unsigned int  c     = 0;         /* silence compiler warning */
+
+    addr += size-1;
+    while (empty && (size-- > 0))
+    {
+        if ((c = *addr--)) empty = false; else i--;
+    }
+    if (empty) return((signed long) LONG_MIN);                  /* minus infinity */
+    i <<= LOGBITS;
+    while (! (c & MSB))
+    {
+        c <<= 1;
+        i--;
+    }
+    return((signed long) --i);
+}
+
+    /**********************************/
+    /* matrix-of-booleans operations: */
+    /**********************************/
+
+void Matrix_Multiplication(unsigned int *  X, unsigned int rowsX, unsigned int colsX,
+                           unsigned int *  Y, unsigned int rowsY, unsigned int colsY,
+                           unsigned int *  Z, unsigned int rowsZ, unsigned int colsZ)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int k;
+    unsigned int indxX;
+    unsigned int indxY;
+    unsigned int indxZ;
+    unsigned int termX;
+    unsigned int termY;
+    unsigned int sum;
+
+  if ((colsY == rowsZ) && (rowsX == rowsY) && (colsX == colsZ) &&
+      (bits_(X) == rowsX*colsX) &&
+      (bits_(Y) == rowsY*colsY) &&
+      (bits_(Z) == rowsZ*colsZ))
+  {
+    for ( i = 0; i < rowsY; i++ )
+    {
+        termX = i * colsX;
+        termY = i * colsY;
+        for ( j = 0; j < colsZ; j++ )
+        {
+            indxX = termX + j;
+            sum = 0;
+            for ( k = 0; k < colsY; k++ )
+            {
+                indxY = termY + k;
+                indxZ = k * colsZ + j;
+                if ( BIT_VECTOR_TST_BIT(Y,indxY) &
+                     BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1;
+            }
+            if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+            else     BIT_VECTOR_CLR_BIT(X,indxX)
+        }
+    }
+  }
+}
+
+void Matrix_Product(unsigned int *  X, unsigned int rowsX, unsigned int colsX,
+                    unsigned int *  Y, unsigned int rowsY, unsigned int colsY,
+                    unsigned int *  Z, unsigned int rowsZ, unsigned int colsZ)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int k;
+    unsigned int indxX;
+    unsigned int indxY;
+    unsigned int indxZ;
+    unsigned int termX;
+    unsigned int termY;
+    unsigned int sum;
+
+  if ((colsY == rowsZ) && (rowsX == rowsY) && (colsX == colsZ) &&
+      (bits_(X) == rowsX*colsX) &&
+      (bits_(Y) == rowsY*colsY) &&
+      (bits_(Z) == rowsZ*colsZ))
+  {
+    for ( i = 0; i < rowsY; i++ )
+    {
+        termX = i * colsX;
+        termY = i * colsY;
+        for ( j = 0; j < colsZ; j++ )
+        {
+            indxX = termX + j;
+            sum = 0;
+            for ( k = 0; k < colsY; k++ )
+            {
+                indxY = termY + k;
+                indxZ = k * colsZ + j;
+                if ( BIT_VECTOR_TST_BIT(Y,indxY) &
+                     BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1;
+            }
+            if (sum) BIT_VECTOR_SET_BIT(X,indxX)
+            else     BIT_VECTOR_CLR_BIT(X,indxX)
+        }
+    }
+  }
+}
+
+void Matrix_Closure(unsigned int *  addr, unsigned int rows, unsigned int cols)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int k;
+    unsigned int ii;
+    unsigned int ij;
+    unsigned int ik;
+    unsigned int kj;
+    unsigned int termi;
+    unsigned int termk;
+
+  if ((rows == cols) && (bits_(addr) == rows*cols))
+  {
+    for ( i = 0; i < rows; i++ )
+    {
+        ii = i * cols + i;
+        BIT_VECTOR_SET_BIT(addr,ii)
+    }
+    for ( k = 0; k < rows; k++ )
+    {
+        termk = k * cols;
+        for ( i = 0; i < rows; i++ )
+        {
+            termi = i * cols;
+            ik = termi + k;
+            for ( j = 0; j < rows; j++ )
+            {
+                ij = termi + j;
+                kj = termk + j;
+                if ( BIT_VECTOR_TST_BIT(addr,ik) &
+                     BIT_VECTOR_TST_BIT(addr,kj) )
+                     BIT_VECTOR_SET_BIT(addr,ij)
+            }
+        }
+    }
+  }
+}
+
+void Matrix_Transpose(unsigned int *  X, unsigned int rowsX, unsigned int colsX,
+                      unsigned int *  Y, unsigned int rowsY, unsigned int colsY)
+{
+    unsigned int  i;
+    unsigned int  j;
+    unsigned int  ii;
+    unsigned int  ij;
+    unsigned int  ji;
+    unsigned int  addii;
+    unsigned int  addij;
+    unsigned int  addji;
+    unsigned int  bitii;
+    unsigned int  bitij;
+    unsigned int  bitji;
+    unsigned int  termi;
+    unsigned int  termj;
+    boolean swap;
+
+  /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */
+
+  if ((rowsX == colsY) && (colsX == rowsY) &&
+      (bits_(X) == rowsX*colsX) &&
+      (bits_(Y) == rowsY*colsY))
+  {
+    if (rowsY == colsY) /* in-place is possible! */
+    {
+        for ( i = 0; i < rowsY; i++ )
+        {
+            termi = i * colsY;
+            for ( j = 0; j < i; j++ )
+            {
+                termj = j * colsX;
+                ij = termi + j;
+                ji = termj + i;
+                addij = ij >> LOGBITS;
+                addji = ji >> LOGBITS;
+                bitij = BITMASKTAB[ij & MODMASK];
+                bitji = BITMASKTAB[ji & MODMASK];
+                swap = ((*(Y+addij) & bitij) != 0);
+                if ((*(Y+addji) & bitji) != 0)
+                     *(X+addij) |=     bitij;
+                else
+                     *(X+addij) &= ~ bitij;
+                if (swap)
+                     *(X+addji) |=     bitji;
+                else
+                     *(X+addji) &= ~ bitji;
+            }
+            ii = termi + i;
+            addii = ii >> LOGBITS;
+            bitii = BITMASKTAB[ii & MODMASK];
+            if ((*(Y+addii) & bitii) != 0)
+                 *(X+addii) |=     bitii;
+            else
+                 *(X+addii) &= ~ bitii;
+        }
+    }
+    else /* rowsX != colsX, in-place is ~ possible! */
+    {
+        for ( i = 0; i < rowsY; i++ )
+        {
+            termi = i * colsY;
+            for ( j = 0; j < colsY; j++ )
+            {
+                termj = j * colsX;
+                ij = termi + j;
+                ji = termj + i;
+                addij = ij >> LOGBITS;
+                addji = ji >> LOGBITS;
+                bitij = BITMASKTAB[ij & MODMASK];
+                bitji = BITMASKTAB[ji & MODMASK];
+                if ((*(Y+addij) & bitij) != 0)
+                     *(X+addji) |=     bitji;
+                else
+                     *(X+addji) &= ~ bitji;
+            }
+        }
+    }
+  }
+}
+}; //end of namespace CONSTANTBV
diff --git a/stp/constantbv/constantbv.h b/stp/constantbv/constantbv.h
new file mode 100644
index 00000000..47e0c56f
--- /dev/null
+++ b/stp/constantbv/constantbv.h
@@ -0,0 +1,316 @@
+#ifndef MODULE_BIT_VECTOR
+#define MODULE_BIT_VECTOR
+/*****************************************************************************/
+/*  AUTHOR:                                                                  */
+/*****************************************************************************/
+/*                                                                           */
+/*    Steffen Beyer                                                          */
+/*    mailto:sb@engelschall.com                                              */
+/*    http://www.engelschall.com/u/sb/download/                              */
+/*                                                                           */
+/*****************************************************************************/
+/*  COPYRIGHT:                                                               */
+/*****************************************************************************/
+/*                                                                           */
+/*    Copyright (c) 1995 - 2004 by Steffen Beyer.                            */
+/*    All rights reserved.                                                   */
+/*                                                                           */
+/*****************************************************************************/
+/*  LICENSE:                                                                 */
+/*****************************************************************************/
+/*                                                                           */
+/*    This library is free software; you can redistribute it and/or          */
+/*    modify it under the terms of the GNU Library General Public            */
+/*    License as published by the Free Software Foundation; either           */
+/*    version 2 of the License, or (at your option) any later version.       */
+/*                                                                           */
+/*    This library is distributed in the hope that it will be useful,        */
+/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU       */
+/*    Library General Public License for more details.                       */
+/*                                                                           */
+/*    You should have received a copy of the GNU Library General Public      */
+/*    License along with this library; if not, write to the                  */
+/*    Free Software Foundation, Inc.,                                        */
+/*    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                  */
+/*                                                                           */
+/*    or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0      */
+/*                                                                           */
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+/*  MODULE NAME:  BitVector.h                           MODULE TYPE:  (adt)  */
+/*****************************************************************************/
+/*  MODULE IMPORTS:                                                          */
+/*****************************************************************************/
+#include <stdlib.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <limits.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <string.h>                                 /*  MODULE TYPE:  (sys)  */
+#include <ctype.h>                                  /*  MODULE TYPE:  (sys)  */
+/*****************************************************************************/
+/*  MODULE INTERFACE:                                                        */
+/*****************************************************************************/
+
+namespace CONSTANTBV {
+
+#ifdef __cplusplus
+  extern "C" {
+    typedef bool boolean;
+#else
+    typedef enum { false = (0!=0), true = (0==0) } boolean;
+#endif
+
+    typedef enum {
+        ErrCode_Ok = 0,    /* everything went allright                       */	
+        ErrCode_Type,      /* types word and size_t have incompatible sizes  */
+        ErrCode_Bits,      /* bits of word and sizeof(word) are inconsistent */
+        ErrCode_Word,      /* size of word is less than 16 bits              */
+        ErrCode_Long,      /* size of word is greater than size of long      */
+        ErrCode_Powr,      /* number of bits of word is not a power of two   */
+        ErrCode_Loga,      /* error in calculation of logarithm              */	
+        ErrCode_Null,      /* unable to allocate memory                      */	
+        ErrCode_Indx,      /* index out of range                             */
+        ErrCode_Ordr,      /* minimum > maximum index                        */
+        ErrCode_Size,      /* bit vector size mismatch                       */
+        ErrCode_Pars,      /* input string syntax error                      */
+        ErrCode_Ovfl,      /* numeric overflow error                         */
+        ErrCode_Same,      /* operands must be distinct                      */
+        ErrCode_Expo,      /* exponent must be positive                      */
+        ErrCode_Zero       /* division by zero error                         */
+      } ErrCode;
+
+
+    /* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */
+    unsigned char * BitVector_Error(ErrCode error);     /* return string for err code */
+    ErrCode         BitVector_Boot (void);              /* 0 = ok, 1..7 = error */
+    unsigned int    BitVector_Size(unsigned int bits);  /* bit vector size (# of words)  */
+    unsigned int    BitVector_Mask(unsigned int bits);  /* bit vector mask (unused bits) */
+    
+    /* ===> CLASS METHODS: <=== */
+    unsigned char * BitVector_Version(void);           /* return version string */
+    unsigned int    BitVector_Word_Bits(void);         /* return # of bits in machine word */
+    unsigned int    BitVector_Long_Bits(void);         /* return # of bits in unsigned long */
+
+    /* ===> CONSTRUCTOR METHODS: <=== */
+    unsigned int *  BitVector_Create      (unsigned int bits, boolean clear);                /* malloc */
+    unsigned int ** BitVector_Create_List (unsigned int bits, boolean clear, unsigned int count);
+    unsigned int *  BitVector_Resize      (unsigned int * oldaddr, unsigned int bits);       /* realloc */
+    unsigned int *  BitVector_Shadow      (unsigned int * addr);                             /* make new same size but empty */
+    unsigned int *  BitVector_Clone       (unsigned int * addr);                             /* make exact duplicate */
+    unsigned int *  BitVector_Concat      (unsigned int * X, unsigned int * Y);              /* return concatenation */
+
+    /* ===> DESTRUCTOR METHODS: <=== */
+    void    BitVector_Dispose             (unsigned char * string);                     /* string */
+    void    BitVector_Destroy             (unsigned int * addr);                        /* bitvec */
+    void    BitVector_Destroy_List        (unsigned int * * list, unsigned int count);  /* list   */
+
+    /* ===> OBJECT METHODS: <=== */
+
+    /* ===> bit vector hash: */
+    size_t  BitVector_Hash                (unsigned int * X);
+
+    /* ===> bit vector copy function: */
+    void    BitVector_Copy                (unsigned int * X, unsigned int * Y);              /* X := Y   */
+
+    /* ===> bit vector initialization: */
+    void    BitVector_Empty               (unsigned int * addr);                      /* X = {}  */
+    void    BitVector_Fill                (unsigned int * addr);                      /* X = ~{} */
+    void    BitVector_Flip                (unsigned int * addr);                      /* X = ~X  */
+    void    BitVector_Primes              (unsigned int * addr);
+
+    /* ===> miscellaneous functions: */
+    void    BitVector_Reverse             (unsigned int * X, unsigned int * Y);
+    
+    /* ===> bit vector interval operations and functions: */
+    void    BitVector_Interval_Empty      (unsigned int * addr, unsigned int lower, unsigned int upper);
+    void    BitVector_Interval_Fill       (unsigned int * addr, unsigned int lower, unsigned int upper);
+    void    BitVector_Interval_Flip       (unsigned int * addr, unsigned int lower, unsigned int upper);
+    void    BitVector_Interval_Reverse    (unsigned int * addr, unsigned int lower, unsigned int upper);
+    
+    boolean BitVector_interval_scan_inc   (unsigned int * addr, unsigned int start,
+					   unsigned int * min, unsigned int * max);
+    boolean BitVector_interval_scan_dec   (unsigned int * addr, unsigned int start,
+					   unsigned int * min, unsigned int * max);
+    void    BitVector_Interval_Copy       (unsigned int * X, unsigned int * Y, 
+					   unsigned int Xoffset, unsigned int Yoffset, unsigned int length);
+    unsigned int * BitVector_Interval_Substitute(unsigned int * X, unsigned int * Y,
+						 unsigned int Xoffset, unsigned int Xlength,
+						 unsigned int Yoffset, unsigned int Ylength);
+
+    /* ===> bit vector test functions: */
+    boolean BitVector_is_empty            (unsigned int * addr);                         /* X == {} ?   */
+    boolean BitVector_is_full             (unsigned int * addr);                         /* X == ~{} ?  */
+    boolean BitVector_equal               (unsigned int * X, unsigned int * Y);          /* X == Y ?    */
+    signed int   BitVector_Lexicompare    (unsigned int * X, unsigned int * Y);          /* X <,=,> Y ? */
+    signed int   BitVector_Compare        (unsigned int * X, unsigned int * Y);          /* X <,=,> Y ? */
+    
+    /* ===> bit vector string conversion functions: */
+    unsigned char * BitVector_to_Hex      (unsigned int * addr);
+    ErrCode BitVector_from_Hex            (unsigned int * addr, unsigned char * string);
+    unsigned char * BitVector_to_Bin      (unsigned int * addr);
+    ErrCode BitVector_from_Bin            (unsigned int * addr, unsigned char * string);
+    unsigned char * BitVector_to_Dec      (unsigned int * addr);
+    ErrCode BitVector_from_Dec            (unsigned int * addr, unsigned char * string);
+    unsigned char * BitVector_to_Enum     (unsigned int * addr);
+    ErrCode BitVector_from_Enum           (unsigned int * addr, unsigned char * string);
+    
+    /* ===> bit vector bit operations, functions & tests: */
+    void    BitVector_Bit_Off             (unsigned int * addr, unsigned int index); /*  X = X \ {x}    */
+    void    BitVector_Bit_On              (unsigned int * addr, unsigned int index); /*  X = X + {x}    */
+    boolean BitVector_bit_flip            (unsigned int * addr, unsigned int index); /* (X+{x})\(X*{x}) */
+    boolean BitVector_bit_test            (unsigned int * addr, unsigned int index); /*  {x} in X ?     */
+    void    BitVector_Bit_Copy            (unsigned int * addr, unsigned int index, boolean bit);
+    
+    /* ===> bit vector bit shift & rotate functions: */
+    void    BitVector_LSB                 (unsigned int * addr, boolean bit);
+    void    BitVector_MSB                 (unsigned int * addr, boolean bit);
+    boolean BitVector_lsb_                (unsigned int * addr);
+    boolean BitVector_msb_                (unsigned int * addr);
+    boolean BitVector_rotate_left         (unsigned int * addr);
+    boolean BitVector_rotate_right        (unsigned int * addr);
+    boolean BitVector_shift_left          (unsigned int * addr, boolean carry_in);
+    boolean BitVector_shift_right         (unsigned int * addr, boolean carry_in);
+    void    BitVector_Move_Left           (unsigned int * addr, unsigned int bits);
+    void    BitVector_Move_Right          (unsigned int * addr, unsigned int bits);
+    
+    /* ===> bit vector insert/delete bits: */
+    void    BitVector_Insert              (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    void    BitVector_Delete              (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    
+    /* ===> bit vector arithmetic: */
+    boolean BitVector_increment           (unsigned int * addr);                        /*  X++  */
+    boolean BitVector_decrement           (unsigned int * addr);                        /*  X--  */
+    boolean BitVector_compute             (unsigned int * X, unsigned int * Y, 
+					   unsigned int * Z, boolean minus, boolean *carry);
+    boolean BitVector_add                 (unsigned int * X, 
+					   unsigned int * Y, unsigned int * Z, boolean *carry);
+    boolean BitVector_sub                 (unsigned int * X, 
+					   unsigned int * Y, unsigned int * Z, boolean *carry); /* X = Y-Z*/
+    boolean BitVector_inc                 (unsigned int * X, unsigned int * Y);
+    boolean BitVector_dec                 (unsigned int * X, unsigned int * Y);
+    
+    void    BitVector_Negate              (unsigned int * X, unsigned int * Y);
+    void    BitVector_Absolute            (unsigned int * X, unsigned int * Y);
+    signed int   BitVector_Sign           (unsigned int * addr);
+    ErrCode BitVector_Mul_Pos             (unsigned int * X, 
+					   unsigned int * Y, unsigned int * Z, boolean strict);
+    ErrCode BitVector_Multiply            (unsigned int * X, unsigned int * Y, unsigned int * Z);
+    ErrCode BitVector_Div_Pos             (unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R);
+    ErrCode BitVector_Divide              (unsigned int * Q, unsigned int * X, unsigned int * Y, unsigned int * R);
+    ErrCode BitVector_GCD                 (unsigned int * X, unsigned int * Y, unsigned int * Z);
+    ErrCode BitVector_GCD2                (unsigned int * U, unsigned int * V, unsigned int * W,      /*   O   */
+					   unsigned int * X, unsigned int * Y);     /*   I   */
+    ErrCode BitVector_Power               (unsigned int * X, unsigned int * Y, unsigned int * Z);
+    
+    /* ===> direct memory access functions: */
+    void    BitVector_Block_Store         (unsigned int * addr, 
+					   unsigned char * buffer, unsigned int length);
+    unsigned char * BitVector_Block_Read  (unsigned int * addr, unsigned int * length);
+    
+    /* ===> word array functions: */
+    void    BitVector_Word_Store          (unsigned int * addr, unsigned int offset, unsigned int value);
+    unsigned int   BitVector_Word_Read    (unsigned int * addr, unsigned int offset);
+    void    BitVector_Word_Insert         (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    void    BitVector_Word_Delete         (unsigned int * addr, 
+					   unsigned int offset, unsigned int count, boolean clear);
+    
+    /* ===> arbitrary size chunk functions: */
+    void    BitVector_Chunk_Store         (unsigned int * addr, unsigned int chunksize,
+					   unsigned int offset, unsigned long value);
+    unsigned long  BitVector_Chunk_Read   (unsigned int * addr, 
+					   unsigned int chunksize,unsigned int offset);
+    
+    /* ===> set operations: */
+    void    Set_Union                     (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y + Z */
+    void    Set_Intersection              (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y * Z */
+    void    Set_Difference                (unsigned int * X, unsigned int * Y, unsigned int * Z); /* X = Y \ Z */
+    void    Set_ExclusiveOr               (unsigned int * X, unsigned int * Y, unsigned int * Z); /*(Y+Z)\(Y*Z)*/
+    void    Set_Complement                (unsigned int * X, unsigned int * Y);                   /* X = ~Y    */
+    
+    /* ===> set functions: */
+    boolean        Set_subset             (unsigned int * X, unsigned int * Y);     /* X in Y ?  */
+    unsigned int   Set_Norm               (unsigned int * addr);                    /* = | X |   */
+    unsigned int   Set_Norm2              (unsigned int * addr);                    /* = | X |   */
+    unsigned int   Set_Norm3              (unsigned int * addr);                    /* = | X |   */
+    signed long    Set_Min                (unsigned int * addr);                    /* = min(X)  */
+    signed long    Set_Max                (unsigned int * addr);                    /* = max(X)  */
+    
+    /* ===> matrix-of-booleans operations: */
+    void    Matrix_Multiplication         (unsigned int * X, unsigned int rowsX, unsigned int colsX,
+					   unsigned int * Y, unsigned int rowsY, unsigned int colsY,
+					   unsigned int * Z, unsigned int rowsZ, unsigned int colsZ);
+    void    Matrix_Product                (unsigned int * X, unsigned int rowsX, unsigned int colsX,
+					   unsigned int * Y, unsigned int rowsY, unsigned int colsY,
+					   unsigned int * Z, unsigned int rowsZ, unsigned int colsZ);
+    void    Matrix_Closure                (unsigned int * addr, unsigned int rows, unsigned int cols);
+    void    Matrix_Transpose              (unsigned int * X, unsigned int rowsX, unsigned int colsX,
+					   unsigned int * Y, unsigned int rowsY, unsigned int colsY);
+    
+    /*****************************************************************************/
+    /*  MODULE RESOURCES:                                                        */
+    /*****************************************************************************/
+#define bits_(BitVector) *(BitVector-3)
+#define size_(BitVector) *(BitVector-2)
+#define mask_(BitVector) *(BitVector-1)
+    
+#define  ERRCODE_TYPE  "sizeof(word) > sizeof(size_t)"
+#define  ERRCODE_BITS  "bits(word) != sizeof(word)*8"
+#define  ERRCODE_WORD  "bits(word) < 16"
+#define  ERRCODE_LONG  "bits(word) > bits(long)"
+#define  ERRCODE_POWR  "bits(word) != 2^x"
+#define  ERRCODE_LOGA  "bits(word) != 2^ld(bits(word))"
+#define  ERRCODE_NULL  "unable to allocate memory"
+#define  ERRCODE_INDX  "index out of range"
+#define  ERRCODE_ORDR  "minimum > maximum index"
+#define  ERRCODE_SIZE  "bit vector size mismatch"
+#define  ERRCODE_PARS  "input string syntax error"
+#define  ERRCODE_OVFL  "numeric overflow error"
+#define  ERRCODE_SAME  "result vector(s) must be distinct"
+#define  ERRCODE_EXPO  "exponent must be positive"
+#define  ERRCODE_ZERO  "division by zero error"
+#define  ERRCODE_OOPS  "unexpected internal error - please contact author"
+        
+    const unsigned int BitVector_BYTENORM[256] = {
+      0x00, 0x01, 0x01, 0x02,  0x01, 0x02, 0x02, 0x03,
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04, /* 0x00 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x10 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x20 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x30 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x40 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x50 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x60 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0x70 */
+      0x01, 0x02, 0x02, 0x03,  0x02, 0x03, 0x03, 0x04,
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05, /* 0x80 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0x90 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xA0 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xB0 */
+      0x02, 0x03, 0x03, 0x04,  0x03, 0x04, 0x04, 0x05,
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06, /* 0xC0 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xD0 */
+      0x03, 0x04, 0x04, 0x05,  0x04, 0x05, 0x05, 0x06,
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07, /* 0xE0 */
+      0x04, 0x05, 0x05, 0x06,  0x05, 0x06, 0x06, 0x07,
+      0x05, 0x06, 0x06, 0x07,  0x06, 0x07, 0x07, 0x08  /* 0xF0 */
+    };
+#ifdef __cplusplus
+  };
+#endif
+}; //end of namespace CONSTANTBV
+#endif
+
diff --git a/stp/parser/Makefile b/stp/parser/Makefile
new file mode 100644
index 00000000..8211c825
--- /dev/null
+++ b/stp/parser/Makefile
@@ -0,0 +1,27 @@
+include ../Makefile.common
+
+SRCS = lexPL.cpp parsePL.cpp let-funcs.cpp main.cpp
+OBJS = $(SRCS:.cpp=.o)
+LIBS = -L../AST -last -L../sat -lsatsolver -L../simplifier -lsimplifier -L../bitvec -lconsteval -L../constantbv -lconstantbv
+
+all: parser 
+
+parser: lexPL.o parsePL.o let-funcs.o main.o 
+		$(CXX) $(CFLAGS) $(LDFLAGS) lexPL.o parsePL.o main.o let-funcs.o $(LIBS) -o parser
+
+main.o: parsePL_defs.h
+
+lexPL.cpp:	PL.lex parsePL_defs.h ../AST/AST.h
+		$(LEX) -o lexPL.cpp PL.lex
+
+parsePL_defs.h: y.tab.h
+		@cp y.tab.h parsePL_defs.h
+parsePL.cpp: y.tab.c
+		@cp y.tab.c parsePL.cpp
+
+y.tab.c y.tab.h:	PL.y
+		$(YACC) PL.y
+
+
+clean:	
+		rm -rf *.o parsePL_defs.h *~ lexPL.cpp parsePL.cpp *.output parser y.tab.* lex.yy.c .#*
diff --git a/stp/parser/PL.lex b/stp/parser/PL.lex
new file mode 100644
index 00000000..e9358a0e
--- /dev/null
+++ b/stp/parser/PL.lex
@@ -0,0 +1,128 @@
+%{
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+#include <iostream>
+#include "../AST/AST.h"
+#include "parsePL_defs.h"
+
+extern char *yytext;
+extern int yyerror (const char *msg);
+%}
+
+%option noyywrap
+%option nounput
+%option noreject
+%option noyymore
+%option yylineno
+%x	COMMENT
+%x	STRING_LITERAL
+LETTER	([a-zA-Z])
+HEX     ([0-9a-fA-F])
+BITS    ([0-1])
+DIGIT	([0-9])
+OPCHAR	(['?\_$])
+ANYTHING ({LETTER}|{DIGIT}|{OPCHAR})
+%%
+
+[()[\]{},.;:'!#?_=]  { return yytext[0];}
+
+[\n]             { /*Skip new line */ }
+[ \t\r\f]	 { /* skip whitespace */ }
+0b{BITS}+	 { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+2,  2)); return BVCONST_TOK;}
+0bin{BITS}+	 { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+4,  2)); return BVCONST_TOK;}
+0h{HEX}+         { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+2, 16)); return BVCONST_TOK;}
+0hex{HEX}+       { yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(yytext+4, 16)); return BVCONST_TOK;}
+{DIGIT}+	 { yylval.uintval = strtoul(yytext, NULL, 10); return NUMERAL_TOK;}
+
+"%"		 { BEGIN COMMENT;}
+<COMMENT>"\n"	 { BEGIN INITIAL; /* return to normal mode */}
+<COMMENT>.	 { /* stay in comment mode */}
+
+"ARRAY"		 { return ARRAY_TOK; }
+"OF"		 { return OF_TOK; }
+"WITH"		 { return WITH_TOK; }
+"AND"		 { return AND_TOK;}
+"NAND"		 { return NAND_TOK;}
+"NOR"		 { return NOR_TOK;}
+"NOT"		 { return NOT_TOK; }
+"OR"		 { return OR_TOK; }
+"/="		 { return NEQ_TOK; }
+ ":="            { return ASSIGN_TOK;}
+"=>"		 { return IMPLIES_TOK; }
+"<=>"		 { return IFF_TOK; }
+"XOR"		 { return XOR_TOK; }
+"IF"		 { return IF_TOK; }
+"THEN"		 { return THEN_TOK; }
+"ELSE"		 { return ELSE_TOK; }
+"ELSIF"		 { return ELSIF_TOK; }
+"END"		 { return END_TOK; }
+"ENDIF"		 { return ENDIF_TOK; }
+"BV"             { return BV_TOK;}
+"BITVECTOR"      { return BV_TOK;}
+"BOOLEAN"        { return BOOLEAN_TOK;}
+"<<"             { return BVLEFTSHIFT_TOK;}
+">>"             { return BVRIGHTSHIFT_TOK;}
+"BVPLUS"         { return BVPLUS_TOK;}
+"BVSUB"          { return BVSUB_TOK;}
+"BVUMINUS"       { return BVUMINUS_TOK;}
+"BVMULT"         { return BVMULT_TOK;}
+"BVDIV"          { return BVDIV_TOK;}
+"BVMOD"          { return BVMOD_TOK;}
+"SBVDIV"         { return SBVDIV_TOK;}
+"SBVMOD"         { return SBVMOD_TOK;}
+"~"              { return BVNEG_TOK;}
+"&"              { return BVAND_TOK;}
+"|"              { return BVOR_TOK;}
+"BVXOR"          { return BVXOR_TOK;}
+"BVNAND"         { return BVNAND_TOK;}
+"BVNOR"          { return BVNOR_TOK;}
+"BVXNOR"         { return BVXNOR_TOK;}
+"@"              { return BVCONCAT_TOK;}
+"BVLT"           { return BVLT_TOK;}
+"BVGT"           { return BVGT_TOK;}
+"BVLE"           { return BVLE_TOK;}
+"BVGE"           { return BVGE_TOK;}
+"BVSLT"          { return BVSLT_TOK;}
+"BVSGT"          { return BVSGT_TOK;}
+"BVSLE"          { return BVSLE_TOK;}
+"BVSGE"          { return BVSGE_TOK;}
+"BVSX"           { return BVSX_TOK;} 
+"SBVLT"          { return BVSLT_TOK;}
+"SBVGT"          { return BVSGT_TOK;}
+"SBVLE"          { return BVSLE_TOK;}
+"SBVGE"          { return BVSGE_TOK;}
+"SX"             { return BVSX_TOK;} 
+"BOOLEXTRACT"    { return BOOLEXTRACT_TOK;}
+"BOOLBV"         { return BOOL_TO_BV_TOK;}
+"ASSERT"	 { return ASSERT_TOK; }
+"QUERY"	         { return QUERY_TOK; }
+"FALSE"          { return FALSELIT_TOK;}
+"TRUE"           { return TRUELIT_TOK;}
+"IN"             { return IN_TOK;}
+"LET"            { return LET_TOK;}
+"COUNTEREXAMPLE" { return COUNTEREXAMPLE_TOK;}
+"COUNTERMODEL"   { return COUNTEREXAMPLE_TOK;}
+ "PUSH"          { return PUSH_TOK;}
+ "POP"           { return POP_TOK;}
+
+(({LETTER})|(_)({ANYTHING}))({ANYTHING})*	{
+  BEEV::ASTNode nptr = BEEV::globalBeevMgr_for_parser->CreateSymbol(yytext); 
+
+  // Check valuesize to see if it's a prop var.  I don't like doing
+  // type determination in the lexer, but it's easier than rewriting
+  // the whole grammar to eliminate the term/formula distinction.  
+  yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(nptr));
+  //yylval.node = new BEEV::ASTNode(nptr);
+  if ((yylval.node)->GetType() == BEEV::BOOLEAN_TYPE)
+    return FORMID_TOK;
+  else 
+    return TERMID_TOK;  
+}
+
+.                { yyerror("Illegal input character."); }
+%%
diff --git a/stp/parser/PL.y b/stp/parser/PL.y
new file mode 100644
index 00000000..aa58aa4c
--- /dev/null
+++ b/stp/parser/PL.y
@@ -0,0 +1,1006 @@
+%{
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+using namespace std; 
+
+  // Suppress the bogus warning suppression in bison (it generates
+  // compile error)
+#undef __GNUC_MINOR__
+
+  extern int yylex(void);
+  extern char* yytext;
+  extern int yylineno;
+  int yyerror(const char *s) {
+    cout << "syntax error: line " << yylineno << "\n" << s << endl;    
+    BEEV::FatalError("");
+    return 1;			/* Dill: don't know what it should return */
+  };
+
+#define YYLTYPE_IS_TRIVIAL 1
+#define YYMAXDEPTH 10485760
+#define YYERROR_VERBOSE 1
+#define YY_EXIT_FAILURE -1
+%}
+
+%union {
+
+  unsigned int uintval;			/* for numerals in types. */
+  struct {
+    //stores the indexwidth and valuewidth
+    //indexwidth is 0 iff type is bitvector. positive iff type is
+    //array, and stores the width of the indexing bitvector
+    unsigned int indexwidth;
+    //width of the bitvector type
+    unsigned int valuewidth;
+  } indexvaluewidth;
+
+  //ASTNode,ASTVec
+  BEEV::ASTNode *node;
+  BEEV::ASTVec *vec;
+
+  //Hash_Map to hold Array Updates during parse A map from array index
+  //to array values. To support the WITH construct
+  BEEV::ASTNodeMap * Index_To_UpdateValue;
+};
+
+%start cmd
+
+%token	AND_TOK			"AND"
+%token	OR_TOK			"OR"
+%token	NOT_TOK			"NOT"
+%token	XOR_TOK			"XOR"
+%token	NAND_TOK		"NAND"
+%token	NOR_TOK			"NOR"
+%token	IMPLIES_TOK		"=>"
+%token	IFF_TOK			"<=>"
+
+%token	IF_TOK			"IF"
+%token	THEN_TOK		"THEN"
+%token	ELSE_TOK		"ELSE"
+%token	ELSIF_TOK		"ELSIF"
+%token	END_TOK			"END"
+%token	ENDIF_TOK		"ENDIF"
+%token	NEQ_TOK			"/="
+%token  ASSIGN_TOK              ":="
+
+%token  BV_TOK                  "BV"
+%token  BVLEFTSHIFT_TOK         "<<"
+%token  BVRIGHTSHIFT_TOK        ">>"
+%token  BVPLUS_TOK              "BVPLUS"
+%token  BVSUB_TOK               "BVSUB"
+%token  BVUMINUS_TOK            "BVUMINUS"
+%token  BVMULT_TOK              "BVMULT"
+
+%token  BVDIV_TOK               "BVDIV"
+%token  BVMOD_TOK               "BVMOD"
+%token  SBVDIV_TOK              "SBVDIV"
+%token  SBVMOD_TOK              "SBVMOD"
+
+
+%token  BVNEG_TOK               "~"
+%token  BVAND_TOK               "&"
+%token  BVOR_TOK                "|"
+%token  BVXOR_TOK               "BVXOR"
+%token  BVNAND_TOK              "BVNAND"
+%token  BVNOR_TOK               "BVNOR"
+%token  BVXNOR_TOK              "BVXNOR"
+%token  BVCONCAT_TOK            "@"
+
+%token  BVLT_TOK                "BVLT"
+%token  BVGT_TOK                "BVGT"
+%token  BVLE_TOK                "BVLE"
+%token  BVGE_TOK                "BVGE"
+
+%token  BVSLT_TOK               "BVSLT"
+%token  BVSGT_TOK               "BVSGT"
+%token  BVSLE_TOK               "BVSLE"
+%token  BVSGE_TOK               "BVSGE"
+%token  BOOL_TO_BV_TOK          "BOOLBV"
+%token  BVSX_TOK                "BVSX"
+%token  BOOLEXTRACT_TOK         "BOOLEXTRACT"
+%token  ASSERT_TOK              "ASSERT"
+%token  QUERY_TOK               "QUERY"
+
+%token  BOOLEAN_TOK             "BOOLEAN"
+%token  ARRAY_TOK               "ARRAY"
+%token  OF_TOK                  "OF"
+%token  WITH_TOK                "WITH"
+
+%token  TRUELIT_TOK             "TRUE"
+%token  FALSELIT_TOK            "FALSE"
+
+%token  IN_TOK                  "IN"
+%token  LET_TOK                 "LET"
+//%token  COUNTEREXAMPLE_TOK      "COUNTEREXAMPLE"
+%token  PUSH_TOK                "PUSH"
+%token  POP_TOK                 "POP"
+
+%left IN_TOK
+%left XOR_TOK
+%left IFF_TOK
+%right IMPLIES_TOK
+%left OR_TOK
+%left AND_TOK
+%left NAND_TOK
+%left NOR_TOK
+%left NOT_TOK
+%left BVCONCAT_TOK
+%left BVOR_TOK
+%left BVAND_TOK
+%left BVXOR_TOK
+%left BVNAND_TOK
+%left BVNOR_TOK
+%left BVXNOR_TOK
+%left BVNEG_TOK
+%left BVLEFTSHIFT_TOK BVRIGHTSHIFT_TOK
+%left WITH_TOK
+
+%nonassoc '=' NEQ_TOK ASSIGN_TOK
+%nonassoc BVLT_TOK BVLE_TOK BVGT_TOK BVGE_TOK
+%nonassoc BVUMINUS_TOK BVPLUS_TOK BVSUB_TOK BVSX_TOK
+%nonassoc '[' 
+%nonassoc '{' '.' '('
+%nonassoc BV_TOK
+
+%type <vec>  Exprs FORM_IDs reverseFORM_IDs
+%type <vec>  Asserts 
+%type <node> Expr Formula IfExpr ElseRestExpr IfForm ElseRestForm Assert Query ArrayUpdateExpr
+%type <Index_To_UpdateValue> Updates
+
+%type <indexvaluewidth>  BvType BoolType ArrayType Type 
+
+%token <node> BVCONST_TOK
+%token <node> TERMID_TOK FORMID_TOK COUNTEREXAMPLE_TOK
+%token <uintval> NUMERAL_TOK
+
+%%
+
+cmd             :      other_cmd
+                |      other_cmd counterexample
+                ; 
+
+counterexample  :      COUNTEREXAMPLE_TOK ';'
+                       {
+			 BEEV::print_counterexample = true;			 
+			 BEEV::globalBeevMgr_for_parser->PrintCounterExample(true);
+		       }                              
+                ;
+
+other_cmd       :      other_cmd1
+                |      Query 
+                       { 
+			 BEEV::globalBeevMgr_for_parser->TopLevelSAT(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE),*$1); 
+			 delete $1;
+		       }
+                |      VarDecls Query 
+                       { 
+			 BEEV::globalBeevMgr_for_parser->TopLevelSAT(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE),*$2); 
+			 delete $2;
+		       }
+                |      other_cmd1 Query
+                       {
+			 BEEV::ASTVec aaa = BEEV::globalBeevMgr_for_parser->GetAsserts();
+			 if(aaa.size() == 0)
+			   yyerror("Fatal Error: parsing:  GetAsserts() call: no assertions: ");
+			 if(aaa.size() == 1)
+			   BEEV::globalBeevMgr_for_parser->TopLevelSAT(aaa[0],*$2);
+			 else  		   
+			   BEEV::globalBeevMgr_for_parser->TopLevelSAT(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND,aaa),*$2);
+			 delete $2;
+		       }
+                ;
+
+other_cmd1      :     VarDecls Asserts
+                      {
+			delete $2;
+                      }                 
+                |     Asserts
+                      {
+			delete $1;
+		      }
+                |     other_cmd1 VarDecls Asserts
+                      {
+                        delete $3;
+                      }
+                ;
+
+/* push            :     PUSH_TOK */
+/*                       { */
+/* 			BEEV::globalBeevMgr_for_parser->Push(); */
+/*                       } */
+/*                 | */
+/*                 ; */
+
+/* pop             :     POP_TOK */
+/*                       { */
+/* 			BEEV::globalBeevMgr_for_parser->Pop(); */
+/*                       } */
+/*                 | */
+/*                 ; */
+
+Asserts         :      Assert 
+                       {
+			 $$ = new BEEV::ASTVec;
+			 $$->push_back(*$1);
+			 BEEV::globalBeevMgr_for_parser->AddAssert(*$1);
+			 delete $1;
+                       }
+                |      Asserts Assert
+                       {
+			 $1->push_back(*$2);
+			 BEEV::globalBeevMgr_for_parser->AddAssert(*$2);
+			 $$ = $1;
+			 delete $2;
+		       }
+                ;
+
+Assert          :      ASSERT_TOK Formula ';' { $$ = $2; }                
+                ;
+
+Query           :      QUERY_TOK Formula ';' { BEEV::globalBeevMgr_for_parser->AddQuery(*$2); $$ = $2;}
+                ; 
+
+
+/* Grammar for Variable Declaration */
+VarDecls	:      VarDecl ';'
+                       {
+                       }
+                |      VarDecls  VarDecl ';'
+                       {
+		       }
+		;
+
+VarDecl		:      FORM_IDs ':' Type 
+                       {
+			 for(BEEV::ASTVec::iterator i=$1->begin(),iend=$1->end();i!=iend;i++) {
+			   BEEV::_parser_symbol_table.insert(*i);
+			   i->SetIndexWidth($3.indexwidth);
+			   i->SetValueWidth($3.valuewidth);
+
+			   //FIXME: HACK_ATTACK. this vector was hacked into the code to
+			   //support a special request by Dawson' group. They want the
+			   //counterexample to be printed in the order of variables declared.
+			   BEEV::globalBeevMgr_for_parser->_special_print_set.push_back(*i);
+			 }
+			 delete $1;
+		       }
+                |      FORM_IDs ':' Type '=' Expr
+		       {
+			 //do type checking. if doesn't pass then abort
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+			 if($3.indexwidth != $5->GetIndexWidth())
+			   yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+			 if($3.valuewidth != $5->GetValueWidth())
+			   yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+			 
+			 for(BEEV::ASTVec::iterator i=$1->begin(),iend=$1->end();i!=iend;i++) {			   
+			   //set the valuewidth of the identifier
+			   i->SetValueWidth($5->GetValueWidth());
+			   i->SetIndexWidth($5->GetIndexWidth());
+			   
+			   BEEV::globalBeevMgr_for_parser->LetExprMgr(*i,*$5);
+			   delete $5;
+			 }
+		       }
+                |      FORM_IDs ':' Type '=' Formula
+                       {
+			 //do type checking. if doesn't pass then abort
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+			 if($3.indexwidth != $5->GetIndexWidth())
+			   yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+			 if($3.valuewidth != $5->GetValueWidth())
+			   yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+			 
+			 for(BEEV::ASTVec::iterator i=$1->begin(),iend=$1->end();i!=iend;i++) {			   
+			   //set the valuewidth of the identifier
+			   i->SetValueWidth($5->GetValueWidth());
+			   i->SetIndexWidth($5->GetIndexWidth());
+			   
+			   BEEV::globalBeevMgr_for_parser->LetExprMgr(*i,*$5);
+			   delete $5;
+			 }
+		       }                
+		;
+
+reverseFORM_IDs  :      FORMID_TOK
+                       {
+			 $$ = new BEEV::ASTVec;		        
+			 $$->push_back(*$1);
+			 delete $1;
+                       }
+                |      FORMID_TOK ',' reverseFORM_IDs
+                       {
+			 $3->push_back(*$1);
+			 $$ = $3;
+			 delete $1;
+                       }
+                ;
+
+FORM_IDs         :     reverseFORM_IDs
+                      {
+			$$ = new BEEV::ASTVec($1->rbegin(),$1->rend());
+			delete $1;
+                      }
+                ;
+
+/* Grammar for Types */
+Type		:      BvType { $$ = $1; }
+                |      BoolType { $$ = $1; }
+                |      ArrayType { $$ = $1; }
+		;		
+
+BvType          :      BV_TOK '(' NUMERAL_TOK ')' 
+                       {
+                         /*((indexwidth is 0) && (valuewidth>0)) iff type is BV*/
+			 $$.indexwidth = 0;
+			 unsigned int length = $3;
+			 if(length > 0) {
+			   $$.valuewidth = length;
+			 }
+			 else
+			  BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+		       }
+                ;
+BoolType        :      BOOLEAN_TOK
+                       {
+			 $$.indexwidth = 0;
+			 $$.valuewidth = 0;
+		       }
+                ;
+ArrayType       :      ARRAY_TOK BvType OF_TOK BvType
+                       {
+			 $$.indexwidth = $2.valuewidth;
+			 $$.valuewidth = $4.valuewidth;
+		       }
+                ;
+
+/*Grammar for ITEs which are a type of Term*/
+IfExpr	        :      IF_TOK Formula THEN_TOK Expr ElseRestExpr 
+                       {
+			 unsigned int width = $4->GetValueWidth();
+			 if (width != $5->GetValueWidth())
+			   yyerror("Width mismatch in IF-THEN-ELSE");			 
+			 if($4->GetIndexWidth() != $5->GetIndexWidth())
+			   yyerror("Width mismatch in IF-THEN-ELSE");
+
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$2);
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$4);
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE, width, *$2, *$4, *$5));
+			 $$->SetIndexWidth($5->GetIndexWidth());
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$$);
+			 delete $2;
+			 delete $4;
+			 delete $5;
+		      }
+		;
+
+ElseRestExpr	:      ELSE_TOK Expr ENDIF_TOK  { $$ = $2; }
+                |      ELSIF_TOK Expr THEN_TOK Expr ElseRestExpr 
+                       {
+			 unsigned int width = $2->GetValueWidth();
+			 if (width != $4->GetValueWidth() || width != $5->GetValueWidth())
+			   yyerror("Width mismatch in IF-THEN-ELSE");
+			 if ($2->GetIndexWidth() != $4->GetValueWidth() || $2->GetIndexWidth() != $5->GetValueWidth())
+			   yyerror("Width mismatch in IF-THEN-ELSE");
+
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$2);
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$4);
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);			
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE, width, *$2, *$4, *$5));
+			 $$->SetIndexWidth($5->GetIndexWidth());
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$$);
+			 delete $2;
+			 delete $4;
+			 delete $5;
+		       }
+		;
+
+/* Grammar for formulas */
+Formula		:     '(' Formula ')' { $$ = $2; }
+		|      FORMID_TOK {  $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1;}
+                |      BOOLEXTRACT_TOK '(' Expr ',' NUMERAL_TOK ')'
+                       {
+			 unsigned int width = $3->GetValueWidth();
+			 if(0 > (unsigned)$5 || width <= (unsigned)$5)
+			   yyerror("Fatal Error: BOOLEXTRACT: trying to boolextract a bit which beyond range");
+			 
+			 BEEV::ASTNode hi  =  BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+			 BEEV::ASTNode low =  BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,1,*$3,hi,low));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 BEEV::ASTNode zero = BEEV::globalBeevMgr_for_parser->CreateBVConst(1,0);			 
+			 BEEV::ASTNode * out = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::EQ,*n,zero));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*out);
+
+			 $$ = out;
+			 delete $3;
+                       }
+                |      Expr '=' Expr 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::EQ, *$1, *$3));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $1;
+			 delete $3;
+		       } 
+		|      Expr NEQ_TOK Expr 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NEQ, *$1, *$3));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $1;
+			 delete $3;
+		       }
+		|      NOT_TOK Formula 
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT, *$2));
+			 delete $2;
+		       }
+		|      Formula OR_TOK Formula %prec OR_TOK 
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::OR, *$1, *$3));
+			 delete $1;
+			 delete $3;
+		       } 
+		|      Formula NOR_TOK Formula
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOR, *$1, *$3));
+			 delete $1;
+			 delete $3;
+		       } 
+		|      Formula AND_TOK Formula %prec AND_TOK 
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND, *$1, *$3));
+			 delete $1;
+			 delete $3;
+		       }
+		|      Formula NAND_TOK Formula
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NAND, *$1, *$3));
+			 delete $1;
+			 delete $3;
+		       }
+		|      Formula IMPLIES_TOK Formula
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IMPLIES, *$1, *$3));
+			 delete $1;
+			 delete $3;
+		       }
+		|      Formula IFF_TOK Formula
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IFF, *$1, *$3));
+			 delete $1;
+			 delete $3;
+		       } 
+		|      Formula XOR_TOK Formula
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::XOR, *$1, *$3));
+			 delete $1;
+			 delete $3;
+		       } 
+	        |      BVLT_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLT, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVGT_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGT, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVLE_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLE, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVGE_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGE, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVSLT_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLT, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVSGT_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGT, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVSLE_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLE, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVSGE_TOK '(' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGE, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+		|      IfForm
+		|      TRUELIT_TOK 
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE)); 
+			 $$->SetIndexWidth(0); 
+			 $$->SetValueWidth(0);
+                       }
+		|      FALSELIT_TOK 
+                       { 
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::FALSE)); 
+			 $$->SetIndexWidth(0); 
+			 $$->SetValueWidth(0);
+		       }
+
+                |      LET_TOK LetDecls IN_TOK Formula
+                       {
+			 $$ = $4;
+			 //Cleanup the LetIDToExprMap
+			 BEEV::globalBeevMgr_for_parser->CleanupLetIDMap();
+		       }
+                ;
+
+/*Grammar for ITEs which are Formulas */
+IfForm	        :      IF_TOK Formula THEN_TOK Formula ElseRestForm 
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::ITE, *$2, *$4, *$5));
+			 delete $2;
+			 delete $4;
+			 delete $5;
+		      }
+		;
+
+ElseRestForm	:      ELSE_TOK Formula ENDIF_TOK  { $$ = $2; }
+                |      ELSIF_TOK Formula THEN_TOK Formula ElseRestForm 
+                       {
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::ITE, *$2, *$4, *$5));
+			 delete $2;
+			 delete $4;
+			 delete $5;
+		       }
+		;
+
+/*Grammar for a list of expressions*/
+Exprs		:      Expr 
+                       {
+			 $$ = new BEEV::ASTVec;
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$1);
+			 $$->push_back(*$1);
+			 delete $1;
+		       }
+                |      Exprs ',' Expr 
+                       {
+			 $1->push_back(*$3);
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+			 $$ = $1; 
+			 delete $3;
+		       }
+		;
+
+/* Grammar for Expr */
+Expr		:      TERMID_TOK { $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); delete $1;}
+                |      '(' Expr ')' { $$ = $2; }
+	        |      BVCONST_TOK { $$ = $1; }
+                |      BOOL_TO_BV_TOK '(' Formula ')'		
+                       {
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+			 BEEV::ASTNode one = BEEV::globalBeevMgr_for_parser->CreateBVConst(1,1);
+			 BEEV::ASTNode zero = BEEV::globalBeevMgr_for_parser->CreateBVConst(1,0);
+
+			 //return ITE(*$3, length(1), 0bin1, 0bin0)
+			 $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE,1,*$3,one,zero));
+			 delete $3;
+                       }
+		|      Expr '[' Expr ']' 
+                       {			 
+			 // valuewidth is same as array, indexwidth is 0.
+			 unsigned int width = $1->GetValueWidth();
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, *$1, *$3));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $1;
+			 delete $3;
+		       }
+                |      Expr '(' Expr ')' //array read but in the form of a uninterpreted function application
+                       {
+			 // valuewidth is same as array, indexwidth is 0.
+			 unsigned int width = $1->GetValueWidth();
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, *$1, *$3));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $1;
+			 delete $3;
+		       }
+	        |      Expr '[' NUMERAL_TOK ':' NUMERAL_TOK ']' 
+                       {
+			 int width = $3 - $5 + 1;
+			 if (width < 0)
+			   yyerror("Negative width in extract");
+			 
+			 if((unsigned)$3 >= $1->GetValueWidth() || (unsigned)$5 < 0)
+			   yyerror("Parsing: Wrong width in BVEXTRACT\n");			 
+
+			 BEEV::ASTNode hi  =  BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $3);
+			 BEEV::ASTNode low =  BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT, width, *$1,hi,low));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $1;
+		       }
+	        |      BVNEG_TOK Expr 
+                       {
+			 unsigned int width = $2->GetValueWidth();
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNEG, width, *$2));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $2;
+		       }
+	        |      Expr BVAND_TOK Expr 
+                       {
+			 unsigned int width = $1->GetValueWidth();
+			 if (width != $3->GetValueWidth()) {
+			   yyerror("Width mismatch in AND");
+			 }
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVAND, width, *$1, *$3));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $1;
+			 delete $3;
+		       }
+	        |      Expr BVOR_TOK Expr 
+                       {
+			 unsigned int width = $1->GetValueWidth();
+			 if (width != $3->GetValueWidth()) {
+			   yyerror("Width mismatch in OR");
+			 }
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVOR, width, *$1, *$3)); 
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $1;
+			 delete $3;
+		       }
+	        |      BVXOR_TOK '(' Expr ',' Expr ')' 
+                       {
+			 unsigned int width = $3->GetValueWidth();
+			 if (width != $5->GetValueWidth()) {
+			   yyerror("Width mismatch in XOR");
+			 }
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVXOR, width, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVNAND_TOK '(' Expr ',' Expr ')' 
+                       {
+			 unsigned int width = $3->GetValueWidth();
+			 if (width != $5->GetValueWidth()) {
+			   yyerror("Width mismatch in NAND");
+			 }
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNAND, width, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $3;
+			 delete $5;
+		       }
+                |      BVNOR_TOK '(' Expr ',' Expr ')' 
+                       {
+			 unsigned int width = $3->GetValueWidth();
+			 if (width != $5->GetValueWidth()) {
+			   yyerror("Width mismatch in NOR");
+			 }
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNOR, width, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $3;
+			 delete $5;
+		       }
+	        |      BVXNOR_TOK '(' Expr ',' Expr ')' 
+                       {
+			 unsigned int width = $3->GetValueWidth();
+			 if (width != $5->GetValueWidth()) {
+			   yyerror("Width mismatch in NOR");
+			 }
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVXNOR, width, *$3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $3;
+			 delete $5;
+		       }
+                |      BVSX_TOK '(' Expr ',' NUMERAL_TOK ')' 
+                       {
+			 //width of the expr which is being sign
+			 //extended. $5 is the resulting length of the
+			 //signextended expr
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+			 if($3->GetValueWidth() == $5) {
+			   $$ = $3;
+			 }
+			 else {
+			   BEEV::ASTNode width = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,$5);
+			   BEEV::ASTNode *n =  
+			     new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSX, $5,*$3,width));
+			   BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			   $$ = n;
+			   delete $3;
+			 }
+		       }
+	        |      Expr BVCONCAT_TOK Expr 
+                       {
+			 unsigned int width = $1->GetValueWidth() + $3->GetValueWidth();
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, width, *$1, *$3));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 
+			 delete $1;
+			 delete $3;
+		       }
+                |      Expr BVLEFTSHIFT_TOK NUMERAL_TOK 
+                       {
+			 BEEV::ASTNode zero_bits = BEEV::globalBeevMgr_for_parser->CreateZeroConst($3);
+			 BEEV::ASTNode * n = 
+			   new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,
+											$1->GetValueWidth() + $3, *$1, zero_bits));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $1;
+                       }
+                |      Expr BVRIGHTSHIFT_TOK NUMERAL_TOK 
+                       {
+			 BEEV::ASTNode len = BEEV::globalBeevMgr_for_parser->CreateZeroConst($3);
+			 unsigned int w = $1->GetValueWidth();
+
+			 //the amount by which you are rightshifting
+			 //is less-than/equal-to the length of input
+			 //bitvector
+			 if((unsigned)$3 < w) {
+			   BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1);
+			   BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,$3);
+			   BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$1,hi,low);
+			   BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,len, extract));
+			   BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			   $$ = n;
+			 } 
+			 else
+			   $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateZeroConst(w));			 
+
+			 delete $1;
+                       }
+                |      BVPLUS_TOK '(' NUMERAL_TOK ',' Exprs ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVPLUS, $3, *$5));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $5;
+                       }
+                |      BVSUB_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSUB, $3, *$5, *$7));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $5;
+			 delete $7;
+                       }
+                |      BVUMINUS_TOK '(' Expr ')' 
+                       {
+			 unsigned width = $3->GetValueWidth();
+			 BEEV::ASTNode * n =  new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVUMINUS,width,*$3));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $3;
+                       }
+                |      BVMULT_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVMULT, $3, *$5, *$7));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $5;
+			 delete $7;
+		       }
+                |      BVDIV_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVDIV, $3, *$5, *$7));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $5;
+			 delete $7;
+		       }
+                |      BVMOD_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVMOD, $3, *$5, *$7));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $5;
+			 delete $7;
+		       }
+                |      SBVDIV_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::SBVDIV, $3, *$5, *$7));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+
+			 delete $5;
+			 delete $7;
+		       }
+                |      SBVMOD_TOK '(' NUMERAL_TOK ',' Expr ',' Expr ')' 
+                       {
+			 BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::SBVMOD, $3, *$5, *$7));
+			 BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+			 $$ = n;
+			 delete $5;
+			 delete $7;
+		       }        
+		|      IfExpr { $$ = $1; }
+                |      ArrayUpdateExpr
+                |      LET_TOK LetDecls IN_TOK Expr
+                       {
+			 $$ = $4;
+			 //Cleanup the LetIDToExprMap
+			 //BEEV::globalBeevMgr_for_parser->CleanupLetIDMap();
+		       }
+		;
+
+/*Grammar for Array Update Expr*/
+ArrayUpdateExpr : Expr WITH_TOK Updates
+                  {
+		    BEEV::ASTNode * result;
+		    unsigned int width = $1->GetValueWidth();
+
+		    BEEV::ASTNodeMap::iterator it = $3->begin();
+		    BEEV::ASTNodeMap::iterator itend = $3->end();
+		    result = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::WRITE,
+							      width,
+							      *$1,
+							      (*it).first,
+							      (*it).second));
+		    result->SetIndexWidth($1->GetIndexWidth());
+		    BEEV::globalBeevMgr_for_parser->BVTypeCheck(*result);
+		    for(it++;it!=itend;it++) {
+		      result = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::WRITE,
+								width,
+								*result,
+								(*it).first,
+								(*it).second));
+		      result->SetIndexWidth($1->GetIndexWidth());
+		      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*result);
+		    }
+		    BEEV::globalBeevMgr_for_parser->BVTypeCheck(*result);
+		    $$ = result;
+		    delete $3;
+                  }
+                ;
+
+Updates         : '[' Expr ']' ASSIGN_TOK Expr 
+                  {
+		    $$ = new BEEV::ASTNodeMap();
+		    (*$$)[*$2] = *$5;		    
+                  }
+                | Updates WITH_TOK '[' Expr ']' ASSIGN_TOK Expr 
+                  {		    
+		    (*$1)[*$4] = *$7;
+                  }
+                ;
+
+/*Grammar for LET Expr*/
+LetDecls	:	LetDecl 
+		|	LetDecls ',' LetDecl 
+		;
+
+LetDecl		:	FORMID_TOK '=' Expr 
+                        {
+			  //Expr must typecheck
+			  BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+
+			  //set the valuewidth of the identifier
+			  $1->SetValueWidth($3->GetValueWidth());
+			  $1->SetIndexWidth($3->GetIndexWidth());
+
+			  //populate the hashtable from LET-var -->
+			  //LET-exprs and then process them:
+			  //
+			  //1. ensure that LET variables do not clash
+			  //1. with declared variables.
+			  //
+			  //2. Ensure that LET variables are not
+			  //2. defined more than once
+			  BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$3);
+			  delete $1;
+			  delete $3;
+			}
+                |	FORMID_TOK ':' Type '=' Expr
+			{
+			  //do type checking. if doesn't pass then abort
+			  BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+			  
+			  if($3.indexwidth != $5->GetIndexWidth())
+			    yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+			  if($3.valuewidth != $5->GetValueWidth())
+			    yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+
+			  //set the valuewidth of the identifier
+			  $1->SetValueWidth($5->GetValueWidth());
+			  $1->SetIndexWidth($5->GetIndexWidth());
+
+			  BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$5);
+			  delete $1;
+			  delete $5;
+			}
+                |       FORMID_TOK '=' Formula
+                        {
+			  //Expr must typecheck
+			  BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+
+			  //set the valuewidth of the identifier
+			  $1->SetValueWidth($3->GetValueWidth());
+			  $1->SetIndexWidth($3->GetIndexWidth());
+
+			  //Do LET-expr management
+			  BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$3);
+			  delete $1;
+			  delete $3;
+			}
+                |	FORMID_TOK ':' Type '=' Formula
+			{
+			  //do type checking. if doesn't pass then abort
+			  BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+
+			  if($3.indexwidth != $5->GetIndexWidth())
+			    yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+			  if($3.valuewidth != $5->GetValueWidth())
+			    yyerror("Fatal Error: parsing: LET Expr: Type check fail: ");
+
+			  //set the valuewidth of the identifier
+			  $1->SetValueWidth($5->GetValueWidth());
+			  $1->SetIndexWidth($5->GetIndexWidth());
+
+			  //Do LET-expr management
+			  BEEV::globalBeevMgr_for_parser->LetExprMgr(*$1,*$5);
+			  delete $1;
+			  delete $5;
+			}                
+		;
+
+%%
diff --git a/stp/parser/let-funcs.cpp b/stp/parser/let-funcs.cpp
new file mode 100644
index 00000000..1de10492
--- /dev/null
+++ b/stp/parser/let-funcs.cpp
@@ -0,0 +1,85 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include <stdlib.h>
+
+namespace BEEV {
+  //external parser table for declared symbols. Only symbols which are
+  //declared are stored here.
+  ASTNodeSet _parser_symbol_table;
+
+  // FUNC: This function maintains a map between LET-var names and
+  // LET-expressions
+  //
+  //1. if the Let-var is already defined in the LET scope, then the
+  //1. function returns an error.
+  //
+  //2. if the Let-var is already declared variable in the input, then
+  //2. the function returns an error
+  //
+  //3. otherwise add the <var,letExpr> pair to the _letid_expr table.
+  void BeevMgr::LetExprMgr(const ASTNode& var, const ASTNode& letExpr) {
+    ASTNodeMap::iterator it;
+    if(((it = _letid_expr_map.find(var)) != _letid_expr_map.end()) && 
+       it->second != ASTUndefined) {      
+      FatalError("LetExprMgr:The LET-var v has already been defined in this LET scope: v =", var);
+    }
+
+    if(_parser_symbol_table.find(var) != _parser_symbol_table.end()) {
+      FatalError("LetExprMgr:This var is already declared. cannot redeclare as a letvar: v =", var);
+    }
+
+    _letid_expr_map[var] = letExpr;   
+  }
+
+  //this function looksup the "var to letexpr map" and returns the
+  //corresponding letexpr. if there is no letexpr, then it simply
+  //returns the var.
+  ASTNode BeevMgr::ResolveID(const ASTNode& v) {
+    if(v.GetKind() != SYMBOL) {
+      return v;
+    }
+
+    if(_parser_symbol_table.find(v) != _parser_symbol_table.end()) {
+      return v;
+    }
+
+    ASTNodeMap::iterator it;
+    if((it =_letid_expr_map.find(v)) != _letid_expr_map.end()) {
+      if(it->second == ASTUndefined) 
+	FatalError("Unresolved Identifier: ",v);
+      else
+	return it->second;
+    }
+
+    //this is to mark the let-var as undefined. the let var is defined
+    //only after the LetExprMgr has completed its work, and until then
+    //'v' is undefined. 
+    //
+    //declared variables also get stored in this map, but there value
+    //is ASTUndefined. This is really a hack. I don't know how to get
+    //rid of this hack.
+    _letid_expr_map[v] = ASTUndefined;
+    return v;    
+  }
+  
+  // This function simply cleans up the LetID -> LetExpr Map.   
+  void BeevMgr::CleanupLetIDMap(void) { 
+    ASTNodeMap::iterator it = _letid_expr_map.begin();
+    ASTNodeMap::iterator itend = _letid_expr_map.end();
+    for(;it!=itend;it++) {
+      if(it->second != ASTUndefined) {
+	it->first.SetValueWidth(0);
+	it->first.SetIndexWidth(0);
+      }
+    }
+    _letid_expr_map.clear();
+  }
+};
diff --git a/stp/parser/main.cpp b/stp/parser/main.cpp
new file mode 100644
index 00000000..ed251ed3
--- /dev/null
+++ b/stp/parser/main.cpp
@@ -0,0 +1,181 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <algorithm>
+#include <ctime>
+#include <unistd.h>
+#include <signal.h>
+//#include <zlib.h>
+#include <stdio.h>
+#include "../AST/AST.h"
+#include "parsePL_defs.h"
+#include "../sat/Solver.h"
+#include "../sat/SolverTypes.h"
+#include "../sat/VarOrder.h"
+
+#include <unistd.h>
+
+#ifdef EXT_HASH_MAP
+  using namespace __gnu_cxx;
+#endif
+
+/* GLOBAL FUNCTION: parser
+ */
+extern int yyparse();
+//extern int smtlibparse();
+
+/* GLOBAL VARS: Some global vars for the Main function.
+ *
+ */
+const char * prog = "stp";
+int linenum  = 1;
+const char * usage = "Usage: %s [-option] [infile]\n";
+std::string helpstring = "\n\n";
+
+// Amount of memory to ask for at beginning of main.
+static const intptr_t INITIAL_MEMORY_PREALLOCATION_SIZE = 4000000;
+
+// Used only in smtlib lexer/parser
+BEEV::ASTNode SingleBitOne;
+BEEV::ASTNode SingleBitZero;
+
+/******************************************************************************
+ * MAIN FUNCTION: 
+ *
+ * step 0. Parse the input into an ASTVec.
+ * step 1. Do BV Rewrites
+ * step 2. Bitblasts the ASTNode.
+ * step 3. Convert to CNF
+ * step 4. Convert to SAT
+ * step 5. Call SAT to determine if input is SAT or UNSAT
+ ******************************************************************************/
+int main(int argc, char ** argv) {
+  char * infile;
+  extern FILE *yyin;
+
+  // 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)) {
+    // FIXME: figure out how to get and print the real error message.
+    BEEV::FatalError("Initial allocation of memory failed.");
+  }
+  
+  //populate the help string
+  helpstring +=  "-r  : switch refinement off (optimizations are ON by default)\n";
+  helpstring +=  "-w  : switch wordlevel solver off (optimizations are ON by default)\n";
+  helpstring +=  "-a  : switch optimizations off (optimizations are ON by default)\n";
+  helpstring +=  "-s  : print function statistics\n";
+  helpstring +=  "-v  : print nodes \n";
+  helpstring +=  "-c  : construct counterexample\n";
+  helpstring +=  "-d  : check counterexample\n";
+  helpstring +=  "-p  : print counterexample\n";
+  helpstring +=  "-x  : flatten nested XORs\n";
+  helpstring +=  "-h  : help\n";
+
+  for(int i=1; i < argc;i++) {
+    if(argv[i][0] == '-')
+      switch(argv[i][1]) {
+      case 'a' :
+	BEEV::optimize = false;
+	BEEV::wordlevel_solve = false;
+	break;
+      case 'b':
+	BEEV::print_STPinput_back = true;
+	break;
+      case 'c':
+	BEEV::construct_counterexample = true;
+	break;
+      case 'd':
+	BEEV::construct_counterexample = true;
+	BEEV::check_counterexample = true;
+	break;
+      case 'e':
+	BEEV::variable_activity_optimize = true;
+	break;
+      case 'f':
+	BEEV::smtlib_parser_enable = true;
+	break;
+      case 'h':
+	fprintf(stderr,usage,prog);
+	cout << helpstring;
+	//BEEV::FatalError("");
+	return -1;
+	break;
+      case 'l' :
+	BEEV::linear_search = true;
+	break;
+      case 'n':
+	BEEV::print_output = true;
+	break;
+      case 'p':
+	BEEV::print_counterexample = true;
+	break;
+      case 'q':
+	BEEV::print_arrayval_declaredorder = true;
+	break;
+      case 'r':
+	BEEV::arrayread_refinement = false;
+	break;
+      case 's' :
+	BEEV::stats = true;
+	break;
+      case 'u':
+	BEEV::arraywrite_refinement = false;
+	break;
+      case 'v' :
+	BEEV::print_nodes = true;
+	break;
+      case 'w':
+	BEEV::wordlevel_solve = false;
+	break;
+      case 'x':
+	BEEV::xor_flatten = true;
+	break;
+      case 'z':
+	BEEV::print_sat_varorder = true;
+	break;
+      default:
+	fprintf(stderr,usage,prog);
+	cout << helpstring;
+	//BEEV::FatalError("");
+	return -1;
+	break;
+      }
+    else {
+      infile = argv[i];
+      yyin = fopen(infile,"r");
+      if(yyin == NULL) {
+	fprintf(stderr,"%s: Error: cannot open %s\n",prog,infile);
+	BEEV::FatalError("");
+      }
+    }
+  }
+
+#ifdef NATIVE_C_ARITH
+#else
+  CONSTANTBV::ErrCode c = CONSTANTBV::BitVector_Boot(); 
+  if(0 != c) {
+    cout << CONSTANTBV::BitVector_Error(c) << endl;
+    return 0;
+  }
+#endif           
+
+  //want to print the output always from the commandline. 
+  BEEV::print_output = true;
+  BEEV::globalBeevMgr_for_parser = new BEEV::BeevMgr();  
+
+  SingleBitOne = BEEV::globalBeevMgr_for_parser->CreateOneConst(1);
+  SingleBitZero = BEEV::globalBeevMgr_for_parser->CreateZeroConst(1);
+  //BEEV::smtlib_parser_enable = true;
+  yyparse();
+}//end of Main
diff --git a/stp/parser/smtlib.lex b/stp/parser/smtlib.lex
new file mode 100644
index 00000000..a03ae94e
--- /dev/null
+++ b/stp/parser/smtlib.lex
@@ -0,0 +1,232 @@
+%{
+  /********************************************************************
+   * AUTHORS: Vijay Ganesh, David L. Dill
+   *
+   * BEGIN DATE: July, 2006
+   *
+   * This file is modified version of the CVCL's smtlib.lex file. Please
+   * see CVCL license below
+   ********************************************************************/
+  
+  /********************************************************************
+   * \file smtlib.lex
+   * 
+   * Author: Sergey Berezin, Clark Barrett
+   * 
+   * Created: Apr 30 2005
+   *
+   * <hr>
+   * Copyright (C) 2004 by the Board of Trustees of Leland Stanford
+   * Junior University and by New York University. 
+   *
+   * License to use, copy, modify, sell and/or distribute this software
+   * and its documentation for any purpose is hereby granted without
+   * royalty, subject to the terms and conditions defined in the \ref
+   * LICENSE file provided with this distribution.  In particular:
+   *
+   * - The above copyright notice and this permission notice must appear
+   * in all copies of the software and related documentation.
+   *
+   * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
+   * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
+   * 
+   * <hr>
+   ********************************************************************/
+  // -*- c++ -*-
+#include <iostream>
+#include "../AST/AST.h"
+#include "parsePL_defs.h"
+  
+  extern char *yytext;
+  extern int yyerror (char *msg);
+  
+  // File-static (local to this file) variables and functions
+  static std::string _string_lit;
+  
+  static char escapeChar(char c) {
+    switch(c) {
+    case 'n': return '\n';
+    case 't': return '\t';
+    default: return c;
+    }
+  }      
+
+  extern BEEV::ASTNode SingleBitOne;
+  extern BEEV::ASTNode SingleBitZero;
+
+/* Changed for smtlib speedup */
+/* bv{DIGIT}+      { yylval.node = new BEEV::ASTNode(BEEV::_bm->CreateBVConst(yytext+2, 10)); return BVCONST_TOK;} */
+
+%}
+
+%option noyywrap
+%option nounput
+%option noreject
+%option noyymore
+%option yylineno
+
+%x	COMMENT
+%x	STRING_LITERAL
+%x      USER_VALUE
+
+LETTER	([a-zA-Z])
+DIGIT	([0-9])
+OPCHAR	(['\.\_]) 
+ANYTHING  ({LETTER}|{DIGIT}|{OPCHAR})
+
+%%
+[ \n\t\r\f]	{ /* sk'ip whitespace */ }
+{DIGIT}+	{ yylval.uintval = strtoul(yytext, NULL, 10); return NUMERAL_TOK; }
+
+
+bv{DIGIT}+	{ yylval.ullval = strtoull(yytext+2, NULL, 10); return BVCONST_TOK; }
+
+bit{DIGIT}+     {
+  		   char c = yytext[3];
+		   if (c == '1') {
+		     yylval.node = new BEEV::ASTNode(SingleBitOne);
+		   }
+		   else {
+		     yylval.node = new BEEV::ASTNode(SingleBitZero);
+		   }
+		   return BITCONST_TOK;
+		};
+
+
+";"		{ BEGIN COMMENT; }
+<COMMENT>"\n"	{ BEGIN INITIAL; /* return to normal mode */}
+<COMMENT>.	{ /* stay in comment mode */ }
+
+<INITIAL>"\""		{ BEGIN STRING_LITERAL;
+                          _string_lit.erase(_string_lit.begin(),
+                                            _string_lit.end()); }
+<STRING_LITERAL>"\\".	{ /* escape characters (like \n or \") */
+                          _string_lit.insert(_string_lit.end(),
+                                             escapeChar(yytext[1])); }
+<STRING_LITERAL>"\""	{ BEGIN INITIAL; /* return to normal mode */
+			  yylval.str = new std::string(_string_lit);
+                          return STRING_TOK; }
+<STRING_LITERAL>.	{ _string_lit.insert(_string_lit.end(),*yytext); }
+
+
+<INITIAL>"{"		{ BEGIN USER_VALUE;
+                          _string_lit.erase(_string_lit.begin(),
+                                            _string_lit.end()); }
+<USER_VALUE>"\\"[{}] { /* escape characters */
+                          _string_lit.insert(_string_lit.end(),yytext[1]); }
+
+<USER_VALUE>"}"	        { BEGIN INITIAL; /* return to normal mode */
+			  yylval.str = new std::string(_string_lit);
+                          return USER_VAL_TOK; }
+<USER_VALUE>"\n"        { _string_lit.insert(_string_lit.end(),'\n');}
+<USER_VALUE>.	        { _string_lit.insert(_string_lit.end(),*yytext); }
+
+"BitVec"        { return BITVEC_TOK;}
+"Array"         { return ARRAY_TOK;}
+"true"          { return TRUE_TOK; }
+"false"         { return FALSE_TOK; }
+"not"           { return NOT_TOK; }
+"implies"       { return IMPLIES_TOK; }
+"ite"           { return ITE_TOK;}
+"if_then_else"  { return IF_THEN_ELSE_TOK; }
+"and"           { return AND_TOK; }
+"or"            { return OR_TOK; }
+"xor"           { return XOR_TOK; }
+"iff"           { return IFF_TOK; }
+"let"           { return LET_TOK; }
+"flet"          { return FLET_TOK; }
+"notes"         { return NOTES_TOK; }
+"cvc_command"   { return CVC_COMMAND_TOK; }
+"sorts"         { return SORTS_TOK; }
+"funs"          { return FUNS_TOK; }
+"preds"         { return PREDS_TOK; }
+"extensions"    { return EXTENSIONS_TOK; }
+"definition"    { return DEFINITION_TOK; }
+"axioms"        { return AXIOMS_TOK; }
+"logic"         { return LOGIC_TOK; }
+"sat"           { return SAT_TOK; }
+"unsat"         { return UNSAT_TOK; }
+"unknown"       { return UNKNOWN_TOK; }
+"assumption"    { return ASSUMPTION_TOK; }
+"formula"       { return FORMULA_TOK; }
+"status"        { return STATUS_TOK; }
+"difficulty"    { return DIFFICULTY_TOK; }
+"benchmark"     { return BENCHMARK_TOK; }
+"source"        { return SOURCE_TOK;}
+"category"      { return CATEGORY_TOK;} 
+"extrasorts"    { return EXTRASORTS_TOK; }
+"extrafuns"     { return EXTRAFUNS_TOK; }
+"extrapreds"    { return EXTRAPREDS_TOK; }
+"language"      { return LANGUAGE_TOK; }
+"distinct"      { return DISTINCT_TOK; }
+"select"        { return SELECT_TOK; }
+"store"         { return STORE_TOK; }
+":"             { return COLON_TOK; }
+"\["            { return LBRACKET_TOK; }
+"\]"            { return RBRACKET_TOK; }
+"("             { return LPAREN_TOK; }
+")"             { return RPAREN_TOK; }
+"$"             { return DOLLAR_TOK; }
+"?"             { return QUESTION_TOK; }
+"="             {return EQ_TOK;}
+
+"nand"		{ return NAND_TOK;}
+"nor"		{ return NOR_TOK;}
+"/="		{ return NEQ_TOK; }
+ ":="           { return ASSIGN_TOK;}
+"shift_left0"   { return BVLEFTSHIFT_TOK;}
+"bvshl"         { return BVLEFTSHIFT_1_TOK;}
+"shift_right0"  { return BVRIGHTSHIFT_TOK;}
+"bvlshr"        { return BVRIGHTSHIFT_1_TOK;}
+"bvadd"         { return BVPLUS_TOK;}
+"bvsub"         { return BVSUB_TOK;}
+"bvnot"         { return BVNOT_TOK;}
+"bvmul"         { return BVMULT_TOK;}
+"bvdiv"         { return BVDIV_TOK;}
+"bvmod"         { return BVMOD_TOK;}
+"bvneg"         { return BVNEG_TOK;}
+"bvand"         { return BVAND_TOK;}
+"bvor"          { return BVOR_TOK;}
+"bvxor"         { return BVXOR_TOK;}
+"bvnand"        { return BVNAND_TOK;}
+"bvnor"         { return BVNOR_TOK;}
+"bvxnor"        { return BVXNOR_TOK;}
+"concat"        { return BVCONCAT_TOK;}
+"extract"       { return BVEXTRACT_TOK;}
+"bvlt"          { return BVLT_TOK;}
+"bvgt"          { return BVGT_TOK;}
+"bvleq"         { return BVLE_TOK;}
+"bvgeq"         { return BVGE_TOK;}
+"bvult"         { return BVLT_TOK;}
+"bvugt"         { return BVGT_TOK;}
+"bvuleq"        { return BVLE_TOK;}
+"bvugeq"        { return BVGE_TOK;}
+"bvule"         { return BVLE_TOK;}
+"bvuge"         { return BVGE_TOK;}
+
+"bvslt"         { return BVSLT_TOK;}
+"bvsgt"         { return BVSGT_TOK;}
+"bvsleq"        { return BVSLE_TOK;}
+"bvsgeq"        { return BVSGE_TOK;}
+"bvsle"         { return BVSLE_TOK;}
+"bvsge"         { return BVSGE_TOK;}
+
+"sign_extend"   { return BVSX_TOK;} 
+"boolextract"   { return BOOLEXTRACT_TOK;}
+"boolbv"        { return BOOL_TO_BV_TOK;}
+
+(({LETTER})|(_)({ANYTHING}))({ANYTHING})*	{
+  BEEV::ASTNode nptr = BEEV::globalBeevMgr_for_parser->CreateSymbol(yytext); 
+
+  // Check valuesize to see if it's a prop var.  I don't like doing
+  // type determination in the lexer, but it's easier than rewriting
+  // the whole grammar to eliminate the term/formula distinction.  
+  yylval.node = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(nptr));
+  //yylval.node = new BEEV::ASTNode(nptr);
+  if ((yylval.node)->GetType() == BEEV::BOOLEAN_TYPE)
+    return FORMID_TOK;
+  else 
+    return TERMID_TOK;  
+}
+. { yyerror("Illegal input character."); }
+%%
diff --git a/stp/parser/smtlib.y b/stp/parser/smtlib.y
new file mode 100644
index 00000000..0aa22dee
--- /dev/null
+++ b/stp/parser/smtlib.y
@@ -0,0 +1,1036 @@
+%{
+  /********************************************************************
+   * AUTHORS: Vijay Ganesh, David L. Dill
+   *
+   * BEGIN DATE: July, 2006
+   *
+   * This file is modified version of the CVCL's smtlib.y file. Please
+   * see CVCL license below
+   ********************************************************************/
+  
+  /********************************************************************
+   *
+   * \file smtlib.y
+   * 
+   * Author: Sergey Berezin, Clark Barrett
+   * 
+   * Created: Apr 30 2005
+   *
+   * <hr>
+   * Copyright (C) 2004 by the Board of Trustees of Leland Stanford
+   * Junior University and by New York University. 
+   *
+   * License to use, copy, modify, sell and/or distribute this software
+   * and its documentation for any purpose is hereby granted without
+   * royalty, subject to the terms and conditions defined in the \ref
+   * LICENSE file provided with this distribution.  In particular:
+   *
+   * - The above copyright notice and this permission notice must appear
+   * in all copies of the software and related documentation.
+   *
+   * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
+   * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
+   * 
+   * <hr>
+   ********************************************************************/
+  // -*- c++ -*-
+
+#include "../AST/AST.h"
+  using namespace std; 
+  
+  // Suppress the bogus warning suppression in bison (it generates
+  // compile error)
+#undef __GNUC_MINOR__
+  
+  extern char* yytext;
+  extern int yylineno;
+  
+  //int yylineno;
+
+  extern int yylex(void);
+
+  int yyerror(char *s) {
+    //yylineno = 0;
+    cout << "syntax error: line " << yylineno << "\n" << s << endl;
+    cout << "  token: " << yytext << endl;
+    BEEV::FatalError("");
+    return 1;
+  }
+
+  BEEV::ASTNode query;
+#define YYLTYPE_IS_TRIVIAL 1
+#define YYMAXDEPTH 104857600
+#define YYERROR_VERBOSE 1
+#define YY_EXIT_FAILURE -1
+%}
+
+%union {  
+  // FIXME: Why is this not an UNSIGNED int?
+  int uintval;			/* for numerals in types. */
+
+  // for BV32 BVCONST 
+  unsigned long long ullval;
+
+  struct {
+    //stores the indexwidth and valuewidth
+    //indexwidth is 0 iff type is bitvector. positive iff type is
+    //array, and stores the width of the indexing bitvector
+    unsigned int indexwidth;
+    //width of the bitvector type
+    unsigned int valuewidth;
+  } indexvaluewidth;
+
+  //ASTNode,ASTVec
+  BEEV::ASTNode *node;
+  BEEV::ASTVec *vec;
+  std::string *str;
+};
+
+%start cmd
+
+%type <indexvaluewidth> sort_symb sort_symbs
+%type <node> status
+%type <vec> bench_attributes an_formulas
+
+%type <node> benchmark bench_name bench_attribute
+%type <node> an_term an_nonbvconst_term an_formula 
+
+%type <node> var fvar logic_name
+%type <str> user_value
+
+%token <uintval> NUMERAL_TOK
+%token <ullval> BVCONST_TOK
+%token <node> BITCONST_TOK
+%token <node> FORMID_TOK TERMID_TOK 
+%token <str> STRING_TOK
+%token <str> USER_VAL_TOK
+%token SOURCE_TOK
+%token CATEGORY_TOK
+%token DIFFICULTY_TOK
+%token BITVEC_TOK
+%token ARRAY_TOK
+%token SELECT_TOK
+%token STORE_TOK
+%token TRUE_TOK
+%token FALSE_TOK
+%token NOT_TOK
+%token IMPLIES_TOK
+%token ITE_TOK
+%token IF_THEN_ELSE_TOK
+%token AND_TOK
+%token OR_TOK
+%token XOR_TOK
+%token IFF_TOK
+%token EXISTS_TOK
+%token FORALL_TOK
+%token LET_TOK
+%token FLET_TOK
+%token NOTES_TOK
+%token CVC_COMMAND_TOK
+%token SORTS_TOK
+%token FUNS_TOK
+%token PREDS_TOK
+%token EXTENSIONS_TOK
+%token DEFINITION_TOK
+%token AXIOMS_TOK
+%token LOGIC_TOK
+%token COLON_TOK
+%token LBRACKET_TOK
+%token RBRACKET_TOK
+%token LPAREN_TOK
+%token RPAREN_TOK
+%token SAT_TOK
+%token UNSAT_TOK
+%token UNKNOWN_TOK
+%token ASSUMPTION_TOK
+%token FORMULA_TOK
+%token STATUS_TOK
+%token BENCHMARK_TOK
+%token EXTRASORTS_TOK
+%token EXTRAFUNS_TOK
+%token EXTRAPREDS_TOK
+%token LANGUAGE_TOK
+%token DOLLAR_TOK
+%token QUESTION_TOK
+%token DISTINCT_TOK
+%token SEMICOLON_TOK
+%token EOF_TOK
+%token EQ_TOK
+/*BV SPECIFIC TOKENS*/
+%token NAND_TOK
+%token NOR_TOK
+%token NEQ_TOK
+%token ASSIGN_TOK
+%token BV_TOK
+%token BOOLEAN_TOK
+%token BVLEFTSHIFT_TOK
+%token BVLEFTSHIFT_1_TOK
+%token BVRIGHTSHIFT_TOK
+%token BVRIGHTSHIFT_1_TOK
+%token BVPLUS_TOK
+%token BVSUB_TOK
+%token BVNOT_TOK //bvneg in CVCL
+%token BVMULT_TOK
+%token BVDIV_TOK
+%token BVMOD_TOK
+%token BVNEG_TOK //bvuminus in CVCL
+%token BVAND_TOK
+%token BVOR_TOK
+%token BVXOR_TOK
+%token BVNAND_TOK
+%token BVNOR_TOK
+%token BVXNOR_TOK
+%token BVCONCAT_TOK
+%token BVLT_TOK
+%token BVGT_TOK
+%token BVLE_TOK
+%token BVGE_TOK
+%token BVSLT_TOK
+%token BVSGT_TOK
+%token BVSLE_TOK
+%token BVSGE_TOK
+%token BVSX_TOK 
+%token BOOLEXTRACT_TOK
+%token BOOL_TO_BV_TOK
+%token BVEXTRACT_TOK
+
+%left LBRACKET_TOK RBRACKET_TOK
+
+%%
+
+cmd:
+    benchmark
+    {
+      if($1 != NULL) {
+	BEEV::globalBeevMgr_for_parser->TopLevelSAT(*$1,query);
+	delete $1;
+      }
+      YYACCEPT;
+    }
+;
+
+benchmark:
+    LPAREN_TOK BENCHMARK_TOK bench_name bench_attributes RPAREN_TOK
+    {
+      if($4 != NULL){
+	if($4->size() > 1) 
+	  $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND,*$4));
+	else
+	  $$ = new BEEV::ASTNode((*$4)[0]);	  
+	delete $4;
+      }
+      else {
+	$$ = NULL;
+      }
+    }
+/*   | EOF_TOK */
+/*     { */
+/*     } */
+;
+
+bench_name:
+    FORMID_TOK
+    {
+    }
+;
+
+bench_attributes:
+    bench_attribute
+    {
+      $$ = new BEEV::ASTVec;
+      if ($1 != NULL) {
+	$$->push_back(*$1);
+	BEEV::globalBeevMgr_for_parser->AddAssert(*$1);
+	delete $1;
+      }
+    }
+  | bench_attributes bench_attribute
+    {
+      if ($1 != NULL && $2 != NULL) {
+	$1->push_back(*$2);
+	BEEV::globalBeevMgr_for_parser->AddAssert(*$2);
+	$$ = $1;
+	delete $2;
+      }
+    }
+;
+
+bench_attribute:
+    COLON_TOK ASSUMPTION_TOK an_formula
+    {
+      //assumptions are like asserts
+      $$ = $3;
+    }
+  | COLON_TOK FORMULA_TOK an_formula
+    {
+      //the query
+      query = BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT,*$3);
+      BEEV::globalBeevMgr_for_parser->AddQuery(query);
+      //dummy true
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE));
+      
+      
+    }
+  | COLON_TOK STATUS_TOK status
+    {
+      $$ = NULL;
+    }
+  | COLON_TOK LOGIC_TOK logic_name
+    {
+      if (!(0 == strcmp($3->GetName(),"QF_UFBV")  ||
+            0 == strcmp($3->GetName(),"QF_AUFBV"))) {
+	yyerror("Wrong input logic:");
+      }
+      $$ = NULL;
+    }
+  | COLON_TOK EXTRAFUNS_TOK LPAREN_TOK var_decls RPAREN_TOK
+    {
+      $$ = NULL;
+    }
+  | COLON_TOK EXTRAPREDS_TOK LPAREN_TOK var_decls RPAREN_TOK
+    {
+      $$ = NULL;
+    }
+  | annotation 
+    {
+      $$ = NULL;
+    }
+;
+
+logic_name:
+    FORMID_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK
+    {
+      $$ = $1;
+    }
+  | FORMID_TOK
+    {
+      $$ = $1;
+    }
+;
+
+status:
+    SAT_TOK { $$ = NULL; }
+  | UNSAT_TOK { $$ = NULL; }
+  | UNKNOWN_TOK { $$ = NULL; }
+;
+
+
+/* annotations: */
+/*     annotation */
+/*     { */
+/*     } */
+/*   | annotations annotation */
+/*     { */
+/*     } */
+/*   ; */
+  
+annotation:
+    attribute 
+    {
+    }
+  | attribute user_value 
+    {
+    }
+;
+
+user_value:
+    USER_VAL_TOK
+    {
+      //cerr << "Printing user_value: " << *$1 << endl;
+    }
+;
+
+attribute:
+    COLON_TOK SOURCE_TOK
+    {
+    }
+   | COLON_TOK CATEGORY_TOK
+    {
+    }
+   | COLON_TOK DIFFICULTY_TOK 
+;
+
+sort_symbs:
+    sort_symb 
+    {
+      //a single sort symbol here means either a BitVec or a Boolean
+      $$.indexwidth = $1.indexwidth;
+      $$.valuewidth = $1.valuewidth;
+    }
+  | sort_symb sort_symb
+    {
+      //two sort symbols mean f: type --> type
+      $$.indexwidth = $1.valuewidth;
+      $$.valuewidth = $2.valuewidth;
+    }
+;
+
+var_decls:
+    var_decl
+    {
+    }
+//  | LPAREN_TOK var_decl RPAREN_TOK
+  |
+    var_decls var_decl
+    {
+    }
+;
+
+var_decl:
+    LPAREN_TOK FORMID_TOK sort_symbs RPAREN_TOK
+    {
+      BEEV::_parser_symbol_table.insert(*$2);
+      //Sort_symbs has the indexwidth/valuewidth. Set those fields in
+      //var
+      $2->SetIndexWidth($3.indexwidth);
+      $2->SetValueWidth($3.valuewidth);
+    }
+   | LPAREN_TOK FORMID_TOK RPAREN_TOK
+    {
+      BEEV::_parser_symbol_table.insert(*$2);
+      //Sort_symbs has the indexwidth/valuewidth. Set those fields in
+      //var
+      $2->SetIndexWidth(0);
+      $2->SetValueWidth(0);
+    }
+;
+
+an_formulas:
+    an_formula
+    {
+      $$ = new BEEV::ASTVec;
+      if ($1 != NULL) {
+	$$->push_back(*$1);
+	delete $1;
+      }
+    }
+  |
+    an_formulas an_formula
+    {
+      if ($1 != NULL && $2 != NULL) {
+	$1->push_back(*$2);
+	$$ = $1;
+	delete $2;
+      }
+    }
+;
+
+an_formula:   
+    TRUE_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::TRUE)); 
+      $$->SetIndexWidth(0); 
+      $$->SetValueWidth(0);
+    }
+  | FALSE_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::FALSE)); 
+      $$->SetIndexWidth(0); 
+      $$->SetValueWidth(0);
+    }
+  | fvar
+    {
+      $$ = $1;
+    }
+  | LPAREN_TOK EQ_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK EQ_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateSimplifiedEQ(*$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVSLT_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVSLT_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLT, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVSLE_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVSLE_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSLE, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVSGT_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVSGT_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGT, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVSGE_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVSGE_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVSGE, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVLT_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVLT_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLT, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVLE_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVLE_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVLE, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVGT_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVGT_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGT, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK BVGE_TOK an_term an_term RPAREN_TOK
+  //| LPAREN_TOK BVGE_TOK an_term an_term annotations RPAREN_TOK
+    {
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::BVGE, *$3, *$4));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $3;
+      delete $4;      
+    }
+  | LPAREN_TOK an_formula RPAREN_TOK
+    {
+      $$ = $2;
+    }
+  | LPAREN_TOK NOT_TOK an_formula RPAREN_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::NOT, *$3));
+      delete $3;
+    }
+  | LPAREN_TOK IMPLIES_TOK an_formula an_formula RPAREN_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IMPLIES, *$3, *$4));
+      delete $3;
+      delete $4;
+    }
+  | LPAREN_TOK IF_THEN_ELSE_TOK an_formula an_formula an_formula RPAREN_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::ITE, *$3, *$4, *$5));
+      delete $3;
+      delete $4;
+      delete $5;
+    }
+  | LPAREN_TOK AND_TOK an_formulas RPAREN_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::AND, *$3));
+      delete $3;
+    }
+  | LPAREN_TOK OR_TOK an_formulas RPAREN_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::OR, *$3));
+      delete $3;
+    }
+  | LPAREN_TOK XOR_TOK an_formula an_formula RPAREN_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::XOR, *$3, *$4));
+      delete $3;
+      delete $4;
+    }
+  | LPAREN_TOK IFF_TOK an_formula an_formula RPAREN_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateNode(BEEV::IFF, *$3, *$4));
+      delete $3;
+      delete $4;
+    }
+  | letexpr_mgmt an_formula RPAREN_TOK
+  //| letexpr_mgmt an_formula annotations RPAREN_TOK
+    {
+      $$ = $2;
+      //Cleanup the LetIDToExprMap
+      BEEV::globalBeevMgr_for_parser->CleanupLetIDMap();			 
+    }
+;
+
+letexpr_mgmt: 
+    LPAREN_TOK LET_TOK LPAREN_TOK QUESTION_TOK FORMID_TOK an_term RPAREN_TOK
+    {
+     //Expr must typecheck
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$6);
+      
+      //set the valuewidth of the identifier
+      $5->SetValueWidth($6->GetValueWidth());
+      $5->SetIndexWidth($6->GetIndexWidth());
+      
+      //populate the hashtable from LET-var -->
+      //LET-exprs and then process them:
+      //
+      //1. ensure that LET variables do not clash
+      //1. with declared variables.
+      //
+      //2. Ensure that LET variables are not
+      //2. defined more than once
+      BEEV::globalBeevMgr_for_parser->LetExprMgr(*$5,*$6);
+      delete $5;
+      delete $6;      
+   }
+ | LPAREN_TOK FLET_TOK LPAREN_TOK DOLLAR_TOK FORMID_TOK an_formula RPAREN_TOK 
+   {
+     //Expr must typecheck
+     BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$6);
+     
+     //set the valuewidth of the identifier
+     $5->SetValueWidth($6->GetValueWidth());
+     $5->SetIndexWidth($6->GetIndexWidth());
+     
+     //Do LET-expr management
+     BEEV::globalBeevMgr_for_parser->LetExprMgr(*$5,*$6);
+     delete $5;
+     delete $6;     
+   }
+
+/* an_terms: */
+/*     an_term */
+/*     { */
+/*     } */
+/*   | an_terms an_term */
+/*     { */
+/*     } */
+/* ; */
+
+an_term:
+    BVCONST_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(64, $1));
+    }
+  | BVCONST_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst($3, $1));
+    }
+  | an_nonbvconst_term
+  ;
+
+an_nonbvconst_term: 
+    BITCONST_TOK { $$ = $1; }
+  | var
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1));
+      delete $1;
+    }
+  | LPAREN_TOK an_term RPAREN_TOK
+  //| LPAREN_TOK an_term annotations RPAREN_TOK
+    {
+      $$ = $2;
+      //$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->SimplifyTerm(*$2));
+      //delete $2;
+    }
+  | LPAREN_TOK TERMID_TOK an_term RPAREN_TOK
+    {
+      //ARRAY READ
+      // valuewidth is same as array, indexwidth is 0.
+      BEEV::ASTNode in = *$2;
+      BEEV::ASTNode m = *$3;
+      unsigned int width = in.GetValueWidth();
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, in, m));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  | SELECT_TOK an_term an_term
+    {
+      //ARRAY READ
+      // valuewidth is same as array, indexwidth is 0.
+      BEEV::ASTNode array = *$2;
+      BEEV::ASTNode index = *$3;
+      unsigned int width = array.GetValueWidth();
+      BEEV::ASTNode * n = 
+	new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::READ, width, array, index));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  | STORE_TOK an_term an_term an_term
+    {
+      //ARRAY WRITE
+      unsigned int width = $4->GetValueWidth();
+      BEEV::ASTNode array = *$2;
+      BEEV::ASTNode index = *$3;
+      BEEV::ASTNode writeval = *$4;
+      BEEV::ASTNode write_term = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::WRITE,width,array,index,writeval);
+      write_term.SetIndexWidth($2->GetIndexWidth());
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(write_term);
+      BEEV::ASTNode * n = new BEEV::ASTNode(write_term);
+      $$ = n;
+      delete $2;
+      delete $3;
+      delete $4;
+    }
+/*   | BVEXTRACT_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK BVCONST_TOK */
+/*     { */
+/*       // This special case is when we have an extract on top of a constant bv, which happens */
+/*       // almost all the time in the smt syntax. */
+
+/*       // $3 is high, $5 is low.  They are ints (why not unsigned? See uintval) */
+/*       int hi  =  $3; */
+/*       int low =  $5; */
+/*       int width = hi - low + 1; */
+
+/*       if (width < 0) */
+/* 	yyerror("Negative width in extract"); */
+
+/*       unsigned long long int val = $7; */
+
+/*       // cut and past from BV32 const evaluator */
+
+/*       unsigned long long int mask1 = 0xffffffffffffffffLL; */
+
+/*       mask1 >>= 64-(hi+1); */
+      
+/*       //extract val[hi:0] */
+/*       val &= mask1; */
+/*       //extract val[hi:low] */
+/*       val >>= low; */
+
+/*       // val is the desired BV32. */
+/*       BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(width, val)); */
+/*       $$ = n; */
+/*     } */
+  | BVEXTRACT_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK an_term
+    {
+      int width = $3 - $5 + 1;
+      if (width < 0)
+	yyerror("Negative width in extract");
+      
+      if((unsigned)$3 >= $7->GetValueWidth() || (unsigned)$5 < 0)
+	yyerror("Parsing: Wrong width in BVEXTRACT\n");			 
+      
+      BEEV::ASTNode hi  =  BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $3);
+      BEEV::ASTNode low =  BEEV::globalBeevMgr_for_parser->CreateBVConst(32, $5);
+      BEEV::ASTNode output = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT, width, *$7,hi,low);
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->SimplifyTerm(output));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $7;
+    }
+  |  ITE_TOK an_formula an_term an_term 
+    {
+      unsigned int width = $3->GetValueWidth();
+      if (width != $4->GetValueWidth()) {
+	cerr << *$3;
+	cerr << *$4;
+	yyerror("Width mismatch in IF-THEN-ELSE");
+      }			 
+      if($3->GetIndexWidth() != $4->GetIndexWidth())
+	yyerror("Width mismatch in IF-THEN-ELSE");
+      
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$2);
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$3);
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$4);
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateSimplifiedTermITE(*$2, *$3, *$4));
+      //$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::ITE,width,*$2, *$3, *$4));
+      $$->SetIndexWidth($4->GetIndexWidth());
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$$);
+      delete $2;
+      delete $3;
+      delete $4;
+    }
+  |  BVCONCAT_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth() + $3->GetValueWidth();
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, width, *$2, *$3));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      
+      delete $2;
+      delete $3;
+    }
+  |  BVNOT_TOK an_term
+    {
+      //this is the BVNEG (term) in the CVCL language
+      unsigned int width = $2->GetValueWidth();
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNEG, width, *$2));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+    }
+  |  BVNEG_TOK an_term
+    {
+      //this is the BVUMINUS term in CVCL langauge
+      unsigned width = $2->GetValueWidth();
+      BEEV::ASTNode * n =  new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVUMINUS,width,*$2));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+    }
+  |  BVAND_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in AND");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVAND, width, *$2, *$3));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  |  BVOR_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in OR");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVOR, width, *$2, *$3)); 
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  |  BVXOR_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in XOR");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVXOR, width, *$2, *$3));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  |  BVSUB_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in BVSUB");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSUB, width, *$2, *$3));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  |  BVPLUS_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in BVPLUS");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVPLUS, width, *$2, *$3));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+
+    }
+  |  BVMULT_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in BVMULT");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVMULT, width, *$2, *$3));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  |  BVNAND_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in BVNAND");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNAND, width, *$2, *$3));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  |  BVNOR_TOK an_term an_term 
+    {
+      unsigned int width = $2->GetValueWidth();
+      if (width != $3->GetValueWidth()) {
+	yyerror("Width mismatch in BVNOR");
+      }
+      BEEV::ASTNode * n = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVNOR, width, *$2, *$3)); 
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $2;
+      delete $3;
+    }
+  |  BVLEFTSHIFT_TOK an_term NUMERAL_TOK 
+    {
+      unsigned int w = $2->GetValueWidth();
+      if((unsigned)$3 < w) {
+	BEEV::ASTNode trailing_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst($3, 0);
+	BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, w-$3-1);
+	BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,0);
+	BEEV::ASTNode m = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$2,hi,low);
+	BEEV::ASTNode * n = 
+	  new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,w,m,trailing_zeros));
+	BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+	$$ = n;
+      }
+      else
+	$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+      delete $2;
+    }
+   |  BVLEFTSHIFT_1_TOK an_term an_term 
+    {
+      unsigned int w = $2->GetValueWidth();
+      unsigned int shift_amt = GetUnsignedConst(*$3);
+      if((unsigned)shift_amt < w) {
+	BEEV::ASTNode trailing_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst(shift_amt, 0);
+	BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32, w-shift_amt-1);
+	BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,0);
+	BEEV::ASTNode m = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-shift_amt,*$2,hi,low);
+	BEEV::ASTNode * n = 
+	  new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT,w,m,trailing_zeros));
+	BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+	$$ = n;
+      }
+      else {
+	$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+      }
+      delete $2;
+      //delete $3;
+    }
+  |  BVRIGHTSHIFT_TOK an_term NUMERAL_TOK 
+    {
+      BEEV::ASTNode leading_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst($3, 0);
+      unsigned int w = $2->GetValueWidth();
+      
+      //the amount by which you are rightshifting
+      //is less-than/equal-to the length of input
+      //bitvector
+      if((unsigned)$3 < w) {
+	BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1);
+	BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,$3);
+	BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-$3,*$2,hi,low);
+	BEEV::ASTNode * n = 
+	  new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,leading_zeros, extract));
+	BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+	$$ = n;
+      }
+      else {
+	$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+      }
+      delete $2;
+    }
+   |  BVRIGHTSHIFT_1_TOK an_term an_term 
+    {
+      unsigned int shift_amt = GetUnsignedConst(*$3);
+      BEEV::ASTNode leading_zeros = BEEV::globalBeevMgr_for_parser->CreateBVConst(shift_amt, 0);
+      unsigned int w = $2->GetValueWidth();
+      
+      //the amount by which you are rightshifting
+      //is less-than/equal-to the length of input
+      //bitvector
+      if((unsigned)shift_amt < w) {
+	BEEV::ASTNode hi = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w-1);
+	BEEV::ASTNode low = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,shift_amt);
+	BEEV::ASTNode extract = BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVEXTRACT,w-shift_amt,*$2,hi,low);
+	BEEV::ASTNode * n = 
+	  new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVCONCAT, w,leading_zeros, extract));
+	BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+	$$ = n;
+      }
+      else {
+	$$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateBVConst(w,0));
+      }
+      delete $2;
+    }
+  |  BVSX_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK an_term 
+    {
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*$5);
+      unsigned w = $5->GetValueWidth() + $3;
+      BEEV::ASTNode width = BEEV::globalBeevMgr_for_parser->CreateBVConst(32,w);
+      BEEV::ASTNode *n =  new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->CreateTerm(BEEV::BVSX,w,*$5,width));
+      BEEV::globalBeevMgr_for_parser->BVTypeCheck(*n);
+      $$ = n;
+      delete $5;
+    }
+;
+  
+sort_symb:
+    BITVEC_TOK LBRACKET_TOK NUMERAL_TOK RBRACKET_TOK
+    {
+      // Just return BV width.  If sort is BOOL, width is 0.
+      // Otherwise, BITVEC[w] returns w. 
+      //
+      //((indexwidth is 0) && (valuewidth>0)) iff type is BV
+      $$.indexwidth = 0;
+      unsigned int length = $3;
+      if(length > 0) {
+	$$.valuewidth = length;
+      }
+      else {
+	BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+      }
+    }
+   | ARRAY_TOK LBRACKET_TOK NUMERAL_TOK COLON_TOK NUMERAL_TOK RBRACKET_TOK
+    {
+      unsigned int index_len = $3;
+      unsigned int value_len = $5;
+      if(index_len > 0) {
+	$$.indexwidth = $3;
+      }
+      else {
+	BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+      }
+
+      if(value_len > 0) {
+	$$.valuewidth = $5;
+      }
+      else {
+	BEEV::FatalError("Fatal Error: parsing: BITVECTORS must be of positive length: \n");
+      }
+    }
+;
+
+var:
+    FORMID_TOK 
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); 
+      delete $1;      
+    }
+   | TERMID_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1));
+      delete $1;
+    }
+   | QUESTION_TOK TERMID_TOK
+    {
+      $$ = $2;
+    }
+;
+
+fvar:
+    DOLLAR_TOK FORMID_TOK
+    {
+      $$ = $2; 
+    }
+  | FORMID_TOK
+    {
+      $$ = new BEEV::ASTNode(BEEV::globalBeevMgr_for_parser->ResolveID(*$1)); 
+      delete $1;      
+    }   
+;
+%%
diff --git a/stp/sat/Global.h b/stp/sat/Global.h
new file mode 100644
index 00000000..a428975c
--- /dev/null
+++ b/stp/sat/Global.h
@@ -0,0 +1,255 @@
+/****************************************************************************************[Global.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Global_h
+#define Global_h
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <new>
+
+// PKT: needs to be outside namespace MINISAT or mac os x compilation breaks
+#ifdef _MSC_VER
+#else
+#include <unistd.h>
+#endif
+
+namespace MINISAT {
+//=================================================================================================
+// Basic Types & Minor Things:
+
+// DWD: This is needed on darwin.
+typedef unsigned int uint;
+
+#ifdef _MSC_VER
+
+typedef INT64              int64;
+typedef UINT64             uint64;
+typedef INT_PTR            intp;
+typedef UINT_PTR           uintp;
+#define I64_fmt "I64d"
+#else
+
+typedef long long          int64;
+typedef unsigned long long uint64;
+typedef __PTRDIFF_TYPE__   intp;
+typedef unsigned __PTRDIFF_TYPE__ uintp;
+#define I64_fmt "lld"
+#endif
+
+template<class T> static inline T min(T x, T y) { return (x < y) ? x : y; }
+template<class T> static inline T max(T x, T y) { return (x > y) ? x : y; }
+
+template <bool> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true>{};
+#define TEMPLATE_FAIL STATIC_ASSERTION_FAILURE<false>()
+
+
+//=================================================================================================
+// 'malloc()'-style memory allocation -- never returns NULL; aborts instead:
+
+
+template<class T> static inline T* xmalloc(size_t size) {
+    T*   tmp = (T*)malloc(size * sizeof(T));
+    assert(size == 0 || tmp != NULL);
+    return tmp; }
+
+template<class T> static inline T* xrealloc(T* ptr, size_t size) {
+    T*   tmp = (T*)realloc((void*)ptr, size * sizeof(T));
+    assert(size == 0 || tmp != NULL);
+    return tmp; }
+
+template<class T> static inline void xfree(T *ptr) {
+    if (ptr != NULL) free((void*)ptr); }
+
+
+//=================================================================================================
+// Random numbers:
+
+
+// Returns a random float 0 <= x < 1. Seed must never be 0.
+static inline double drand(double& seed) {
+    seed *= 1389796;
+    int q = (int)(seed / 2147483647);
+    seed -= (double)q * 2147483647;
+    return seed / 2147483647; }
+
+// Returns a random integer 0 <= x < size. Seed must never be 0.
+static inline int irand(double& seed, int size) {
+    return (int)(drand(seed) * size); }
+
+
+//=================================================================================================
+// 'vec' -- automatically resizable arrays (via 'push()' method):
+
+
+// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc)
+
+template<class T>
+class vec {
+    T*  data;
+    int sz;
+    int cap;
+
+    void     init(int size, const T& pad);
+    void     grow(int min_cap);
+
+public:
+    // Types:
+    typedef int Key;
+    typedef T   Datum;
+
+    // Constructors:
+    vec(void)                   : data(NULL) , sz(0)   , cap(0)    { }
+    vec(int size)               : data(NULL) , sz(0)   , cap(0)    { growTo(size); }
+    vec(int size, const T& pad) : data(NULL) , sz(0)   , cap(0)    { growTo(size, pad); }
+    vec(T* array, int size)     : data(array), sz(size), cap(size) { }      // (takes ownership of array -- will be deallocated with 'xfree()')
+   ~vec(void)                                                      { clear(true); }
+
+    // Ownership of underlying array:
+    T*       release  (void)           { T* ret = data; data = NULL; sz = 0; cap = 0; return ret; }
+    operator T*       (void)           { return data; }     // (unsafe but convenient)
+    operator const T* (void) const     { return data; }
+
+    // Size operations:
+    int      size   (void) const       { return sz; }
+    void     shrink (int nelems)       { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); }
+    void     pop    (void)             { sz--, data[sz].~T(); }
+    void     growTo (int size);
+    void     growTo (int size, const T& pad);
+    void     clear  (bool dealloc = false);
+    void     capacity (int size) { grow(size); }
+
+    // Stack interface:
+    void     push  (void)              { if (sz == cap) grow(sz+1); new (&data[sz]) T()    ; sz++; }
+    void     push  (const T& elem)     { if (sz == cap) grow(sz+1); new (&data[sz]) T(elem); sz++; }
+    const T& last  (void) const        { return data[sz-1]; }
+    T&       last  (void)              { return data[sz-1]; }
+
+    // Vector interface:
+    const T& operator [] (int index) const  { return data[index]; }
+    T&       operator [] (int index)        { return data[index]; }
+
+    // Don't allow copying (error prone):
+    vec<T>&  operator = (vec<T>& other) { TEMPLATE_FAIL; }
+             vec        (vec<T>& other) { TEMPLATE_FAIL; }
+
+    // Duplicatation (preferred instead):
+    void copyTo(vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) new (&copy[i]) T(data[i]); }
+    void moveTo(vec<T>& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; }
+};
+
+template<class T>
+void vec<T>::grow(int min_cap) {
+    if (min_cap <= cap) return;
+    if (cap == 0) cap = (min_cap >= 2) ? min_cap : 2;
+    else          do cap = (cap*3+1) >> 1; while (cap < min_cap);
+    data = xrealloc(data, cap); }
+
+template<class T>
+void vec<T>::growTo(int size, const T& pad) {
+    if (sz >= size) return;
+    grow(size);
+    for (int i = sz; i < size; i++) new (&data[i]) T(pad);
+    sz = size; }
+
+template<class T>
+void vec<T>::growTo(int size) {
+    if (sz >= size) return;
+    grow(size);
+    for (int i = sz; i < size; i++) new (&data[i]) T();
+    sz = size; }
+
+template<class T>
+void vec<T>::clear(bool dealloc) {
+    if (data != NULL){
+        for (int i = 0; i < sz; i++) data[i].~T();
+        sz = 0;
+        if (dealloc) xfree(data), data = NULL, cap = 0; } }
+
+
+//=================================================================================================
+// Useful functions on vectors
+
+
+template<class V, class T>
+void remove(V& ts, const T& t)
+{
+    int j = 0;
+    for (; j < ts.size() && ts[j] != t; j++);
+    assert(j < ts.size());
+    for (; j < ts.size()-1; j++) ts[j] = ts[j+1];
+    ts.pop();
+}
+
+
+template<class V, class T>
+bool find(V& ts, const T& t)
+{
+    int j = 0;
+    for (; j < ts.size() && ts[j] != t; j++);
+    return j < ts.size();
+}
+
+//=================================================================================================
+// Lifted booleans:
+
+
+class lbool {
+    int     value;
+    explicit lbool(int v) : value(v) { }
+
+public:
+    lbool()       : value(0) { }
+    lbool(bool x) : value((int)x*2-1) { }
+    int toInt(void) const { return value; }
+
+    bool  operator == (const lbool& other) const { return value == other.value; }
+    bool  operator != (const lbool& other) const { return value != other.value; }
+    lbool operator ~  (void)               const { return lbool(-value); }
+
+    friend int   toInt  (lbool l);
+    friend lbool toLbool(int   v);
+};
+inline int   toInt  (lbool l) { return l.toInt(); }
+inline lbool toLbool(int   v) { return lbool(v);  }
+
+const lbool l_True  = toLbool( 1);
+const lbool l_False = toLbool(-1);
+const lbool l_Undef = toLbool( 0);
+
+
+//=================================================================================================
+// Relation operators -- extend definitions from '==' and '<'
+
+
+#ifndef __SGI_STL_INTERNAL_RELOPS   // (be aware of SGI's STL implementation...)
+#define __SGI_STL_INTERNAL_RELOPS
+template <class T> static inline bool operator != (const T& x, const T& y) { return !(x == y); }
+template <class T> static inline bool operator >  (const T& x, const T& y) { return y < x;     }
+template <class T> static inline bool operator <= (const T& x, const T& y) { return !(y < x);  }
+template <class T> static inline bool operator >= (const T& x, const T& y) { return !(x < y);  }
+#endif
+
+
+//=================================================================================================
+};
+#endif
diff --git a/stp/sat/Heap.h b/stp/sat/Heap.h
new file mode 100644
index 00000000..acfa1c1e
--- /dev/null
+++ b/stp/sat/Heap.h
@@ -0,0 +1,151 @@
+/******************************************************************************************[Heap.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Heap_h
+#define Heap_h
+
+#include "../AST/ASTUtil.h"
+namespace MINISAT {
+
+//=================================================================================================
+
+
+static inline int left  (int i) { return i+i; }
+static inline int right (int i) { return i+i + 1; }
+static inline int parent(int i) { return i >> 1; }
+
+template<class C>
+class Heap {
+  public:
+    C        comp;
+    vec<int> heap;     // heap of ints
+    vec<int> indices;  // int -> index in heap
+
+    inline void percolateUp(int i)
+    {
+        int x = heap[i];
+        while (parent(i) != 0 && comp(x,heap[parent(i)])){
+            heap[i]          = heap[parent(i)];
+            indices[heap[i]] = i;
+            i                = parent(i);
+        }
+        heap   [i] = x;
+        indices[x] = i;
+    }
+
+    inline void percolateDown(int i)
+    {
+        int x = heap[i];
+        while (left(i) < heap.size()){
+            int child = right(i) < heap.size() && comp(heap[right(i)],heap[left(i)]) ? right(i) : left(i);
+            if (!comp(heap[child],x)) break;
+            heap[i]          = heap[child];
+            indices[heap[i]] = i;
+            i                = child;
+        }
+        heap   [i] = x;
+        indices[x] = i;
+    }
+
+    bool ok(int n) const { 
+        return n >= 0 && n < (int)indices.size(); }
+
+  public:
+    Heap(C c) : comp(c) { heap.push(-1); }
+
+    void setBounds (int size)    { assert(size >= 0); indices.growTo(size,0); }
+    void increase  (int n)       { assert(ok(n)); assert(inHeap(n)); percolateUp(indices[n]); }
+    bool inHeap    (int n) const { assert(ok(n)); return indices[n] != 0; }
+    int  size      ()      const { return heap.size()-1; }
+    bool empty     ()      const { return size() == 0; }
+
+
+    void insert(int n) {
+        assert(!inHeap(n));
+        assert(ok(n));
+        indices[n] = heap.size();
+        heap.push(n);
+        percolateUp(indices[n]); 
+    }
+
+
+  int  getmin() {
+    //printing heap
+    if(BEEV::print_sat_varorder) {
+      // fprintf(stderr, "Vijay: heap before getmin: ");
+      //       for (uint i = 1; i < (uint)heap.size(); i++)
+      // 	fprintf(stderr, "%d ", heap[i]);
+      //       fprintf(stderr, "\n");
+    }
+    
+    int r            = heap[1];
+    heap[1]          = heap.last();
+    indices[heap[1]] = 1;
+    indices[r]       = 0;
+    heap.pop();
+    if (heap.size() > 1)
+      percolateDown(1);
+    return r; 
+  }
+
+    // fool proof variant of insert/increase
+    void update    (int n)    {
+        //fprintf(stderr, "update heap: ");
+        //for (uint i = 1; i < (uint)heap.size(); i++)
+        //    fprintf(stderr, "%d ", heap[i]);
+        //fprintf(stderr, "\n");
+        setBounds(n+1);
+        if (!inHeap(n))
+            insert(n);
+        else {
+            percolateUp(indices[n]);
+            percolateDown(indices[n]);
+        }
+    }
+
+
+    bool heapProperty() {
+        return heapProperty(1); }
+
+
+    bool heapProperty(int i) {
+        return i >= heap.size()
+            || ((parent(i) == 0 || !comp(heap[i],heap[parent(i)])) && heapProperty(left(i)) && heapProperty(right(i))); }
+
+    template <class F> void filter(const F& filt) {
+        int i,j;
+        for (i = j = 1; i < heap.size(); i++)
+            if (filt(heap[i])){
+                heap[j]          = heap[i];
+                indices[heap[i]] = j++;
+            }else
+                indices[heap[i]] = 0;
+
+        heap.shrink(i - j);
+        for (int i = heap.size() / 2; i >= 1; i--)
+            percolateDown(i);
+
+        assert(heapProperty());
+    }
+
+};
+
+//=================================================================================================
+};
+#endif
diff --git a/stp/sat/LICENSE b/stp/sat/LICENSE
new file mode 100644
index 00000000..590930bc
--- /dev/null
+++ b/stp/sat/LICENSE
@@ -0,0 +1,20 @@
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/stp/sat/Makefile b/stp/sat/Makefile
new file mode 100644
index 00000000..8298e05a
--- /dev/null
+++ b/stp/sat/Makefile
@@ -0,0 +1,16 @@
+include ../Makefile.common
+
+SRCS = Solver.C Simplifier.C
+OBJS = $(SRCS:.C=.o)
+
+libsatsolver.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+Solver.o: Solver.C Solver.h Sort.h SolverTypes.h VarOrder.h Global.h Heap.h
+Simplifier.o: Simplifier.C Solver.h Sort.h SolverTypes.h VarOrder.h Global.h Heap.h
+
+clean:
+	rm -rf *.o *~  *.a  depend.mak .#*
+depend:
+	makedepend -- $(CFLAGS) -- $(SRCS)
diff --git a/stp/sat/Simplifier.C b/stp/sat/Simplifier.C
new file mode 100644
index 00000000..1c192e20
--- /dev/null
+++ b/stp/sat/Simplifier.C
@@ -0,0 +1,542 @@
+/************************************************************************************[Simplifier.C]
+MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#include "Solver.h"
+
+namespace MINISAT {
+
+static const int grow = 0;
+
+//#define WEAKEN
+//#define MATING
+//#define ASSYMM
+
+bool Solver::assymmetricBranching(Clause& c)
+{
+    assert(decisionLevel() == 0);
+
+    //fprintf(stderr, "assymmetric branching on clause: "); printClause(c); fprintf(stderr, "\n");
+    if (satisfied(c)){
+        //fprintf(stderr, "subsumed.\n");
+        return true; }
+
+    int      old;
+    vec<Lit> copy; for (int i = 0; i < c.size(); i++) copy.push(c[i]);
+
+    do {
+        assert(copy.size() == c.size());
+
+        old = copy.size();
+
+        //fprintf(stderr, "checking that clause is normalized\n");
+        //for (int i = 0; i < copy.size(); i++)
+        //    assert(value(copy[i]) == l_Undef);
+
+        for (int i = 0; i < copy.size(); i++){
+            trail_lim.push(trail.size());
+            //fprintf(stderr, " -- trying to delete literal "); printLit(copy[i]); 
+            for (int j = 0; j < copy.size(); j++)
+                if (j != i)
+                    check(enqueue(~copy[j]));
+
+            if (propagate() != NULL){
+                //fprintf(stderr, " succeeded\n");
+                cancelUntil(0);
+                Lit l = copy[i];
+                assert(find(copy, l));
+                remove(copy, l);
+                if (!strengthen(c, l))
+                    return false;
+                i--;
+
+                if (c.size() == 1)
+                    return propagate() == NULL;
+                else
+                    assert(qhead == trail.size());
+            }
+            else
+                //fprintf(stderr, " failed\n");
+
+            cancelUntil(0);
+        }
+
+        //} while (false);
+    } while (copy.size() < old);
+
+    return true;
+}
+
+// Returns FALSE if clause is always satisfied ('out_clause' should not be used). 
+//bool Solver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
+bool Solver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
+{  
+    stats.merges++;
+
+    bool  ps_smallest = _ps.size() < _qs.size();
+    const Clause& ps =  ps_smallest ? _qs : _ps;
+    const Clause& qs =  ps_smallest ? _ps : _qs;
+
+    for (int i = 0; i < qs.size(); i++){
+        if (var(qs[i]) != v){
+            for (int j = 0; j < ps.size(); j++)
+                if (var(ps[j]) == var(qs[i])) {
+                    if (ps[j] == ~qs[i])
+                        return false;
+                    else
+                        goto next;
+                }
+            out_clause.push(qs[i]);
+        }
+        next:;
+    }
+
+    for (int i = 0; i < ps.size(); i++)
+        if (var(ps[i]) != v)
+            out_clause.push(ps[i]);
+
+    return true;
+}
+
+
+void Solver::gather(vec<Clause*>& clauses)
+{
+    //fprintf(stderr, "Gathering clauses for backwards subsumption\n");
+    int ntouched = 0;
+    assert(touched.size() == occurs.size());
+    clauses.clear();
+    for (int i = 0; i < touched.size(); i++)
+        if (touched[i]){
+            const vec<Clause*>& cs = getOccurs(i);
+            ntouched++;
+            for (int j = 0; j < cs.size(); j++)
+                if (cs[j]->mark() == 0){
+                    clauses.push(cs[j]);
+                    cs[j]->mark(2);
+                }
+            touched[i] = 0;
+        }
+
+    //fprintf(stderr, "Touched variables %d of %d yields %d clauses to check\n", ntouched, touched.size(), clauses.size());
+    for (int i = 0; i < clauses.size(); i++)
+        clauses[i]->mark(0);
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  subsumes : (_c : ClauseId) (c : Clause&) (_d : ClauseId) (d : Clause&)  ->  bool
+|
+|  Description:
+|     Checks if c subsumes d, and at the same time, if c can be used to simplify d by subsumption
+|     resolution.
+|    
+|  Input:
+|     Indices into the 'clauses' vector _c, _d, and references to the corresponding clauses c, d.
+|
+|  Result:
+|     lit_Error  - No subsumption or simplification
+|     lit_Undef  - Clause c subsumes d
+|     l          - The literal l can be deleted from d
+|________________________________________________________________________________________________@*/
+inline Lit Solver::subsumes(const Clause& c, const Clause& d)
+{
+    stats.subsumption_checks++;
+    if (d.size() < c.size() || (c.abstraction() & ~d.abstraction()) != 0)
+        return lit_Error;
+
+    Lit ret = lit_Undef;
+
+    for (int i = 0; i < c.size(); i++) {
+        // search for c[i] or ~c[i]
+        for (int j = 0; j < d.size(); j++)
+            if (c[i] == d[j])
+                goto ok;
+            else if (ret == lit_Undef && c[i] == ~d[j]){
+                ret = c[i];
+                goto ok;
+            }
+
+        // did not find it
+        stats.subsumption_misses++;
+        return lit_Error;
+    ok:;
+    }
+
+    return ret;
+}
+
+
+// Backward subsumption + backward subsumption resolution
+bool Solver::backwardSubsumptionCheck()
+{
+    while (subsumption_queue.size() > 0 || qhead < trail.size()){
+
+        // if propagation queue is non empty, take the first literal and
+        // create a dummy unit clause
+        if (qhead < trail.size()){
+            Lit l = trail[qhead++];
+            (*bwdsub_tmpunit)[0] = l;
+            assert(bwdsub_tmpunit->mark() == 0);
+            subsumption_queue.push(bwdsub_tmpunit);
+        }
+        Clause&  c = *subsumption_queue.last(); subsumption_queue.pop();
+
+        if (c.mark())
+            continue;
+
+        if (c.size() == 1 && !enqueue(c[0]))
+            return false; 
+
+        // (1) find best variable to scan
+        Var best = var(c[0]);
+        for (int i = 1; i < c.size(); i++)
+            if (occurs[var(c[i])].size() < occurs[best].size())
+                best = var(c[i]);
+
+        // (2) search all candidates
+        const vec<Clause*>& cs = getOccurs(best);
+
+        for (int j = 0; j < cs.size(); j++)
+            if (cs[j] != &c){
+                if (cs[j]->mark())
+                    continue;
+                if (c.mark())
+                    break;
+
+                //fprintf(stderr, "backward candidate "); printClause(*cs[j]); fprintf(stderr, "\n"); 
+                Lit l = subsumes(c, *cs[j]);
+                if (l == lit_Undef){
+                    //fprintf(stderr, "clause backwards subsumed\n");
+                    //fprintf(stderr, " >> clause %d: ", cs[j]->mark()); printClause(*cs[j]); fprintf(stderr, "\n");
+                    //fprintf(stderr, " >> clause %d: ", c.mark()); printClause(c); fprintf(stderr, "\n");
+                    removeClause(*cs[j], false);
+                }else if (l != lit_Error){
+                    //fprintf(stderr, "backwards subsumption resolution\n");
+                    //fprintf(stderr, " >> clause %d: ", cs[j]->mark()); printClause(*cs[j]); fprintf(stderr, "\n");
+                    //fprintf(stderr, " >> clause %d: ", c.mark()); printClause(c); fprintf(stderr, "\n");
+
+                    assert(cs[j]->size() > 1);
+                    assert(find(*cs[j], ~l));
+
+                    subsumption_queue.push(cs[j]);
+                    if (!strengthen(*cs[j], ~l))
+                        return false;
+
+                    // did current candidate get deleted from cs? then check candidate at index j again
+                    if (var(l) == best)
+                        j--;
+                }
+            }
+    }
+
+    return true;
+}
+
+
+bool Solver::eliminateVar(Var v, bool fail)
+{
+    assert(hasVarProp(v, p_frozen));
+
+    vec<Clause*>  pos, neg;
+    const vec<Clause*>& cls = getOccurs(v);
+
+    if (value(v) != l_Undef || cls.size() == 0)
+        return true;
+
+    //fprintf(stderr, "trying to eliminate var %d\n", v+1);
+    for (int i = 0; i < cls.size(); i++){
+        //fprintf(stderr, "clause: "); printClause(*cls[i]); fprintf(stderr, "\n");
+        if (find(*cls[i], Lit(v)))
+            pos.push(cls[i]);
+        else{
+            assert(find(*cls[i], ~Lit(v)));
+            neg.push(cls[i]);
+        }
+    }
+
+#ifdef WEAKEN
+    vec<int> posc(pos.size(), 0);
+    vec<int> negc(neg.size(), 0);
+#endif
+    // check if number of clauses decreases
+    int      cnt = 0;
+    vec<Lit> resolvent;
+    for (int i = 0; i < pos.size(); i++)
+        for (int j = 0; j < neg.size(); j++){
+            resolvent.clear();
+            if (merge(*pos[i], *neg[j], v, resolvent)){
+                cnt++;
+#ifdef WEAKEN
+                posc[i]++;
+                negc[j]++;
+#endif
+            }
+#ifndef WEAKEN
+            if (cnt > cls.size() + grow)
+                return true;
+#else
+#ifdef MATING
+            if (cnt > cls.size() + grow)
+                if (posc[i] > 0)
+                    break;
+#endif
+#endif
+            assert(pos.size() <= n_occ[toInt(Lit(v))]);
+            assert(neg.size() <= n_occ[toInt(~Lit(v))]);
+        }
+
+#ifdef WEAKEN
+#ifdef MATING
+    for (int i = 0; i < neg.size(); i++)
+        if (negc[i] == 0)
+            for (int j = 0; j < pos.size(); j++){
+                resolvent.clear();
+                if (merge(*neg[i], *pos[j], v, resolvent)){
+                    negc[i]++;
+                    break;
+                }
+            }
+#endif
+    for (int i = 0; i < pos.size(); i++)
+        if (posc[i] == 0)
+            removeClause(*pos[i], false);
+
+    for (int i = 0; i < neg.size(); i++)
+        if (negc[i] == 0)
+            removeClause(*neg[i], false);
+
+    if (cnt > cls.size() + grow)
+        return true;
+#endif    
+    //if (pos.size() != n_occ[toInt(Lit(v))])
+    //    fprintf(stderr, "pos.size() = %d, n_occ[toInt(Lit(v))] = %d\n", pos.size(), n_occ[toInt(Lit(v))]);
+    assert(pos.size() == n_occ[toInt(Lit(v))]);
+    //if (neg.size() != n_occ[toInt(~Lit(v))])
+    //    fprintf(stderr, "neg.size() = %d, n_occ[toInt(Lit(v))] = %d\n", neg.size(), n_occ[toInt(Lit(v))]);
+    assert(neg.size() == n_occ[toInt(~Lit(v))]);
+    assert(cnt <= cls.size() + grow);
+    setVarProp(v, p_decisionvar, false);
+
+    // produce clauses in cross product
+    int top = clauses.size();
+    for (int i = 0; i < pos.size(); i++)
+        for (int j = 0; j < neg.size(); j++){
+            resolvent.clear();
+#ifdef WEAKEN
+            if (pos[i]->mark() == 1)
+                break;
+            if (neg[j]->mark() == 1)
+                continue;
+#endif
+
+            if (merge(*pos[i], *neg[j], v, resolvent)){
+                int i, j;
+                for (i = j = 0; i < resolvent.size(); i++)
+                    if (value(resolvent[i]) == l_True)
+                        goto next;
+                    else if (value(resolvent[i]) == l_Undef)
+                        resolvent[j++] = resolvent[i];
+                resolvent.shrink(i - j);
+
+                if (resolvent.size() == 1){
+                    if (!enqueue(resolvent[0]))
+                        return false;
+                }else{
+                    int apa = clauses.size();
+                    check(newClause(resolvent, false, true));
+                    assert(apa + 1 == clauses.size());
+                }
+            }
+            next:;
+        }
+
+    if (fail){
+        fprintf(stderr, "eliminated var %d, %d <= %d\n", v+1, cnt, cls.size());
+        fprintf(stderr, "previous clauses:\n");
+        for (int i = 0; i < cls.size(); i++){
+            printClause(*cls[i]);
+            fprintf(stderr, "\n");
+        }
+        
+        fprintf(stderr, "new clauses:\n");
+        for (int i = top; i < clauses.size(); i++){
+            printClause(*clauses[i]);
+            fprintf(stderr, "\n");
+        }
+
+        assert(0); }
+
+    //fprintf(stderr, "eliminated var %d, %d <= %d\n", v+1, cnt, cls.size());
+    //fprintf(stderr, "previous clauses:\n");
+    //for (int i = 0; i < cls.size(); i++){
+    //    printClause(*cls[i]);
+    //    fprintf(stderr, "\n");
+    //}
+    //
+    //fprintf(stderr, "new clauses:\n");
+    //for (int i = top; i < clauses.size(); i++){
+    //    printClause(*clauses[i]);
+    //    fprintf(stderr, "\n");
+    //}
+
+    // delete + store old clauses
+    eliminated_var.push(v);
+    eliminated_lim.push(eliminated.size());
+    for (int i = 0; i < cls.size(); i++){
+        eliminated.push(Clause_new(*cls[i]));
+
+#ifdef WEAKEN
+        if (cls[i]->mark() == 0)
+#endif
+            removeClause(*cls[i], false); 
+
+    }
+
+    assert(subsumption_queue.size() == 0);
+    for (int i = top; i < clauses.size(); i++)
+#ifdef ASSYMM
+        if (clauses[i]->mark() == 0)
+            if (!assymmetricBranching(*clauses[i]))
+                return false;
+            else
+                subsumption_queue.push(clauses[i]);
+#else
+        if (clauses[i]->mark() == 0)
+            subsumption_queue.push(clauses[i]);
+#endif
+
+    return backwardSubsumptionCheck();
+}
+
+
+void Solver::extendModel()
+{
+    assert(eliminated_var.size() == eliminated_lim.size());
+    for (int i = eliminated_var.size()-1; i >= 0; i--){
+        Var v = eliminated_var[i];
+        Lit l = lit_Undef;
+
+        //fprintf(stderr, "extending var %d\n", v+1);
+
+        for (int j = eliminated_lim[i]; j < (i+1 >= eliminated_lim.size() ? eliminated.size() : eliminated_lim[i+1]); j++){
+            assert(j < eliminated.size());
+            Clause& c = *eliminated[j];
+
+            //fprintf(stderr, "checking clause: "); printClause(c); fprintf(stderr, "\n");
+
+            for (int k = 0; k < c.size(); k++)
+                if (var(c[k]) == v)
+                    l = c[k];
+                else if (value(c[k]) != l_False)
+                    goto next;
+
+            assert(l != lit_Undef);
+            //fprintf(stderr, "Fixing var %d to %d\n", v+1, !sign(l));
+
+            assigns[v] = toInt(lbool(!sign(l)));
+            break;
+
+        next:;
+        }
+
+        if (value(v) == l_Undef)
+            assigns[v] = toInt(l_True);
+    }
+}
+
+
+bool Solver::eliminate()
+{
+    assert(subsumption);
+
+    int cnt = 0;
+    //fprintf(stderr, "eliminating variables\n");
+
+#ifdef INVARIANTS
+    // check that all clauses are simplified
+    fprintf(stderr, "Checking that all clauses are normalized prior to variable elimination\n");
+    for (int i = 0; i < clauses.size(); i++)
+        if (clauses[i]->mark() == 0){
+            Clause& c = *clauses[i];
+            for (int j = 0; j < c.size(); j++)
+                assert(value(c[j]) == l_Undef);
+        }
+    fprintf(stderr, "done.\n");
+#endif
+
+    for (;;){
+        gather(subsumption_queue);
+
+        if (subsumption_queue.size() == 0 && heap.size() == 0)
+            break;
+
+        //fprintf(stderr, "backwards subsumption: %10d\n", subsumption_queue.size());
+        if (!backwardSubsumptionCheck())
+            return false;
+
+        //fprintf(stderr, "variable elimination:  %10d\n", heap.size());
+        cnt = 0;
+        for (;;){
+            assert(!heap.empty() || heap.size() == 0);
+            if (heap.empty())
+                break;
+
+            Var elim = heap.getmin();
+
+            assert(hasVarProp(elim, p_frozen));
+
+            //for (int i = 1; i < heap.heap.size(); i++)
+            //    assert(heap.comp(elim, heap.heap[i]) || !heap.comp(elim, heap.heap[i]));
+
+            //if (cnt++ % 100 == 0)
+            //    fprintf(stderr, "left %10d\r", heap.size());
+            
+            if (!eliminateVar(elim))
+                return false;
+        }
+    }
+#ifdef INVARIANTS
+    // check that no more subsumption is possible
+    fprintf(stderr, "Checking that no more subsumption is possible\n");
+    cnt = 0;
+    for (int i = 0; i < clauses.size(); i++){
+        if (cnt++ % 1000 == 0)
+            fprintf(stderr, "left %10d\r", clauses.size() - i);
+        for (int j = 0; j < i; j++)
+            assert(clauses[i]->mark() ||
+                   clauses[j]->mark() ||
+                   subsumes(*clauses[i], *clauses[j]) == lit_Error);
+    }
+    fprintf(stderr, "done.\n");
+
+    // check that no more elimination is possible
+    fprintf(stderr, "Checking that no more elimination is possible\n");
+    for (int i = 0; i < nVars(); i++){
+        if (hasVarProp(i, p_frozen))
+            eliminateVar(i, true);
+    }
+    fprintf(stderr, "done.\n");
+
+#endif
+
+    assert(qhead == trail.size());
+
+    return true;
+}
+};
diff --git a/stp/sat/Solver.C b/stp/sat/Solver.C
new file mode 100644
index 00000000..0fcb6149
--- /dev/null
+++ b/stp/sat/Solver.C
@@ -0,0 +1,811 @@
+/****************************************************************************************[Solver.C]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#include "Solver.h"
+#include "Sort.h"
+#include <cmath>
+
+namespace MINISAT {
+//=================================================================================================
+// Operations on clauses:
+
+
+/*_________________________________________________________________________________________________
+|
+|  newClause : (ps : const vec<Lit>&) (learnt : bool)  ->  [void]
+|  
+|  Description:
+|    Allocate and add a new clause to the SAT solvers clause database. 
+|  
+|  Input:
+|    ps     - The new clause as a vector of literals.
+|    learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the
+|             asserting literal. An appropriate 'enqueue()' operation will be performed on this
+|             literal. One of the watches will always be on this literal, the other will be set to
+|             the literal with the highest decision level.
+|  
+|  Effect:
+|    Activity heuristics are updated.
+|________________________________________________________________________________________________@*/
+bool Solver::newClause(const vec<Lit>& ps_, bool learnt, bool normalized)
+{
+    vec<Lit>    qs;
+    if (!learnt && !normalized){
+        assert(decisionLevel() == 0);
+        ps_.copyTo(qs);             // Make a copy of the input vector.
+
+        // Remove duplicates:
+        sortUnique(qs);
+
+        // Check if clause is satisfied:
+        for (int i = 0; i < qs.size()-1; i++){
+            if (qs[i] == ~qs[i+1])
+                return true; }
+        for (int i = 0; i < qs.size(); i++){
+            if (value(qs[i]) == l_True)
+                return true; }
+
+        // Remove false literals:
+        int     i, j;
+        for (i = j = 0; i < qs.size(); i++)
+            if (value(qs[i]) != l_False)
+                qs[j++] = qs[i];
+        qs.shrink(i - j);
+    }
+    const vec<Lit>& ps = learnt || normalized ? ps_ : qs;     // 'ps' is now the (possibly) reduced vector of literals.
+
+    if (ps.size() == 0)
+        return false;
+    else if (ps.size() == 1){
+        assert(decisionLevel() == 0);
+        return enqueue(ps[0]);
+    }else{
+        // Allocate clause:
+        Clause* c   = Clause_new(ps, learnt);
+
+        if (learnt){
+            // Put the second watch on the first literal with highest decision level:
+            // (requires that this method is called at the level where the clause is asserting!)
+            int i;
+            for (i = 1; i < ps.size() && position(trailpos[var(ps[i])]) < trail_lim.last(); i++)
+                ;
+            (*c)[1] = ps[i];
+            (*c)[i] = ps[1];
+
+            // Bump, enqueue, store clause:
+            claBumpActivity(*c);        // (newly learnt clauses should be considered active)
+            check(enqueue((*c)[0], c));
+            learnts.push(c);
+            stats.learnts_literals += c->size();
+        }else{
+            // Store clause:
+            clauses.push(c);
+            stats.clauses_literals += c->size();
+
+            if (subsumption){
+                c->calcAbstraction();
+                for (int i = 0; i < c->size(); i++){
+                    assert(!find(occurs[var((*c)[i])], c));
+                    occurs[var((*c)[i])].push(c);
+                    n_occ[toInt((*c)[i])]++;
+                    touched[var((*c)[i])] = 1;
+
+                    if (heap.inHeap(var((*c)[i])))
+		      updateHeap(var((*c)[i]));
+                }
+            }
+
+        }
+        // Watch clause:
+        watches[toInt(~(*c)[0])].push(c);
+        watches[toInt(~(*c)[1])].push(c);
+    }
+
+    return true;
+}
+
+
+// Disposes a clauses and removes it from watcher lists. NOTE!
+// Low-level; does NOT change the 'clauses' and 'learnts' vector.
+//
+void Solver::removeClause(Clause& c, bool dealloc)
+{
+    //fprintf(stderr, "delete %d: ", _c); printClause(c); fprintf(stderr, "\n");
+    assert(c.mark() == 0);
+
+    if (c.size() > 1){
+        assert(find(watches[toInt(~c[0])], &c));
+        assert(find(watches[toInt(~c[1])], &c));
+        remove(watches[toInt(~c[0])], &c);
+        remove(watches[toInt(~c[1])], &c); }
+
+    if (c.learnt()) stats.learnts_literals -= c.size();
+    else            stats.clauses_literals -= c.size();
+
+    if (subsumption && !c.learnt()){
+        for (int i = 0; i < c.size(); i++){
+            if (dealloc){
+                assert(find(occurs[var(c[i])], &c));
+                remove(occurs[var(c[i])], &c); 
+            }
+            n_occ[toInt(c[i])]--;
+            updateHeap(var(c[i]));
+        }
+    }
+
+    if (dealloc)
+        xfree(&c);
+    else
+        c.mark(1);
+}
+
+
+bool Solver::satisfied(Clause& c) const
+{
+    for (int i = 0; i < c.size(); i++)
+        if (value(c[i]) == l_True)
+            return true;
+    return false; }
+
+
+bool Solver::strengthen(Clause& c, Lit l)
+{
+    assert(decisionLevel() == 0);
+    assert(c.size() > 1);
+    assert(c.mark() == 0);
+
+    assert(toInt(~c[0]) < watches.size());
+    assert(toInt(~c[1]) < watches.size());
+    
+    assert(find(watches[toInt(~c[0])], &c));
+    assert(find(watches[toInt(~c[1])], &c));
+    assert(find(c,l));
+
+    if (c.learnt()) stats.learnts_literals -= 1;
+    else            stats.clauses_literals -= 1;
+
+    if (c[0] == l || c[1] == l){
+        assert(find(watches[toInt(~l)], &c));
+        remove(c,l);
+        remove(watches[toInt(~l)], &c);
+        if (c.size() > 1){
+            assert(!find(watches[toInt(~c[1])], &c));
+            watches[toInt(~c[1])].push(&c); }
+        else {
+            assert(find(watches[toInt(~c[0])], &c));
+            remove(watches[toInt(~c[0])], &c);
+            removeClause(c, false);
+        }
+    }
+    else
+        remove(c,l);
+        
+    assert(c.size() == 1 || find(watches[toInt(~c[0])], &c));
+    assert(c.size() == 1 || find(watches[toInt(~c[1])], &c));
+
+    if (subsumption){
+        assert(find(occurs[var(l)], &c));
+        remove(occurs[var(l)], &c);
+        assert(!find(occurs[var(l)], &c));
+
+        c.calcAbstraction();
+
+        n_occ[toInt(l)]--;
+        updateHeap(var(l));
+    }
+
+    return c.size() == 1 ? enqueue(c[0]) : true;
+}
+
+
+//=================================================================================================
+// Minor methods:
+
+
+// Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be
+// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
+//
+Var Solver::newVar(bool polarity, bool dvar) {
+    int     index;
+    index = nVars();
+    watches     .push();          // (list for positive literal)
+    watches     .push();          // (list for negative literal)
+    reason      .push(NULL);
+    assigns     .push(toInt(l_Undef));
+    trailpos    .push(TrailPos(0,0));
+    activity    .push(0);
+    order       .newVar(polarity,dvar);
+    seen        .push(0);
+    touched     .push(0);
+    if (subsumption){
+        occurs  .push();
+        n_occ   .push(0);
+        n_occ   .push(0);
+        heap    .setBounds(index+1);
+    }
+    return index; }
+
+
+// Returns FALSE if immediate conflict.
+bool Solver::assume(Lit p) {
+    trail_lim.push(trail.size());
+    return enqueue(p); }
+
+
+// Revert to the state at given level.
+void Solver::cancelUntil(int level) {
+    if (decisionLevel() > level){
+        for (int c = trail.size()-1; c >= trail_lim[level]; c--){
+            Var     x  = var(trail[c]);
+            assigns[x] = toInt(l_Undef);
+            reason [x] = NULL; 
+            order.undo(x); }
+        qhead = trail_lim[level];
+        trail.shrink(trail.size() - trail_lim[level]);
+        trail_lim.shrink(trail_lim.size() - level);
+    }
+}
+
+
+//=================================================================================================
+// Major methods:
+
+
+/*_________________________________________________________________________________________________
+|
+|  analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&)  ->  [void]
+|  
+|  Description:
+|    Analyze conflict and produce a reason clause.
+|  
+|    Pre-conditions:
+|      * 'out_learnt' is assumed to be cleared.
+|      * Current decision level must be greater than root level.
+|  
+|    Post-conditions:
+|      * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
+|  
+|  Effect:
+|    Will undo part of the trail, upto but not beyond the assumption of the current decision level.
+|________________________________________________________________________________________________@*/
+void Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel)
+{
+    int            pathC = 0;
+    int            btpos = -1;
+    Lit            p     = lit_Undef;
+
+    // Generate conflict clause:
+    //
+    out_learnt.push();      // (leave room for the asserting literal)
+    int index = trail.size()-1;
+    do{
+        assert(confl != NULL);          // (otherwise should be UIP)
+        Clause& c = *confl;
+
+        if (c.learnt())
+            claBumpActivity(c);
+
+        for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
+            Lit q = c[j];
+            if (!seen[var(q)] && position(trailpos[var(q)]) >= trail_lim[0]){
+	      varBumpActivity(q);
+                seen[var(q)] = 1;
+                if (position(trailpos[var(q)]) >= trail_lim.last())
+                    pathC++;
+                else{
+                    out_learnt.push(q);
+                    btpos = max(btpos, position(trailpos[var(q)]));
+                }
+            }
+        }
+
+        // Select next clause to look at:
+        while (!seen[var(trail[index--])]);
+        p     = trail[index+1];
+        confl = reason[var(p)];
+        seen[var(p)] = 0;
+        pathC--;
+
+    }while (pathC > 0);
+    out_learnt[0] = ~p;
+
+    // Find correct backtrack level
+    for (out_btlevel = trail_lim.size()-1; out_btlevel > 0 && trail_lim[out_btlevel-1] > btpos; out_btlevel--)
+        ;
+
+    int     i, j;
+    if (expensive_ccmin){
+        // Simplify conflict clause (a lot):
+        //
+        uint    min_level = 0;
+        for (i = 1; i < out_learnt.size(); i++)
+            min_level |= abstractLevel(trailpos[var(out_learnt[i])]);     // (maintain an abstraction of levels involved in conflict)
+
+        out_learnt.copyTo(analyze_toclear);
+        for (i = j = 1; i < out_learnt.size(); i++)
+            if (reason[var(out_learnt[i])] == NULL || !analyze_removable(out_learnt[i], min_level))
+                out_learnt[j++] = out_learnt[i];
+    }else{
+        // Simplify conflict clause (a little):
+        //
+        out_learnt.copyTo(analyze_toclear);
+        for (i = j = 1; i < out_learnt.size(); i++){
+            Clause& c = *reason[var(out_learnt[i])];
+            for (int k = 1; k < c.size(); k++)
+                if (!seen[var(c[k])] && position(trailpos[var(c[k])]) >= trail_lim[0]){
+                    out_learnt[j++] = out_learnt[i];
+                    break; }
+        }
+    }
+
+    stats.max_literals += out_learnt.size();
+    out_learnt.shrink(i - j);
+    stats.tot_literals += out_learnt.size();
+
+    for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0;    // ('seen[]' is now cleared)
+}
+
+
+// Check if 'p' can be removed. 'min_level' is used to abort early if visiting literals at a level that cannot be removed.
+//
+bool Solver::analyze_removable(Lit p, uint min_level)
+{
+    analyze_stack.clear(); analyze_stack.push(p);
+    int top = analyze_toclear.size();
+    while (analyze_stack.size() > 0){
+        assert(reason[var(analyze_stack.last())] != NULL);
+        Clause& c = *reason[var(analyze_stack.last())]; analyze_stack.pop();
+
+        for (int i = 1; i < c.size(); i++){
+            Lit      p   = c[i];
+            TrailPos tp = trailpos[var(p)];
+            if (!seen[var(p)] && position(tp) >= trail_lim[0]){
+                if (reason[var(p)] != NULL && (abstractLevel(tp) & min_level) != 0){
+                    seen[var(p)] = 1;
+                    analyze_stack.push(p);
+                    analyze_toclear.push(p);
+                }else{
+                    for (int j = top; j < analyze_toclear.size(); j++)
+                        seen[var(analyze_toclear[j])] = 0;
+                    analyze_toclear.shrink(analyze_toclear.size() - top);
+                    return false;
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  analyzeFinal : (p : Lit) ->  [void]
+|  
+|  Description:
+|    Specialized analysis procedure to express the final conflict in terms of assumptions.
+|    Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
+|    stores the result in 'out_conflict'.
+|________________________________________________________________________________________________@*/
+void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict)
+{
+    out_conflict.clear();
+    out_conflict.push(p);
+
+    if (decisionLevel() == 0)
+        return;
+
+    seen[var(p)] = 1;
+
+    int start = position(trailpos[var(p)]);
+    for (int i = start; i >= trail_lim[0]; i--){
+        Var     x = var(trail[i]);
+        if (seen[x]){
+            if (reason[x] == NULL){
+                assert(position(trailpos[x]) >= trail_lim[0]);
+                out_conflict.push(~trail[i]);
+            }else{
+                Clause& c = *reason[x];
+                for (int j = 1; j < c.size(); j++)
+                    if (position(trailpos[var(c[j])]) >= trail_lim[0])
+                        seen[var(c[j])] = 1;
+            }
+            seen[x] = 0;
+        }
+    }
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  enqueue : (p : Lit) (from : Clause*)  ->  [bool]
+|  
+|  Description:
+|    Puts a new fact on the propagation queue as well as immediately updating the variable's value.
+|    Should a conflict arise, FALSE is returned.
+|  
+|  Input:
+|    p    - The fact to enqueue
+|    from - [Optional] Fact propagated from this (currently) unit clause. Stored in 'reason[]'.
+|           Default value is NULL (no reason).
+|  
+|  Output:
+|    TRUE if fact was enqueued without conflict, FALSE otherwise.
+|________________________________________________________________________________________________@*/
+bool Solver::enqueue(Lit p, Clause* from)
+{
+
+    if (value(p) != l_Undef)
+        return value(p) != l_False;
+    else{
+        assigns [var(p)] = toInt(lbool(!sign(p)));
+        trailpos[var(p)] = TrailPos(trail.size(),decisionLevel());
+        reason  [var(p)] = from;
+        trail.push(p);
+        return true;
+    }
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  propagate : [void]  ->  [Clause*]
+|  
+|  Description:
+|    Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
+|    otherwise NULL.
+|  
+|    Post-conditions:
+|      * the propagation queue is empty, even if there was a conflict.
+|________________________________________________________________________________________________@*/
+Clause* Solver::propagate()
+{
+    if (decisionLevel() == 0 && subsumption)
+        return backwardSubsumptionCheck() ? NULL : propagate_tmpempty;
+
+    Clause* confl = NULL;
+    //fprintf(stderr, "propagate, qhead = %d, qtail = %d\n", qhead, qtail);
+    while (qhead < trail.size()){
+        stats.propagations++;
+        simpDB_props--;
+
+        Lit            p   = trail[qhead++];     // 'p' is enqueued fact to propagate.
+        vec<Clause*>&  ws  = watches[toInt(p)];
+        Clause         **i, **j, **end;
+
+        for (i = j = (Clause**)ws, end = i + ws.size();  i != end;){
+            Clause& c = **i++;
+            
+            // Make sure the false literal is data[1]:
+            Lit false_lit = ~p;
+            if (c[0] == false_lit)
+                c[0] = c[1], c[1] = false_lit;
+
+            assert(c[1] == false_lit);
+
+            // If 0th watch is true, then clause is already satisfied.
+            Lit first = c[0];
+            if (value(first) == l_True){
+                *j++ = &c;
+            }else{
+                // Look for new watch:
+                for (int k = 2; k < c.size(); k++)
+                    if (value(c[k]) != l_False){
+                        c[1] = c[k]; c[k] = false_lit;
+                        watches[toInt(~c[1])].push(&c);
+                        goto FoundWatch; }
+
+                // Did not find watch -- clause is unit under assignment:
+                *j++ = &c;
+                if (!enqueue(first, &c)){
+                    confl = &c;
+                    qhead = trail.size();
+                    // Copy the remaining watches:
+                    while (i < end)
+                        *j++ = *i++;
+                }
+            FoundWatch:;
+            }
+        }
+        ws.shrink(i - j);
+    }
+
+    return confl;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  reduceDB : ()  ->  [void]
+|  
+|  Description:
+|    Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
+|    clauses are clauses that are reason to some assignment. Binary clauses are never removed.
+|________________________________________________________________________________________________@*/
+struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } };
+void Solver::reduceDB()
+{
+    int     i, j;
+    double  extra_lim = cla_inc / learnts.size();    // Remove any clause below this activity
+
+    sort(learnts, reduceDB_lt());
+    for (i = j = 0; i < learnts.size() / 2; i++){
+        if (learnts[i]->size() > 2 && !locked(*learnts[i]))
+            removeClause(*learnts[i]);
+        else
+            learnts[j++] = learnts[i];
+    }
+    for (; i < learnts.size(); i++){
+        if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() < extra_lim)
+            removeClause(*learnts[i]);
+        else
+            learnts[j++] = learnts[i];
+    }
+    learnts.shrink(i - j);
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  simplifyDB : [void]  ->  [bool]
+|  
+|  Description:
+|    Simplify the clause database according to the current top-level assigment. Currently, the only
+|    thing done here is the removal of satisfied clauses, but more things can be put here.
+|________________________________________________________________________________________________@*/
+bool Solver::simplifyDB(bool expensive)
+{
+    assert(decisionLevel() == 0);
+    if (!ok || propagate() != NULL)
+        return ok = false;
+
+    if (nAssigns() == simpDB_assigns || 
+        (!subsumption && simpDB_props > 0)) // (nothing has changed or preformed a simplification too recently)
+        return true;
+
+    if (subsumption){
+        if (expensive && !eliminate())
+            return ok = false;
+
+        // Move this cleanup code to its own method ?
+        int      i , j;
+        vec<Var> dirty;
+        for (i = 0; i < clauses.size(); i++)
+            if (clauses[i]->mark() == 1){
+                Clause& c = *clauses[i];
+                for (int k = 0; k < c.size(); k++)
+                    if (!seen[var(c[k])]){
+                        seen[var(c[k])] = 1;
+                        dirty.push(var(c[k]));
+                    }
+            }
+        
+        for (i = 0; i < dirty.size(); i++){
+            cleanOcc(dirty[i]);
+            seen[dirty[i]] = 0;
+        }
+
+        for (i = j = 0; i < clauses.size(); i++)
+            if (clauses[i]->mark() == 1)
+                xfree(clauses[i]);
+            else
+                clauses[j++] = clauses[i];
+        clauses.shrink(i - j);
+    }
+
+    // Remove satisfied clauses:
+    for (int type = 0; type < (subsumption ? 1 : 2); type++){  // (only scan learnt clauses if subsumption is on)
+        vec<Clause*>& cs = type ? learnts : clauses;
+        int     j  = 0;
+        for (int i = 0; i < cs.size(); i++){
+            assert(cs[i]->mark() == 0);
+            if (satisfied(*cs[i]))
+                removeClause(*cs[i]);
+            else
+                cs[j++] = cs[i];
+        }
+        cs.shrink(cs.size()-j);
+    }
+    order.cleanup();
+
+    simpDB_assigns = nAssigns();
+    simpDB_props   = stats.clauses_literals + stats.learnts_literals;   // (shouldn't depend on 'stats' really, but it will do for now)
+
+    return true;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&)  ->  [lbool]
+|  
+|  Description:
+|    Search for a model the specified number of conflicts, keeping the number of learnt clauses
+|    below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to
+|    indicate infinity.
+|  
+|  Output:
+|    'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
+|    all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
+|    if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
+|________________________________________________________________________________________________@*/
+lbool Solver::search(int nof_conflicts, int nof_learnts)
+{
+    assert(ok);
+    int         backtrack_level;
+    int         conflictC = 0;
+    vec<Lit>    learnt_clause;
+
+    stats.starts++;
+    var_decay = 1 / params.var_decay;
+    cla_decay = 1 / params.clause_decay;
+
+    for (;;){
+        Clause* confl = propagate();
+        if (confl != NULL){
+            // CONFLICT
+            stats.conflicts++; conflictC++;
+            if (decisionLevel() == 0) return l_False;
+
+            learnt_clause.clear();
+            analyze(confl, learnt_clause, backtrack_level);
+            cancelUntil(backtrack_level);
+            newClause(learnt_clause, true);
+            varDecayActivity();
+            claDecayActivity();
+
+        }else{
+            // NO CONFLICT
+
+            if (nof_conflicts >= 0 && conflictC >= nof_conflicts){
+                // Reached bound on number of conflicts:
+                progress_estimate = progressEstimate();
+                cancelUntil(0);
+                return l_Undef; }
+
+            // Simplify the set of problem clauses:
+            if (decisionLevel() == 0 && !simplifyDB())
+                return l_False;
+
+            if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts)
+                // Reduce the set of learnt clauses:
+                reduceDB();
+
+            Lit next = lit_Undef;
+
+            if (decisionLevel() < assumptions.size()){
+                // Perform user provided assumption:
+                next = assumptions[decisionLevel()]; 
+                if (value(next) == l_False){
+                    analyzeFinal(~next, conflict);
+                    return l_False; }
+            }else{
+                // New variable decision:
+                stats.decisions++;
+                next = order.select(params.random_var_freq, decisionLevel());		
+	    }
+            if (next == lit_Undef)
+                // Model found:
+                return l_True;
+
+            check(assume(next));
+        }
+    }
+}
+
+
+// Return search-space coverage. Not extremely reliable.
+//
+double Solver::progressEstimate()
+{
+    double  progress = 0;
+    double  F = 1.0 / nVars();
+
+    for (int i = 0; i <= decisionLevel(); i++){
+        int beg = i == 0 ? 0 : trail_lim[i - 1];
+        int end = i == decisionLevel() ? trail.size() : trail_lim[i];
+        progress += pow(F, i) * (end - beg);
+    }
+
+    return progress / nVars();
+}
+
+
+// Divide all variable activities by 1e100.
+//
+void Solver::varRescaleActivity()
+{
+    for (int i = 0; i < nVars(); i++)
+        activity[i] *= 1e-100;
+    var_inc *= 1e-100;
+}
+
+
+// Divide all constraint activities by 1e100.
+//
+void Solver::claRescaleActivity()
+{
+    for (int i = 0; i < learnts.size(); i++)
+        learnts[i]->activity() *= 1e-20;
+    cla_inc *= 1e-20;
+}
+
+
+/*_________________________________________________________________________________________________
+|
+|  solve : (assumps : const vec<Lit>&)  ->  [bool]
+|  
+|  Description:
+|    Top-level solve.
+|________________________________________________________________________________________________@*/
+bool Solver::solve(const vec<Lit>& assumps)
+{
+    model.clear();
+    conflict.clear();
+
+    if (!simplifyDB(true)) return false;
+
+
+    double  nof_conflicts = params.restart_first;
+    double  nof_learnts   = nClauses() * params.learntsize_factor;
+    lbool   status        = l_Undef;
+    assumps.copyTo(assumptions);
+
+    if (verbosity >= 1){
+        reportf("==================================[MINISAT]====================================\n");
+        reportf("| Conflicts |          ORIGINAL         |          LEARNT          | Progress |\n");
+        reportf("|           |    Vars  Clauses Literals |    Limit  Clauses Lit/Cl |          |\n");
+        reportf("===============================================================================\n");
+    }
+
+    // Search:
+    while (status == l_Undef){
+        if (verbosity >= 1)
+            //reportf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", (int)stats.conflicts, nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (int)stats.learnts_literals, (double)stats.learnts_literals/nLearnts(), progress_estimate*100);
+            reportf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", (int)stats.conflicts, order.size(), nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (double)stats.learnts_literals/nLearnts(), progress_estimate*100);
+        status = search((int)nof_conflicts, (int)nof_learnts);
+        nof_conflicts *= params.restart_inc;
+        nof_learnts   *= params.learntsize_inc;
+    }
+
+    if (verbosity >= 1)
+        reportf("==============================================================================\n");
+
+    if (status == l_True){
+        // Copy model:
+        extendModel();
+#if 1
+        //fprintf(stderr, "Verifying model.\n");
+        for (int i = 0; i < clauses.size(); i++)
+            assert(satisfied(*clauses[i]));
+        for (int i = 0; i < eliminated.size(); i++)
+            assert(satisfied(*eliminated[i]));
+#endif
+        model.growTo(nVars());
+        for (int i = 0; i < nVars(); i++) model[i] = value(i);
+    }else{
+        assert(status == l_False);
+        if (conflict.size() == 0)
+            ok = false;
+    }
+
+    cancelUntil(0);
+    return status == l_True;
+}
+};//end of MINISAT namespace
diff --git a/stp/sat/Solver.h b/stp/sat/Solver.h
new file mode 100644
index 00000000..829194cc
--- /dev/null
+++ b/stp/sat/Solver.h
@@ -0,0 +1,359 @@
+/****************************************************************************************[Solver.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Solver_h
+#define Solver_h
+
+#include "SolverTypes.h"
+#include "VarOrder.h"
+
+namespace MINISAT {
+// Redfine if you want output to go somewhere else:
+#define reportf(format, args...) ( printf(format , ## args), fflush(stdout) )
+
+
+//=================================================================================================
+// Solver -- the main class:
+struct SolverStats {
+    int64   starts, decisions, propagations, conflicts;
+    int64   clauses_literals, learnts_literals, max_literals, tot_literals;
+    int64   subsumption_checks, subsumption_misses, merges;
+    SolverStats() : 
+        starts(0), decisions(0), propagations(0), conflicts(0)
+      , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0) 
+      , subsumption_checks(0), subsumption_misses(0), merges(0)
+    { }
+};
+
+
+struct SearchParams {
+    double  var_decay, clause_decay, random_var_freq;
+    double  restart_inc, learntsize_inc, learntsize_factor;
+    int     restart_first;
+    
+    SearchParams(double v = 0.95, double c = 0.999, double r = 0.02,
+                 double ri = 1.5, double li = 1.1, double lf = (double)1/(double)3,
+                 int rf = 100) : 
+        var_decay(v), clause_decay(c), random_var_freq(r),
+        restart_inc(ri), learntsize_inc(li), learntsize_factor(lf),
+        restart_first(rf) { }
+};
+
+  struct ElimLt {
+    const vec<int>& n_occ;
+    
+    ElimLt(const vec<int>& no) : n_occ(no) {}
+    int  cost      (Var x)        const { return n_occ[toInt(Lit(x))] * n_occ[toInt(~Lit(x))]; }
+    bool operator()(Var x, Var y) const { return cost(x) < cost(y); } 
+  };
+
+class Solver {
+protected:
+    // Solver state:    
+    bool                ok;               // If FALSE,the constraints are already unsatisfiable. 
+                                          // No part of solver state may be used!
+    vec<Clause*>        clauses;          // List of problem clauses.
+    vec<Clause*>        learnts;          // List of learnt clauses.
+    int                 n_bin_clauses;    // Keep track of number of binary clauses "inlined" into the watcher lists (we do this primarily to get identical behavior to the version without the binary clauses trick).
+    double              cla_inc;          // Amount to bump next clause with.
+    double              cla_decay;        // INVERSE decay factor for clause activity: stores 1/decay.
+
+    vec<double>         activity;         // A heuristic measurement of the activity of a variable.
+    double              var_inc;          // Amount to bump next variable with.
+    double              var_decay;        // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order.
+    VarOrder            order;            // Keeps track of the decision variable order.
+    vec<char>           properties;       // TODO: describe!!!
+
+    vec<vec<Clause*> >  watches;          // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
+    vec<char>           assigns;          // The current assignments (lbool:s stored as char:s).
+    vec<Lit>            trail;            // Assignment stack; stores all assigments made in the order they were made.
+    vec<int>            trail_lim;        // Separator indices for different decision levels in 'trail'.
+    vec<Clause*>        reason;           // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none.
+    vec<TrailPos>       trailpos;         // 'trailpos[var]' contains the position in the trail at wich the assigment was made.
+    int                 qhead;            // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).
+    int                 simpDB_assigns;   // Number of top-level assignments since last execution of 'simplifyDB()'.
+    int64               simpDB_props;     // Remaining number of propagations that must be made before next execution of 'simplifyDB()'.
+    vec<Lit>            assumptions;      // Current set of assumptions provided to solve by the user.
+
+    bool                subsumption;
+    vec<char>           touched;
+    vec<vec<Clause*> >  occurs;
+    vec<int>            n_occ;
+    Heap<ElimLt>        heap;
+    vec<Clause*>        subsumption_queue;
+
+    vec<Clause*>        eliminated;
+    vec<int>            eliminated_lim;
+    vec<Var>            eliminated_var;
+
+    // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is
+    // used, exept 'seen' wich is used in several places.
+    //
+    vec<char>           seen;
+    vec<Lit>            analyze_stack;
+    vec<Lit>            analyze_toclear;
+    Clause*             propagate_tmpempty;
+    Clause*             propagate_tmpbin;
+    Clause*             analyze_tmpbin;
+    Clause*             bwdsub_tmpunit;
+
+    vec<Lit>            addBinary_tmp;
+    vec<Lit>            addTernary_tmp;
+
+    // Main internal methods:
+    //
+    bool        assume           (Lit p);
+    void        cancelUntil      (int level);
+    void        record           (const vec<Lit>& clause);
+
+    void        analyze          (Clause* confl, vec<Lit>& out_learnt, int& out_btlevel); // (bt = backtrack)
+    bool        analyze_removable(Lit p, uint min_level);                                 // (helper method for 'analyze()')
+    void        analyzeFinal     (Lit p, vec<Lit>& out_conflict);
+    bool        enqueue          (Lit fact, Clause* from = NULL);
+    Clause*     propagate        ();
+    void        reduceDB         ();
+    Lit         pickBranchLit    ();
+    lbool       search           (int nof_conflicts, int nof_learnts);
+    double      progressEstimate ();
+
+    // Variable properties:
+    void        setVarProp (Var v, uint prop, bool b) { order.setVarProp(v, prop, b); }
+    bool        hasVarProp (Var v, uint prop) const   { return order.hasVarProp(v, prop); }
+    void        updateHeap (Var v) { 
+        if (hasVarProp(v, p_frozen))
+            heap.update(v); }
+
+    // Simplification methods:
+    //
+    void cleanOcc (Var v) {
+        assert(subsumption);
+        vec<Clause*>& occ = occurs[v];
+        int i, j;
+        for (i = j = 0; i < occ.size(); i++)
+            if (occ[i]->mark() != 1)
+                occ[j++] = occ[i];
+        occ.shrink(i - j); 
+    }
+
+    vec<Clause*>& getOccurs                (Var x) { cleanOcc(x); return occurs[x]; }
+    void          gather                   (vec<Clause*>& clauses);
+    Lit           subsumes                 (const Clause& c, const Clause& d);
+    bool          assymmetricBranching     (Clause& c);
+    bool          merge                    (const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause);
+    
+    bool          backwardSubsumptionCheck ();
+    bool          eliminateVar             (Var v, bool fail = false);
+    bool          eliminate                ();
+    void          extendModel              ();
+
+    // Activity:
+    //
+    void     varBumpActivity(Lit p) {
+        if (var_decay < 0) return;     // (negative decay means static variable order -- don't bump)
+        if ( (activity[var(p)] += var_inc) > 1e100 ) varRescaleActivity();
+        order.update(var(p)); }
+    void     varDecayActivity  () { if (var_decay >= 0) var_inc *= var_decay; }
+    void     varRescaleActivity();
+    void     claDecayActivity  () { cla_inc *= cla_decay; }
+    void     claRescaleActivity();
+
+    // Operations on clauses:
+    //
+    bool     newClause(const vec<Lit>& ps, bool learnt = false, bool normalized = false);
+    void     claBumpActivity (Clause& c) { if ( (c.activity() += cla_inc) > 1e20 ) claRescaleActivity(); }
+    bool     locked          (const Clause& c) const { return reason[var(c[0])] == &c; }
+    bool     satisfied       (Clause& c) const;
+    bool     strengthen      (Clause& c, Lit l);
+    void     removeClause    (Clause& c, bool dealloc = true);
+
+    int      decisionLevel() const { return trail_lim.size(); }
+
+public:
+    Solver() : ok               (true)
+             , n_bin_clauses    (0)
+             , cla_inc          (1)
+             , cla_decay        (1)
+             , var_inc          (1)
+             , var_decay        (1)
+             , order            (assigns, activity)
+             , qhead            (0)
+             , simpDB_assigns   (-1)
+             , simpDB_props     (0)
+             , subsumption      (true)
+             , heap             (n_occ)
+             , params           ()
+             , expensive_ccmin  (true)
+             , verbosity        (0)
+             , progress_estimate(0)
+             {
+                vec<Lit> dummy(2,lit_Undef);
+                propagate_tmpbin   = Clause_new(dummy);
+                analyze_tmpbin     = Clause_new(dummy);
+                dummy.pop();
+                bwdsub_tmpunit     = Clause_new(dummy);
+                dummy.pop();
+                propagate_tmpempty = Clause_new(dummy);
+                addBinary_tmp .growTo(2);
+                addTernary_tmp.growTo(3);
+             }
+
+   ~Solver() {
+       xfree(propagate_tmpbin);
+       xfree(analyze_tmpbin);
+       xfree(bwdsub_tmpunit);
+       xfree(propagate_tmpempty);
+       for (int i = 0; i < eliminated.size(); i++) xfree(eliminated[i]);
+       for (int i = 0; i < learnts.size();    i++) xfree(learnts[i]);
+       for (int i = 0; i < clauses.size();    i++) xfree(clauses[i]); }
+
+    // Helpers: (semi-internal)
+    //
+    lbool   value(Var x) const { return toLbool(assigns[x]); }
+    lbool   value(Lit p) const { return sign(p) ? ~toLbool(assigns[var(p)]) : toLbool(assigns[var(p)]); }
+
+    int     nAssigns()   { return trail.size(); }
+    int     nClauses()   { return clauses.size(); }
+    int     nLearnts()   { return learnts.size(); }
+    int     nConflicts() { return (int)stats.conflicts; }
+
+    // Statistics: (read-only member variable)
+    //
+    SolverStats     stats;
+
+    // Mode of operation:
+    //
+    SearchParams    params;             // Restart frequency etc.
+    bool            expensive_ccmin;    // Controls conflict clause minimization. TRUE by default.
+    int             verbosity;          // Verbosity level. 0=silent, 1=some progress report, 2=everything
+
+    // Problem specification:
+    //
+    Var     newVar    (bool polarity = true, bool dvar = true);
+    int     nVars     ()                    { return assigns.size(); }
+    bool    addUnit   (Lit p)               { return ok && (ok = enqueue(p)); }
+    bool    addBinary (Lit p, Lit q)        { addBinary_tmp [0] = p; addBinary_tmp [1] = q; return addClause(addBinary_tmp); }
+    bool    addTernary(Lit p, Lit q, Lit r) { addTernary_tmp[0] = p; addTernary_tmp[1] = q; addTernary_tmp[2] = r; return addClause(addTernary_tmp); }
+    bool    addClause (const vec<Lit>& ps)  { if (ok && !newClause(ps)) ok = false; return ok; }
+
+    // Variable mode:
+    // 
+    void    freezeVar    (Var v) { setVarProp(v, p_frozen, true); updateHeap(v); }
+
+    // Solving:
+    //
+    bool    okay         () { return ok; }       // FALSE means solver is in a conflicting state
+    bool    simplifyDB   (bool expensive = true);
+    bool    solve        (const vec<Lit>& assumps);
+    bool    solve        () { vec<Lit> tmp; return solve(tmp); }
+    void    turnOffSubsumption() {
+        subsumption = false;
+        occurs.clear(true);
+        n_occ.clear(true);
+    }
+
+    double      progress_estimate;  // Set by 'search()'.
+    vec<lbool>  model;              // If problem is satisfiable, this vector contains the model (if any).
+    vec<Lit>    conflict;           // If problem is unsatisfiable (possibly under assumptions), this vector represent the conflict clause expressed in the assumptions.
+
+  double  returnActivity(int i) { return activity[i];}
+  void    updateInitialActivity(int i, double act) {activity[i] = act; order.heap.update(i);}
+};
+
+
+//=================================================================================================
+// Debug:
+
+
+#define L_LIT    "%sx%d"
+#define L_lit(p) sign(p)?"~":"", var(p)
+
+// Just like 'assert()' but expression will be evaluated in the release version as well.
+inline void check(bool expr) { assert(expr); }
+
+static void printLit(Lit l)
+{
+    fprintf(stderr, "%s%d", sign(l) ? "-" : "", var(l)+1);
+}
+
+template<class C>
+static void printClause(const C& c)
+{
+    for (int i = 0; i < c.size(); i++){
+        printLit(c[i]);
+        fprintf(stderr, " ");
+    }
+}
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#ifdef _MSC_VER
+
+#include <ctime>
+
+static inline double cpuTime(void) {
+    return (double)clock() / CLOCKS_PER_SEC; }
+
+static inline int64 memUsed() {
+    return 0; }
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#else
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static inline double cpuTime(void) {
+    struct rusage ru;
+    getrusage(RUSAGE_SELF, &ru);
+    return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; }
+
+#if defined(__linux__) || defined(__CYGWIN__)
+static inline int memReadStat(int field)
+{
+    char    name[256];
+    pid_t pid = getpid();
+    sprintf(name, "/proc/%d/statm", pid);
+    FILE*   in = fopen(name, "rb");
+    if (in == NULL) return 0;
+    int     value;
+    for (; field >= 0; field--) {
+      int res = fscanf(in, "%d", &value);
+      (void) res;
+    }
+    fclose(in);
+    return value;
+}
+
+static inline int64 memUsed() { return (int64)memReadStat(0) * (int64)getpagesize(); }
+#else
+// use this by default. Mac OS X (Darwin) does not define an os type
+//defined(__FreeBSD__)
+
+static inline int64 memUsed(void) {
+    struct rusage ru;
+    getrusage(RUSAGE_SELF, &ru);
+    return ru.ru_maxrss*1024; }
+
+#endif
+
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#endif
+
+//=================================================================================================
+};
+#endif
diff --git a/stp/sat/SolverTypes.h b/stp/sat/SolverTypes.h
new file mode 100644
index 00000000..2b98b8ca
--- /dev/null
+++ b/stp/sat/SolverTypes.h
@@ -0,0 +1,127 @@
+/***********************************************************************************[SolverTypes.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+
+#ifndef SolverTypes_h
+#define SolverTypes_h
+
+#include "Global.h"
+
+namespace MINISAT {
+
+//=================================================================================================
+// Variables, literals, clause IDs:
+
+
+// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N,
+// so that they can be used as array indices.
+
+typedef int Var;
+#define var_Undef (-1)
+
+
+struct Lit {
+    int     x;
+
+    Lit() : x(2*var_Undef)                                              { }   // (lit_Undef)
+    explicit Lit(Var var, bool sign = false) : x((var+var) + (int)sign) { }
+};
+
+// Don't use these for constructing/deconstructing literals. Use the normal constructors instead.
+inline  int  toInt       (Lit p)           { return p.x; }                   // A "toInt" method that guarantees small, positive integers suitable for array indexing.
+inline  Lit  toLit       (int i)           { Lit p; p.x = i; return p; }     // Inverse of 'toInt()'
+
+inline  Lit  operator   ~(Lit p)           { Lit q; q.x = p.x ^ 1; return q; }
+inline  bool sign        (Lit p)           { return p.x & 1; }
+inline  int  var         (Lit p)           { return p.x >> 1; }
+inline  Lit  unsign      (Lit p)           { Lit q; q.x = p.x & ~1; return q; }
+inline  Lit  id          (Lit p, bool sgn) { Lit q; q.x = p.x ^ (int)sgn; return q; }
+
+inline  bool operator == (Lit p, Lit q)    { return toInt(p) == toInt(q); }
+inline  bool operator != (Lit p, Lit q)    { return toInt(p) != toInt(q); }
+inline  bool operator <  (Lit p, Lit q)    { return toInt(p)  < toInt(q); }  // '<' guarantees that p, ~p are adjacent in the ordering.
+
+
+const Lit lit_Undef(var_Undef, false);  // }- Useful special constants.
+const Lit lit_Error(var_Undef, true );  // }
+
+
+//=================================================================================================
+// Clause -- a simple class for representing a clause:
+
+class Clause {
+    uint    size_etc;
+    union { float act; uint abst; } apa;
+    Lit     data[0];
+public:
+    // NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
+    template<class V>
+    Clause(const V& ps, bool learnt) {
+        size_etc = (ps.size() << 3) | (uint)learnt;
+        for (int i = 0; i < ps.size(); i++) data[i] = ps[i];
+        if (learnt) apa.act = 0; else apa.abst = 0; }
+
+    // -- use this function instead:
+    template<class V>
+    friend Clause* Clause_new(const V& ps, bool learnt = false) {
+        assert(sizeof(Lit)      == sizeof(uint));
+        assert(sizeof(float)    == sizeof(uint));
+        void*   mem = xmalloc<char>(sizeof(Clause) + sizeof(uint)*(ps.size()));
+        return new (mem) Clause(ps, learnt); }
+
+    int       size        ()      const { return size_etc >> 3; }
+    void      shrink      (int i)       { assert(i <= size()); size_etc = (((size_etc >> 3) - i) << 3) | (size_etc & 7); }
+    void      pop         ()            { shrink(1); }
+    bool      learnt      ()      const { return size_etc & 1; }
+    uint      mark        ()      const { return (size_etc >> 1) & 3; }
+    void      mark        (uint m)      { size_etc = (size_etc & ~6) | ((m & 3) << 1); }
+    Lit       operator [] (int i) const { return data[i]; }
+    Lit&      operator [] (int i)       { return data[i]; }
+
+    float&    activity    ()       { return apa.act; }
+
+    uint      abstraction () const { return apa.abst; }
+
+    void calcAbstraction() {
+        uint abstraction = 0;
+        for (int i = 0; i < size(); i++)
+            abstraction |= 1 << (var(data[i]) & 31);
+        apa.abst = abstraction;  }
+};
+
+
+//=================================================================================================
+// TrailPos -- Stores an index into the trail as well as an approximation of a level. This data
+// is recorded for each assigment. (Replaces the old level information)
+
+
+class TrailPos {
+    int tp;
+ public:
+    explicit TrailPos(int index, int level) : tp( (index << 5) + (level & 31) ) { }
+
+    friend int abstractLevel(const TrailPos& p) { return 1 << (p.tp & 31); }
+    friend int position     (const TrailPos& p) { return p.tp >> 5; }
+
+    bool operator ==  (TrailPos other) const { return tp == other.tp; }
+    bool operator <   (TrailPos other) const { return tp <  other.tp; }
+};
+
+};
+#endif
diff --git a/stp/sat/Sort.h b/stp/sat/Sort.h
new file mode 100644
index 00000000..a7011edb
--- /dev/null
+++ b/stp/sat/Sort.h
@@ -0,0 +1,133 @@
+/******************************************************************************************[Sort.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef Sort_h
+#define Sort_h
+
+
+namespace MINISAT {
+//=================================================================================================
+
+
+template<class T>
+struct LessThan_default {
+    bool operator () (T x, T y) { return x < y; }
+};
+
+
+//=================================================================================================
+
+
+template <class T, class LessThan>
+void selectionSort(T* array, int size, LessThan lt)
+{
+    int     i, j, best_i;
+    T       tmp;
+
+    for (i = 0; i < size-1; i++){
+        best_i = i;
+        for (j = i+1; j < size; j++){
+            if (lt(array[j], array[best_i]))
+                best_i = j;
+        }
+        tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
+    }
+}
+template <class T> static inline void selectionSort(T* array, int size) {
+    selectionSort(array, size, LessThan_default<T>()); }
+
+
+template <class T, class LessThan>
+void sort(T* array, int size, LessThan lt, double& seed)
+{
+    if (size <= 15)
+        selectionSort(array, size, lt);
+
+    else{
+        T           pivot = array[irand(seed, size)];
+        T           tmp;
+        int         i = -1;
+        int         j = size;
+
+        for(;;){
+            do i++; while(lt(array[i], pivot));
+            do j--; while(lt(pivot, array[j]));
+
+            if (i >= j) break;
+
+            tmp = array[i]; array[i] = array[j]; array[j] = tmp;
+        }
+
+        sort(array    , i     , lt, seed);
+        sort(&array[i], size-i, lt, seed);
+    }
+}
+template <class T, class LessThan> void sort(T* array, int size, LessThan lt) {
+    double  seed = 91648253; sort(array, size, lt, seed); }
+template <class T> static inline void sort(T* array, int size) {
+    sort(array, size, LessThan_default<T>()); }
+
+
+template <class T, class LessThan>
+void sortUnique(T* array, int& size, LessThan lt)
+{
+    int         i, j;
+    T           last;
+
+    if (size == 0) return;
+
+    sort(array, size, lt);
+
+    i    = 1;
+    last = array[0];
+    for (j = 1; j < size; j++){
+        if (lt(last, array[j])){
+            last = array[i] = array[j];
+            i++; }
+    }
+
+    size = i;
+}
+template <class T> static inline void sortUnique(T* array, int& size) {
+    sortUnique(array, size, LessThan_default<T>()); }
+
+
+//=================================================================================================
+// For 'vec's:
+
+
+template <class T, class LessThan> void sort(vec<T>& v, LessThan lt) {
+    sort((T*)v, v.size(), lt); }
+template <class T> void sort(vec<T>& v) {
+    sort(v, LessThan_default<T>()); }
+
+
+template <class T, class LessThan> void sortUnique(vec<T>& v, LessThan lt) {
+    int     size = v.size();
+    T*      data = v.release();
+    sortUnique(data, size, lt);
+    v.~vec<T>();
+    new (&v) vec<T>(data, size); }
+template <class T> void sortUnique(vec<T>& v) {
+    sortUnique(v, LessThan_default<T>()); }
+
+
+//=================================================================================================
+};
+#endif
diff --git a/stp/sat/VarOrder.h b/stp/sat/VarOrder.h
new file mode 100644
index 00000000..6ad1bfb1
--- /dev/null
+++ b/stp/sat/VarOrder.h
@@ -0,0 +1,146 @@
+/**************************************************************************************[VarOrder.h]
+MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
+OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**************************************************************************************************/
+
+#ifndef VarOrder_h
+#define VarOrder_h
+
+#include "SolverTypes.h"
+#include "Solver.h"
+#include "Heap.h"
+#include "../AST/ASTUtil.h"
+
+namespace MINISAT {
+  //=================================================================================================
+
+  struct VarOrder_lt {
+    const vec<double>&  activity;
+    bool operator () (Var x, Var y) { return activity[x] > activity[y]; }
+    VarOrder_lt(const vec<double>&  act) : activity(act) { }
+  };
+  
+
+  enum { p_decisionvar = 0, p_polarity = 1, p_frozen = 2, p_dontcare = 3 };
+  
+  
+  class VarOrder {
+    const vec<char>&    assigns;     // var->val. Pointer to external assignment table.
+    const vec<double>&  activity;    // var->act. Pointer to external activity table.
+    vec<char>           properties;
+    //Heap<VarOrder_lt>   heap;
+    //double              random_seed; // For the internal random number generator
+    
+    friend class VarFilter;
+  public:
+    //FIXME: Vijay: delete after experiments
+    Heap<VarOrder_lt>   heap;
+    double              random_seed; // For the internal random number generator
+    //FIXME ENDS HERE
+
+    VarOrder(const vec<char>& ass, const vec<double>& act) :
+      assigns(ass), activity(act), heap(VarOrder_lt(act)), random_seed(2007)
+      //assigns(ass), activity(act), heap(VarOrder_lt(act))
+    { }
+    
+    int  size       ()                         { return heap.size(); }
+    void setVarProp (Var v, uint prop, bool b) { properties[v] = (properties[v] & ~(1 << prop)) | (b << prop); }
+    bool hasVarProp (Var v, uint prop) const   { return properties[v] & (1 << prop); }
+    inline void cleanup    ();
+    
+    inline void newVar(bool polarity, bool dvar);
+    inline void update(Var x);                  // Called when variable increased in activity.
+    inline void undo(Var x);                    // Called when variable is unassigned and may be selected again.
+    //Selects a new, unassigned variable (or 'var_Undef' if none exists).
+    inline Lit  select(double random_freq =.0, int decision_level = 0); 
+  };
+  
+  
+  struct VarFilter {
+    const VarOrder& o;
+    VarFilter(const VarOrder& _o) : o(_o) {}
+    bool operator()(Var v) const { return toLbool(o.assigns[v]) == l_Undef  && o.hasVarProp(v, p_decisionvar); }
+    //bool operator()(Var v) const { return toLbool(o.assigns[v]) == l_Undef; }
+  };
+  
+  void VarOrder::cleanup()
+  {
+    VarFilter f(*this);
+    heap.filter(f);
+  }
+  
+  void VarOrder::newVar(bool polarity, bool dvar)
+  {
+    Var v = assigns.size()-1;
+    heap.setBounds(v+1);
+    properties.push(0);
+    setVarProp(v, p_decisionvar, dvar);
+    setVarProp(v, p_polarity, polarity);
+    undo(v);
+  }
+  
+  
+  void VarOrder::update(Var x)
+  {
+    if (heap.inHeap(x))
+      heap.increase(x);
+  }
+  
+  
+  void VarOrder::undo(Var x)
+  {
+    if (!heap.inHeap(x) && hasVarProp(x, p_decisionvar))
+      heap.insert(x);
+  }
+  
+  
+  Lit VarOrder::select(double random_var_freq, int decision_level)
+  {
+    Var next = var_Undef;
+    
+    if (drand(random_seed) < random_var_freq && !heap.empty())
+      next = irand(random_seed,assigns.size());
+
+    // Activity based decision:
+    while (next == var_Undef || toLbool(assigns[next]) != l_Undef || !hasVarProp(next, p_decisionvar))
+      if (heap.empty()){
+	next = var_Undef;
+	break;
+      }else
+	next = heap.getmin();
+    
+    //printing
+    if(BEEV::print_sat_varorder) {
+      if (next != var_Undef) {
+	BEEV::Convert_MINISATVar_To_ASTNode_Print(next,
+						  decision_level,
+						  hasVarProp(next, p_polarity));
+	// fprintf(stderr,"var = %d, prop = %d, decision = %d, polarity = %d, frozen = %d\n", 
+	// 		next+1, properties[next], hasVarProp(next, p_decisionvar), 
+	// 		hasVarProp(next, p_polarity), hasVarProp(next, p_frozen));
+      }
+      else
+	fprintf(stderr, "var = undef\n");
+    }
+    
+    return next == var_Undef ? lit_Undef : Lit(next, hasVarProp(next, p_polarity));
+  }
+  
+  
+  //=================================================================================================
+};
+#endif
diff --git a/stp/simplifier/Makefile b/stp/simplifier/Makefile
new file mode 100644
index 00000000..aba07e1b
--- /dev/null
+++ b/stp/simplifier/Makefile
@@ -0,0 +1,11 @@
+include ../Makefile.common
+
+SRCS = simplifier.cpp bvsolver.cpp
+OBJS = $(SRCS:.cpp=.o)
+
+libsimplifier.a: $(OBJS)
+	$(AR) rc $@ $^
+	$(RANLIB) $@
+
+clean:	
+	rm -rf *.o *~ *.a .#*
diff --git a/stp/simplifier/bvsolver.cpp b/stp/simplifier/bvsolver.cpp
new file mode 100644
index 00000000..1c08f30b
--- /dev/null
+++ b/stp/simplifier/bvsolver.cpp
@@ -0,0 +1,714 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+#include "bvsolver.h"
+
+  //This file contains the implementation of member functions of
+  //bvsolver class, which represents the bitvector arithmetic linear
+  //solver. Please also refer the STP's CAV 2007 paper for the
+  //complete description of the linear solver algorithm
+  //
+  //The bitvector solver is a partial solver, i.e. it does not solve
+  //for all variables in the system of equations. it is
+  //best-effort. it relies on the SAT solver to be complete.
+  //
+  //The BVSolver assumes that the input equations are normalized, and
+  //have liketerms combined etc.
+  //
+  //0. Traverse top-down over the input DAG, looking for a conjunction
+  //0. of equations. if you find one, then for each equation in the
+  //0. conjunction, do the following steps.
+  //
+  //1. check for Linearity of the input equation
+  //
+  //2. Solve for a "chosen" variable. The variable should occur
+  //2. exactly once and must have an odd coeff. Refer STP's CAV 2007
+  //2. paper for actual solving procedure
+  //
+  //4. Outside the solver, Substitute and Re-normalize the input DAG 
+namespace BEEV {  
+  //check the solver map for 'key'. If key is present, then return the
+  //value by reference in the argument 'output'
+  bool BVSolver::CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output) {
+    ASTNodeMap::iterator it;
+    if((it = FormulasAlreadySolvedMap.find(key)) != FormulasAlreadySolvedMap.end()) {
+      output = it->second;
+      return true;
+    }
+    return false;
+  } //CheckAlreadySolvedMap()
+
+  void BVSolver::UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value) {
+    FormulasAlreadySolvedMap[key] = value;
+  } //end of UpdateAlreadySolvedMap()
+
+  //FIXME This is doing way more arithmetic than it needs to.
+  //accepts an even number "in", and splits it into an odd number and
+  //a power of 2. i.e " in = b.(2^k) ". returns the odd number, and
+  //the power of two by reference
+  ASTNode BVSolver::SplitEven_into_Oddnum_PowerOf2(const ASTNode& in, 
+						unsigned int& number_shifts) {
+    if(BVCONST != in.GetKind() || _bm->BVConstIsOdd(in)) {
+      FatalError("BVSolver:SplitNum_Odd_PowerOf2: input must be a BVCONST and even\n",in);
+    }
+    
+    unsigned int len = in.GetValueWidth();
+    ASTNode zero = _bm->CreateZeroConst(len);
+    ASTNode two = _bm->CreateTwoConst(len);
+    ASTNode div_by_2 = in;
+    ASTNode mod_by_2 = 
+      _bm->BVConstEvaluator(_bm->CreateTerm(BVMOD,len,div_by_2,two)); 
+    while(mod_by_2 == zero) {
+      div_by_2 = 
+	_bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,div_by_2,two));
+      number_shifts++;
+      mod_by_2 = 
+	_bm->BVConstEvaluator(_bm->CreateTerm(BVMOD,len,div_by_2,two));
+    }
+    return div_by_2;
+  } //end of SplitEven_into_Oddnum_PowerOf2()
+
+  //Checks if there are any ARRAYREADS in the term, after the
+  //alreadyseenmap is cleared, i.e. traversing a new term altogether
+  bool BVSolver::CheckForArrayReads_TopLevel(const ASTNode& term) {
+    TermsAlreadySeenMap.clear();
+    return CheckForArrayReads(term);
+  }
+  
+  //Checks if there are any ARRAYREADS in the term
+  bool BVSolver::CheckForArrayReads(const ASTNode& term) {
+    ASTNode a = term;
+    ASTNodeMap::iterator it;    
+    if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
+      //if the term has been seen, then simply return true, else
+      //return false
+      if(ASTTrue == (it->second)) {
+	return true;
+      }
+      else {
+	return false;
+      }
+    }
+
+    switch(term.GetKind()) {
+    case READ:
+      //an array read has been seen. Make an entry in the map and
+      //return true
+      TermsAlreadySeenMap[term] = ASTTrue;
+      return true;
+    default: {
+      ASTVec c = term.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	if(CheckForArrayReads(*it)) {
+	  return true;
+	}
+      }
+      break;
+    }
+    }
+
+    //If control is here, then it means that no arrayread was seen for
+    //the input 'term'. Make an entry in the map with the term as key
+    //and FALSE as value.
+    TermsAlreadySeenMap[term] = ASTFalse;
+    return false;
+  } //end of CheckForArrayReads()
+  
+  //check the solver map for 'key'. If key is present, then return the
+  //value by reference in the argument 'output'
+  bool BeevMgr::CheckSolverMap(const ASTNode& key, ASTNode& output) {
+    ASTNodeMap::iterator it;
+    if((it = SolverMap.find(key)) != SolverMap.end()) {
+      output = it->second;
+      return true;
+    }
+    return false;
+  } //end of CheckSolverMap()
+
+  bool BeevMgr::CheckSolverMap(const ASTNode& key) {
+    if(SolverMap.find(key) != SolverMap.end())	
+      return true;
+    else
+      return false;
+  } //end of CheckSolverMap()
+  
+  //update solvermap with (key,value) pair
+  bool BeevMgr::UpdateSolverMap(const ASTNode& key, const ASTNode& value) {
+    ASTNode var = (BVEXTRACT == key.GetKind()) ? key[0] : key;
+    if(!CheckSolverMap(var) && key != value) {
+      SolverMap[key] = value;
+      return true;
+    }  
+    return false;
+  } //end of UpdateSolverMap()
+
+  //collects the vars in the term 'lhs' into the multiset Vars
+  void BVSolver::VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& Vars) {
+    TermsAlreadySeenMap.clear();
+    VarsInTheTerm(lhs,Vars);
+  }
+
+  //collects the vars in the term 'lhs' into the multiset Vars
+  void BVSolver::VarsInTheTerm(const ASTNode& term, ASTNodeMultiSet& Vars) {
+    ASTNode a = term;
+    ASTNodeMap::iterator it;    
+    if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
+      //if the term has been seen, then simply return
+      return;
+    }
+
+    switch(term.GetKind()) {
+    case BVCONST:
+      return;
+    case SYMBOL:
+      //cerr << "debugging: symbol added: " << term << endl;
+      Vars.insert(term);
+      break;
+    case READ:
+      //skip the arrayname, provided the arrayname is a SYMBOL
+      if(SYMBOL == term[0].GetKind()) {
+	VarsInTheTerm(term[1],Vars);
+      }
+      else {
+	VarsInTheTerm(term[0],Vars);
+	VarsInTheTerm(term[1],Vars);
+      }
+      break;
+    default: {
+      ASTVec c = term.GetChildren();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	  VarsInTheTerm(*it,Vars);	  
+      }
+      break;
+    }
+    }
+
+    //ensures that you don't double count. if you have seen the term
+    //once, then memoize
+    TermsAlreadySeenMap[term] = ASTTrue;
+    return;
+  } //end of VarsInTheTerm()  
+
+  bool BVSolver::DoNotSolveThis(const ASTNode& var) {
+    if(DoNotSolve_TheseVars.find(var) != DoNotSolve_TheseVars.end()) {
+      return true;
+    }
+    return false;
+  }
+
+  //chooses a variable in the lhs and returns the chosen variable
+  ASTNode BVSolver::ChooseMonom(const ASTNode& eq, ASTNode& modifiedlhs) {
+    if(!(EQ == eq.GetKind() && BVPLUS == eq[0].GetKind())) {
+      FatalError("ChooseMonom: input must be a EQ",eq);
+    }
+
+    ASTNode lhs = eq[0];
+    ASTNode rhs = eq[1];
+    ASTNode zero = _bm->CreateZeroConst(32);
+
+    //collect all the vars in the lhs and rhs
+    ASTNodeMultiSet Vars;
+    VarsInTheTerm_TopLevel(lhs,Vars);
+
+    //handle BVPLUS case
+    ASTVec c = lhs.GetChildren();
+    ASTVec o;    
+    ASTNode outmonom = _bm->CreateNode(UNDEFINED);
+    bool chosen_symbol = false;
+    bool chosen_odd = false;
+
+    //choose variables with no coeffs
+    for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+      ASTNode monom = *it;
+      if(SYMBOL == monom.GetKind() &&
+	 Vars.count(monom) == 1    &&	 
+	 !_bm->VarSeenInTerm(monom,rhs) &&
+	 !DoNotSolveThis(monom)   &&
+	 !chosen_symbol) {
+	outmonom = monom;
+	chosen_symbol = true;
+      }
+      else if(BVUMINUS == monom.GetKind()  &&
+	      SYMBOL == monom[0].GetKind() &&
+	      Vars.count(monom[0]) == 1    &&
+	      !DoNotSolveThis(monom[0])   &&
+	      !_bm->VarSeenInTerm(monom[0],rhs) &&
+	      !chosen_symbol) {
+	//cerr << "Chosen Monom: " << monom << endl;
+	outmonom = monom;
+	chosen_symbol = true;
+      }
+      else {
+	o.push_back(monom);
+      }
+    }
+
+    //try to choose only odd coeffed variables first
+    if(!chosen_symbol) {
+      o.clear();
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	ASTNode monom = *it;
+	ASTNode var = (BVMULT == monom.GetKind()) ? monom[1] : _bm->CreateNode(UNDEFINED);
+
+	if(BVMULT == monom.GetKind()     && 
+	   BVCONST == monom[0].GetKind() &&
+	   _bm->BVConstIsOdd(monom[0])   &&
+	   ((SYMBOL == var.GetKind()  && 
+	     Vars.count(var) == 1) 
+	    || 
+	    (BVEXTRACT == var.GetKind()  && 
+	     SYMBOL == var[0].GetKind()  && 
+	     BVCONST == var[1].GetKind() && 
+	     zero == var[2] && 
+	     !_bm->VarSeenInTerm(var[0],rhs) &&
+	     !DoNotSolveThis(var[0]))	    
+	    ) &&
+	   !DoNotSolveThis(var)     &&
+	   !_bm->VarSeenInTerm(var,rhs)  &&
+	   !chosen_odd) {
+	  //monom[0] is odd.
+	  outmonom = monom;
+	  chosen_odd = true;
+	}
+	else {
+	o.push_back(monom);
+	}
+      }
+    }
+
+    modifiedlhs = (o.size() > 1) ? _bm->CreateTerm(BVPLUS,lhs.GetValueWidth(),o) : o[0];
+    return outmonom;
+  } //end of choosemonom()
+
+  //solver function which solves for variables with odd coefficient
+  ASTNode BVSolver::BVSolve_Odd(const ASTNode& input) {
+    ASTNode eq = input;
+    //cerr << "Input to BVSolve_Odd()" << eq << endl;
+    if(!(wordlevel_solve && EQ == eq.GetKind())) {
+      return input;
+    }
+
+    ASTNode output = input;
+    if(CheckAlreadySolvedMap(input,output)) {
+      return output;
+    }
+
+    //get the lhs and the rhs, and case-split on the lhs kind
+    ASTNode lhs = eq[0];
+    ASTNode rhs = eq[1];
+    if(BVPLUS == lhs.GetKind()) {
+      ASTNode chosen_monom = _bm->CreateNode(UNDEFINED);
+      ASTNode leftover_lhs;
+
+      //choose monom makes sure that it gets only those vars that
+      //occur exactly once in lhs and rhs put together
+      chosen_monom = ChooseMonom(eq, leftover_lhs);
+      if(chosen_monom == _bm->CreateNode(UNDEFINED)) {
+	//no monomial was chosen
+	return eq;
+      }
+      
+      //if control is here then it means that a monom was chosen
+      //
+      //construct:  rhs - (lhs without the chosen monom)
+      unsigned int len = lhs.GetValueWidth();
+      leftover_lhs = _bm->SimplifyTerm_TopLevel(_bm->CreateTerm(BVUMINUS,len,leftover_lhs));      
+      ASTNode newrhs = _bm->SimplifyTerm(_bm->CreateTerm(BVPLUS,len,rhs,leftover_lhs));
+      lhs = chosen_monom;
+      rhs = newrhs;
+    } //end of if(BVPLUS ...)
+
+    if(BVUMINUS == lhs.GetKind()) {
+      //equation is of the form (-lhs0) = rhs
+      ASTNode lhs0 = lhs[0];
+      rhs = _bm->SimplifyTerm(_bm->CreateTerm(BVUMINUS,rhs.GetValueWidth(),rhs));
+      lhs = lhs0;      
+    }
+
+    switch(lhs.GetKind()) {
+    case SYMBOL: {     
+      //input is of the form x = rhs first make sure that the lhs
+      //symbol does not occur on the rhs or that it has not been
+      //solved for
+      if(_bm->VarSeenInTerm(lhs,rhs)) {
+	//found the lhs in the rhs. Abort!
+	DoNotSolve_TheseVars.insert(lhs);
+	return eq;
+      }
+      
+      //rhs should not have arrayreads in it. it complicates matters
+      //during transformation
+      // if(CheckForArrayReads_TopLevel(rhs)) {
+      //       	return eq;
+      //       }
+
+      DoNotSolve_TheseVars.insert(lhs);
+      if(!_bm->UpdateSolverMap(lhs,rhs)) {
+	return eq;
+      }
+
+      output = ASTTrue;
+      break;
+    }
+    case BVEXTRACT: {
+      ASTNode zero = _bm->CreateZeroConst(32);
+      
+      if(!(SYMBOL == lhs[0].GetKind()  && 
+      	   BVCONST == lhs[1].GetKind() && 
+      	   zero == lhs[2] && 
+      	   !_bm->VarSeenInTerm(lhs[0],rhs) &&
+      	   !DoNotSolveThis(lhs[0]))) {
+      	return eq;
+      }
+      
+      if(_bm->VarSeenInTerm(lhs[0],rhs)) {
+      	DoNotSolve_TheseVars.insert(lhs[0]);
+      	return eq;
+      }
+      
+      DoNotSolve_TheseVars.insert(lhs[0]);
+      if(!_bm->UpdateSolverMap(lhs,rhs)) {
+      	return eq;
+      }
+
+      //if the extract of x[i:0] = t is entered into the solvermap,
+      //then also add another entry for x = x1@t
+      ASTNode var = lhs[0];
+      ASTNode newvar = NewVar(var.GetValueWidth() - lhs.GetValueWidth());
+      newvar = _bm->CreateTerm(BVCONCAT,var.GetValueWidth(),newvar,rhs);
+      _bm->UpdateSolverMap(var,newvar);      
+      output = ASTTrue;
+      break;
+    }
+    case BVMULT: {
+      //the input is of the form a*x = t. If 'a' is odd, then compute
+      //its multiplicative inverse a^-1, multiply 't' with it, and
+      //update the solver map
+      if(BVCONST != lhs[0].GetKind()) {
+	return eq;
+      }
+      
+      if(!(SYMBOL == lhs[1].GetKind() ||
+	   (BVEXTRACT == lhs[1].GetKind() &&
+	   SYMBOL == lhs[1][0].GetKind()))) {
+	return eq;
+      }
+
+      bool ChosenVar_Is_Extract = (BVEXTRACT == lhs[1].GetKind()) ? true : false;
+
+      //if coeff is even, then we know that all the coeffs in the eqn
+      //are even. Simply return the eqn
+      if(!_bm->BVConstIsOdd(lhs[0])) {
+	return eq;
+      }
+
+      ASTNode a = _bm->MultiplicativeInverse(lhs[0]);
+      ASTNode chosenvar = (BVEXTRACT == lhs[1].GetKind()) ? lhs[1][0] : lhs[1];
+      ASTNode chosenvar_value = 
+	_bm->SimplifyTerm(_bm->CreateTerm(BVMULT,rhs.GetValueWidth(),a,rhs));
+      
+      //if chosenvar is seen in chosenvar_value then abort
+      if(_bm->VarSeenInTerm(chosenvar,chosenvar_value)) {
+	//abort solving
+	DoNotSolve_TheseVars.insert(lhs);
+	return eq;
+      }
+
+      //rhs should not have arrayreads in it. it complicates matters
+      //during transformation
+      // if(CheckForArrayReads_TopLevel(chosenvar_value)) {
+      //       	return eq;
+      //       }
+            
+      //found a variable to solve
+      DoNotSolve_TheseVars.insert(chosenvar);
+      chosenvar = lhs[1];
+      if(!_bm->UpdateSolverMap(chosenvar,chosenvar_value)) {
+	return eq;
+      }
+
+      if(ChosenVar_Is_Extract) {
+	ASTNode var = lhs[1][0];
+	ASTNode newvar = NewVar(var.GetValueWidth() - lhs[1].GetValueWidth());
+	newvar = _bm->CreateTerm(BVCONCAT,var.GetValueWidth(),newvar,chosenvar_value);
+	_bm->UpdateSolverMap(var,newvar);
+      }
+      output = ASTTrue;
+      break;
+    }    
+    default:
+      output = eq;
+      break;
+    }
+    
+    UpdateAlreadySolvedMap(input,output);
+    return output;
+  } //end of BVSolve_Odd()
+
+  //Create a new variable of ValueWidth 'n'
+  ASTNode BVSolver::NewVar(unsigned int n) {
+    std:: string c("v");
+    char d[32];
+    sprintf(d,"%d",_symbol_count++);
+    std::string ccc(d);
+    c += "_solver_" + ccc;
+    
+    ASTNode CurrentSymbol = _bm->CreateSymbol(c.c_str());
+    CurrentSymbol.SetValueWidth(n);
+    CurrentSymbol.SetIndexWidth(0);
+    return CurrentSymbol;
+  } //end of NewVar()
+
+  //The toplevel bvsolver(). Checks if the formula has already been
+  //solved. If not, the solver() is invoked. If yes, then simply drop
+  //the formula
+  ASTNode BVSolver::TopLevelBVSolve(const ASTNode& input) {
+    if(!wordlevel_solve) {
+      return input;
+    }
+    
+    Kind k = input.GetKind();
+    if(!(EQ == k || AND == k)) {
+      return input;
+    }
+
+    ASTNode output = input;
+    if(CheckAlreadySolvedMap(input,output)) {
+      //output is TRUE. The formula is thus dropped
+      return output;
+    }
+    ASTVec o;
+    ASTVec c;
+    if(EQ == k) 
+      c.push_back(input);
+    else 
+      c = input.GetChildren();
+    ASTVec eveneqns;
+    ASTNode solved = ASTFalse;
+    for(ASTVec::iterator it = c.begin(), itend = c.end();it != itend;it++) { 
+      //_bm->ASTNodeStats("Printing before calling simplifyformula inside the solver:", *it);
+      ASTNode aaa = (ASTTrue == solved && EQ == it->GetKind()) ? _bm->SimplifyFormula(*it,false) : *it;
+      //ASTNode aaa = *it;
+      //_bm->ASTNodeStats("Printing after calling simplifyformula inside the solver:", aaa);
+      aaa = BVSolve_Odd(aaa);
+      //_bm->ASTNodeStats("Printing after oddsolver:", aaa);
+      bool even = false;
+      aaa = CheckEvenEqn(aaa, even);
+      if(even) {
+	eveneqns.push_back(aaa);
+      }
+      else {
+	if(ASTTrue != aaa) {
+	  o.push_back(aaa);
+	}
+      }
+      solved = aaa;
+    }
+
+    ASTNode evens;
+    if(eveneqns.size() > 0) {
+      //if there is a system of even equations then solve them
+      evens = (eveneqns.size() > 1) ? _bm->CreateNode(AND,eveneqns) : eveneqns[0];
+      //evens = _bm->SimplifyFormula(evens,false);
+      evens = BVSolve_Even(evens);
+      _bm->ASTNodeStats("Printing after evensolver:", evens);
+    }
+    else {
+      evens = ASTTrue;
+    }
+    output = (o.size() > 0) ? ((o.size() > 1) ? _bm->CreateNode(AND,o) : o[0]) : ASTTrue;
+    output = _bm->CreateNode(AND,output,evens);
+
+    UpdateAlreadySolvedMap(input,output);
+    return output;
+  } //end of TopLevelBVSolve()
+
+  ASTNode BVSolver::CheckEvenEqn(const ASTNode& input, bool& evenflag) {
+    ASTNode eq = input;
+    //cerr << "Input to BVSolve_Odd()" << eq << endl;
+    if(!(wordlevel_solve && EQ == eq.GetKind())) {
+      evenflag = false;
+      return eq;
+    }
+
+    ASTNode lhs = eq[0];
+    ASTNode rhs = eq[1];
+    ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+    //lhs must be a BVPLUS, and rhs must be a BVCONST
+    if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
+      evenflag = false;
+      return eq;
+    }
+    
+    ASTVec lhs_c = lhs.GetChildren();
+    ASTNode savetheconst = rhs;
+    for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
+      ASTNode aaa = *it;
+      Kind itk = aaa.GetKind();
+
+      if(BVCONST == itk){
+	//check later if the constant is even or not
+	savetheconst = aaa;
+	continue;
+      }
+      
+      if(!(BVMULT == itk &&
+	   BVCONST == aaa[0].GetKind() &&
+	   SYMBOL == aaa[1].GetKind() &&
+	   !_bm->BVConstIsOdd(aaa[0]))) {
+	//If the monomials of the lhs are NOT of the form 'a*x' where
+	//'a' is even, then return the false
+	evenflag = false;
+	return eq;
+      }  
+    }//end of for loop
+
+    //if control is here then it means that all coeffs are even. the
+    //only remaining thing is to check if the constant is even or not
+    if(_bm->BVConstIsOdd(savetheconst)) {
+      //the constant turned out to be odd. we have UNSAT eqn
+      evenflag = false;
+      return ASTFalse;
+    }
+    
+    //all is clear. the eqn in even, through and through
+    evenflag = true;
+    return eq;
+  } //end of CheckEvenEqn
+
+  //solve an eqn whose monomials have only even coefficients
+  ASTNode BVSolver::BVSolve_Even(const ASTNode& input) {
+    if(!wordlevel_solve) {
+      return input;
+    }
+
+    if(!(EQ == input.GetKind() || AND == input.GetKind())) {
+      return input;
+    }
+
+    ASTNode output;
+    if(CheckAlreadySolvedMap(input,output)) {
+      return output;
+    }
+
+    ASTVec input_c;
+    if(EQ == input.GetKind()) {
+      input_c.push_back(input);
+    }
+    else {
+      input_c = input.GetChildren();
+    }
+
+    //power_of_2 holds the exponent of 2 in the coeff
+    unsigned int power_of_2 = 0;
+    //we need this additional variable to find the lowest power of 2
+    unsigned int power_of_2_lowest = 0xffffffff;
+    //the monom which has the least power of 2 in the coeff
+    ASTNode monom_with_best_coeff;
+    for(ASTVec::iterator jt=input_c.begin(),jtend=input_c.end();jt!=jtend;jt++) {
+      ASTNode eq = *jt;
+      ASTNode lhs = eq[0];
+      ASTNode rhs = eq[1];
+      ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+      //lhs must be a BVPLUS, and rhs must be a BVCONST
+      if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
+	return input;
+      }
+    
+      ASTVec lhs_c = lhs.GetChildren();
+      ASTNode odd;
+      for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
+	ASTNode aaa = *it;
+	Kind itk = aaa.GetKind();
+	if(!(BVCONST == itk &&
+	     !_bm->BVConstIsOdd(aaa)) &&
+	   !(BVMULT == itk &&
+	     BVCONST == aaa[0].GetKind() &&
+	     SYMBOL == aaa[1].GetKind() &&
+	     !_bm->BVConstIsOdd(aaa[0]))) {
+	  //If the monomials of the lhs are NOT of the form 'a*x' or 'a'
+	  //where 'a' is even, then return the eqn
+	  return input;
+	}
+	
+	//we are gauranteed that if control is here then the monomial is
+	//of the form 'a*x' or 'a', where 'a' is even
+	ASTNode coeff = (BVCONST == itk) ? aaa : aaa[0];
+	odd = SplitEven_into_Oddnum_PowerOf2(coeff,power_of_2);
+	if(power_of_2  < power_of_2_lowest) {
+	  power_of_2_lowest = power_of_2;
+	  monom_with_best_coeff = aaa;
+	}
+	power_of_2 = 0;
+      }//end of inner for loop
+    } //end of outer for loop    
+
+    //get the exponent
+    power_of_2 = power_of_2_lowest;
+    
+    //if control is here, we are gauranteed that we have chosen a
+    //monomial with fewest powers of 2
+    ASTVec formula_out;
+    for(ASTVec::iterator jt=input_c.begin(),jtend=input_c.end();jt!=jtend;jt++) {
+      ASTNode eq = *jt;      
+      ASTNode lhs = eq[0];
+      ASTNode rhs = eq[1];
+      ASTNode zero = _bm->CreateZeroConst(rhs.GetValueWidth());
+      //lhs must be a BVPLUS, and rhs must be a BVCONST
+      if(!(BVPLUS == lhs.GetKind() && zero == rhs)) {
+	return input;
+      }
+      
+      unsigned len = lhs.GetValueWidth();
+      ASTNode hi = _bm->CreateBVConst(32,len-1);
+      ASTNode low = _bm->CreateBVConst(32,len - power_of_2);
+      ASTNode low_minus_one = _bm->CreateBVConst(32,len - power_of_2 - 1);
+      ASTNode low_zero = _bm->CreateZeroConst(32);
+      unsigned newlen = len - power_of_2;
+      ASTNode two_const = _bm->CreateTwoConst(len);
+
+      unsigned count = power_of_2;
+      ASTNode two = two_const;
+      while(--count) {
+	two = _bm->BVConstEvaluator(_bm->CreateTerm(BVMULT,len,two_const,two));
+      }
+      ASTVec lhs_c = lhs.GetChildren();
+      ASTVec lhs_out;
+      for(ASTVec::iterator it=lhs_c.begin(),itend=lhs_c.end();it!=itend;it++) {
+	ASTNode aaa = *it;
+	Kind itk = aaa.GetKind();
+	if(BVCONST == itk) {
+	  aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,aaa,two));
+	  aaa = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT,newlen,aaa,low_minus_one,low_zero));
+	}
+	else {
+	  //it must be of the form a*x
+	  ASTNode coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVDIV,len,aaa[0],two));
+	  coeff = _bm->BVConstEvaluator(_bm->CreateTerm(BVEXTRACT,newlen,coeff,low_minus_one,low_zero));
+	  ASTNode upper_x, lower_x;
+	  //upper_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, power_of_2, aaa[1], hi, low));
+	  lower_x = _bm->SimplifyTerm(_bm->CreateTerm(BVEXTRACT, newlen,aaa[1],low_minus_one,low_zero));
+	  aaa = _bm->CreateTerm(BVMULT,newlen,coeff,lower_x);
+	}
+	lhs_out.push_back(aaa);
+      }//end of inner forloop()
+      rhs = _bm->CreateZeroConst(newlen);
+      lhs = _bm->CreateTerm(BVPLUS,newlen,lhs_out);     
+      formula_out.push_back(_bm->CreateSimplifiedEQ(lhs,rhs));
+    } //end of outer forloop()
+
+    output = 
+      (formula_out.size() > 0) ? (formula_out.size() > 1) ? _bm->CreateNode(AND,formula_out) : formula_out[0] : ASTTrue;
+
+    UpdateAlreadySolvedMap(input,output);
+    return output;
+  } //end of BVSolve_Even()
+};//end of namespace BEEV
diff --git a/stp/simplifier/bvsolver.h b/stp/simplifier/bvsolver.h
new file mode 100644
index 00000000..a8981b12
--- /dev/null
+++ b/stp/simplifier/bvsolver.h
@@ -0,0 +1,134 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+namespace BEEV {
+
+  //This class represents the bitvector arithmetic linear solver.
+  //
+  //The bitvector solver is a partial solver, i.e. it does not solve
+  //for all variables in the system of equations. it is
+  //best-effort. it relies on the SAT solver to be complete.
+  //
+  //The BVSolver assumes that the input equations are normalized, and
+  //have liketerms combined etc.
+  //
+  //0. Traverse top-down over the input DAG, looking for a conjunction
+  //0. of equations. if you find one, then for each equation in the
+  //0. conjunction, do the following steps.
+  //
+  //1. check for Linearity of the input equation
+  //
+  //2. Solve for a "chosen" variable. The variable should occur
+  //2. exactly once and must have an odd coeff. Refer STP's CAV 2007
+  //2. paper for actual solving procedure
+  //
+  //4. Outside the solver, Substitute and Re-normalize the input DAG 
+  class BVSolver {
+    //Ptr to toplevel manager that manages bit-vector expressions
+    //(i.e. construct various kinds of expressions), and also has
+    //member functions that simplify bit-vector expressions
+    BeevMgr * _bm;
+    ASTNode ASTTrue, ASTFalse;
+
+    //Those formulas which have already been solved. If the same
+    //formula occurs twice then do not solve the second occurence, and
+    //instead drop it
+    ASTNodeMap FormulasAlreadySolvedMap;
+
+    //this map is useful while traversing terms and uniquely
+    //identifying variables in the those terms. Prevents double
+    //counting.
+    ASTNodeMap TermsAlreadySeenMap;
+    ASTNodeMap TermsAlreadySeenMap_ForArrays;
+
+    //count is used in the creation of new variables
+    unsigned int _symbol_count;
+
+    //solved variables list: If a variable has been solved for then do
+    //not solve for it again
+    ASTNodeSet DoNotSolve_TheseVars;
+
+    //checks if var has been solved for or not. if yes, then return
+    //true else return false
+    bool DoNotSolveThis(const ASTNode& var);
+
+    //traverses a term, and creates a multiset of all variables in the
+    //term. Does memoization to avoid double counting.
+    void VarsInTheTerm(const ASTNode& lhs, ASTNodeMultiSet& v);
+    void VarsInTheTerm_TopLevel(const ASTNode& lhs, ASTNodeMultiSet& v);
+
+    //choose a suitable var from the term
+    ASTNode ChooseMonom(const ASTNode& eq, ASTNode& modifiedterm);
+    //accepts an equation and solves for a variable or a monom in it
+    ASTNode BVSolve_Odd(const ASTNode& eq);
+
+    //solves equations of the form a*x=t where 'a' is even. Has a
+    //return value, unlike the normal BVSolve()
+    ASTNode BVSolve_Even(const ASTNode& eq);
+    ASTNode CheckEvenEqn(const ASTNode& input, bool& evenflag);
+
+    //Checks for arrayreads in a term. if yes then returns true, else
+    //return false
+    bool CheckForArrayReads(const ASTNode& term);
+    bool CheckForArrayReads_TopLevel(const ASTNode& term);
+
+    //Creates new variables used in solving
+    ASTNode NewVar(unsigned int n);
+
+    //this function return true if the var occurs in term, else the
+    //function returns false
+    bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
+    
+    //takes an even number "in" as input, and returns an odd number
+    //(return value) and a power of 2 (as number_shifts by reference),
+    //such that in = (odd_number * power_of_2).
+    //
+    //Refer STP's CAV 2007 (or Clark Barrett's 1998 paper on
+    //bit-vector arithmetic published in DAC 1998) paper for precise
+    //understanding of the algorithm
+    ASTNode SplitEven_into_Oddnum_PowerOf2(const ASTNode& in, unsigned int& number_shifts);
+
+    //Once a formula has been solved, then update the alreadysolvedmap
+    //with the formula, and the solved value. The solved value can be
+    //described using the following example: Suppose input to the
+    //solver is
+    //
+    // input key: x = 2 AND y = x + t
+    //
+    // output value: y = 2 + t
+    void UpdateAlreadySolvedMap(const ASTNode& key, const ASTNode& value);
+
+    //This function checks if the key (formula) has already been
+    //solved for.
+    //
+    //If yes it returns TRUE and fills the "output" with the
+    //solved-value (call by reference argument),
+    //
+    //else returns FALSE
+    bool CheckAlreadySolvedMap(const ASTNode& key, ASTNode& output);
+  public:
+    //constructor
+    BVSolver(BeevMgr * bm) : _bm(bm), _symbol_count(0) {
+      ASTTrue = _bm->CreateNode(TRUE);
+      ASTFalse = _bm->CreateNode(FALSE);
+    };
+
+    //Destructor
+    ~BVSolver() {
+      TermsAlreadySeenMap.clear();
+      DoNotSolve_TheseVars.clear();
+    }
+
+    //Top Level Solver: Goes over the input DAG, identifies the
+    //equation to be solved, solves them,
+    ASTNode TopLevelBVSolve(const ASTNode& a);
+  }; //end of class bvsolver
+};//end of namespace BEEV
diff --git a/stp/simplifier/simplifier.cpp b/stp/simplifier/simplifier.cpp
new file mode 100644
index 00000000..2a627398
--- /dev/null
+++ b/stp/simplifier/simplifier.cpp
@@ -0,0 +1,2495 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "../AST/AST.h"
+#include "../AST/ASTUtil.h"
+namespace BEEV {
+  
+  bool BeevMgr::CheckSimplifyMap(const ASTNode& key, 
+				 ASTNode& output, bool pushNeg) {
+    ASTNodeMap::iterator it, itend;
+    it = pushNeg ? SimplifyNegMap.find(key) : SimplifyMap.find(key);
+    itend = pushNeg ? SimplifyNegMap.end() : SimplifyMap.end();
+    
+    if(it != itend) {
+      output = it->second;
+      CountersAndStats("Successful_CheckSimplifyMap");
+      return true;
+    }
+
+    if(pushNeg && (it = SimplifyMap.find(key)) != SimplifyMap.end()) {
+      output = 
+	(ASTFalse == it->second) ? 
+	ASTTrue : 
+	(ASTTrue == it->second) ? ASTFalse : CreateNode(NOT, it->second);
+      CountersAndStats("2nd_Successful_CheckSimplifyMap");
+      return true;
+    }
+
+    return false;
+  }
+  
+  void BeevMgr::UpdateSimplifyMap(const ASTNode& key, const ASTNode& value, bool pushNeg) {
+    if(pushNeg) 
+      SimplifyNegMap[key] = value;
+    else
+      SimplifyMap[key] = value;
+  }
+
+  bool BeevMgr::CheckSubstitutionMap(const ASTNode& key, ASTNode& output) {
+    ASTNodeMap::iterator it;
+    if((it = SolverMap.find(key)) != SolverMap.end()) {
+      output = it->second;
+      return true;
+    }
+    return false;
+  }
+  
+  bool BeevMgr::CheckSubstitutionMap(const ASTNode& key) {
+    if(SolverMap.find(key) != SolverMap.end())	
+      return true;
+    else
+      return false;
+  }
+  
+  bool BeevMgr::UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1) {
+    int i = TermOrder(e0,e1);
+    if(0 == i)
+      return false;
+
+    //e0 is of the form READ(Arr,const), and e1 is const, or
+    //e0 is of the form var, and e1 is const    
+    if(1 == i && !CheckSubstitutionMap(e0)) {
+      SolverMap[e0] = e1;
+      return true;
+    }
+    
+    //e1 is of the form READ(Arr,const), and e0 is const, or
+    //e1 is of the form var, and e0 is const
+    if (-1 == i && !CheckSubstitutionMap(e1)) { 
+      SolverMap[e1] = e0;
+      return true;
+    }
+
+    return false;
+  }
+
+  bool BeevMgr::CheckMultInverseMap(const ASTNode& key, ASTNode& output) {
+    ASTNodeMap::iterator it;
+    if((it = MultInverseMap.find(key)) != MultInverseMap.end()) {
+      output = it->second;
+      return true;
+    }
+    return false;
+  }
+
+  void BeevMgr::UpdateMultInverseMap(const ASTNode& key, const ASTNode& value) {
+      MultInverseMap[key] = value;
+  }
+
+
+  bool BeevMgr::CheckAlwaysTrueFormMap(const ASTNode& key) {
+    ASTNodeSet::iterator it = AlwaysTrueFormMap.find(key);
+    ASTNodeSet::iterator itend = AlwaysTrueFormMap.end();
+    
+    if(it != itend) {
+      //cerr << "found:" << *it << endl;
+      CountersAndStats("Successful_CheckAlwaysTrueFormMap");
+      return true;
+    }
+    
+    return false;
+  }
+  
+  void BeevMgr::UpdateAlwaysTrueFormMap(const ASTNode& key) {
+    AlwaysTrueFormMap.insert(key);
+  }
+
+  //if a is READ(Arr,const) or SYMBOL, and b is BVCONST then return 1
+  //if b is READ(Arr,const) or SYMBOL, and a is BVCONST then return -1
+  //
+  //else return 0 by default
+   int BeevMgr::TermOrder(const ASTNode& a, const ASTNode& b) {
+    Kind k1 = a.GetKind();
+    Kind k2 = b.GetKind();
+
+    //a is of the form READ(Arr,const), and b is const, or
+    //a is of the form var, and b is const
+    if((k1 == READ 
+	&& 
+	a[0].GetKind() == SYMBOL && 
+	a[1].GetKind() == BVCONST
+	)
+       && 
+       (k2 == BVCONST)
+       )
+      return 1;
+
+    if(k1 == SYMBOL) 
+      return 1;
+
+    //b is of the form READ(Arr,const), and a is const, or
+    //b is of the form var, and a is const
+    if((k1  == BVCONST)
+       &&
+       ((k2 == READ
+	 && 
+	 b[0].GetKind() == SYMBOL &&
+	 b[1].GetKind() == BVCONST
+	 ) 
+	 ||
+	k2 == SYMBOL
+	))
+      return -1;
+    return 0;
+  }
+
+  //This function records all the const-indices seen so far for each
+  //array. It populates the map '_arrayname_readindices' whose key is
+  //the arrayname, and vlaue is a vector of read-indices.
+  //
+  //fill the arrayname_readindices vector if e0 is a READ(Arr,index)
+  //and index is a BVCONST.  
+  //
+  //Since these arrayreads are being nuked and recorded in the
+  //substitutionmap, we have to also record the fact that each
+  //arrayread (e0 is of the form READ(Arr,const) here is represented
+  //by a BVCONST (e1). This is necessary for later Leibnitz Axiom
+  //generation
+  void BeevMgr::FillUp_ArrReadIndex_Vec(const ASTNode& e0, const ASTNode& e1) {
+    int i = TermOrder(e0,e1);
+    if(0 == i) return;
+
+    if(1 == i && e0.GetKind() != SYMBOL && !CheckSubstitutionMap(e0)) {
+      _arrayname_readindices[e0[0]].push_back(e0[1]);
+      //e0 is the array read : READ(A,i) and e1 is a bvconst
+      _arrayread_symbol[e0] = e1;
+      return;
+    }
+    if(-1 == i && e1.GetKind() != SYMBOL &&  !CheckSubstitutionMap(e1)) {
+      _arrayname_readindices[e1[0]].push_back(e1[1]);
+      //e0 is the array read : READ(A,i) and e1 is a bvconst
+      _arrayread_symbol[e1] = e0;
+      return;
+    }
+  }
+
+  ASTNode BeevMgr::SimplifyFormula_NoRemoveWrites(const ASTNode& b, bool pushNeg) {
+    Begin_RemoveWrites = false;
+    ASTNode out = SimplifyFormula(b,pushNeg);
+    return out;
+  }
+
+  ASTNode BeevMgr::SimplifyFormula_TopLevel(const ASTNode& b, bool pushNeg) {
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    ASTNode out = SimplifyFormula(b,pushNeg);
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    return out;
+  }
+
+  ASTNode BeevMgr::SimplifyFormula(const ASTNode& b, bool pushNeg){
+    if(!optimize)
+      return b;
+
+    Kind kind = b.GetKind();
+    if(BOOLEAN_TYPE != b.GetType()) {
+      FatalError(" SimplifyFormula: You have input a nonformula kind: ",ASTUndefined,kind);
+    }
+    
+    ASTNode a = b;
+    ASTVec ca = a.GetChildren();
+    if(!(IMPLIES == kind || 
+	 ITE == kind ||
+	 isAtomic(kind))) {
+      SortByExprNum(ca);
+      a = CreateNode(kind,ca);
+    }
+
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    switch(kind){
+    case AND:
+    case OR:
+      output = SimplifyAndOrFormula(a,pushNeg);
+      break;
+    case NOT:
+      output = SimplifyNotFormula(a,pushNeg);
+      break;
+    case XOR:
+      output = SimplifyXorFormula(a,pushNeg);
+      break;
+    case NAND:
+      output = SimplifyNandFormula(a,pushNeg);
+      break;
+    case NOR:
+      output = SimplifyNorFormula(a,pushNeg);
+      break;
+    case IFF:
+      output = SimplifyIffFormula(a,pushNeg);
+      break;
+    case IMPLIES:
+      output = SimplifyImpliesFormula(a,pushNeg);
+      break;
+    case ITE:
+      output = SimplifyIteFormula(a,pushNeg);
+      break;
+    default:
+      //kind can be EQ,NEQ,BVLT,BVLE,... or a propositional variable
+      output = SimplifyAtomicFormula(a,pushNeg);
+      //output = pushNeg ? CreateNode(NOT,a) : a;
+      break;
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output, pushNeg);
+    return output;
+  }
+    
+  ASTNode BeevMgr::SimplifyAtomicFormula(const ASTNode& a, bool pushNeg) {    
+    if(!optimize) {
+      return a;
+    }
+
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,pushNeg)) {
+      return output;
+    }
+
+    ASTNode left,right;
+    if(a.Degree() == 2) {
+      //cerr << "Input to simplifyterm: left: " << a[0] << endl;
+      left = SimplifyTerm(a[0]);
+      //cerr << "Output of simplifyterm:left: " << left << endl;
+      //cerr << "Input to simplifyterm: right: " << a[1] << endl;
+      right = SimplifyTerm(a[1]);
+      //cerr << "Output of simplifyterm:left: " << right << endl;
+    }
+
+    Kind kind = a.GetKind();
+    switch(kind) {
+    case TRUE:
+      output = pushNeg ? ASTFalse : ASTTrue;
+      break;
+    case FALSE:
+      output = pushNeg ? ASTTrue : ASTFalse;
+      break;
+    case SYMBOL:
+      if(!CheckSolverMap(a,output)) {
+	output = a;
+      }
+      output = pushNeg ? CreateNode(NOT,output) : output;           
+      break;
+    case BVGETBIT: {
+      ASTNode term = SimplifyTerm(a[0]);
+      ASTNode thebit = a[1];
+      ASTNode zero = CreateZeroConst(1);
+      ASTNode one = CreateOneConst(1);
+      ASTNode getthebit = SimplifyTerm(CreateTerm(BVEXTRACT,1,term,thebit,thebit));
+      if(getthebit == zero)
+	output = pushNeg ? ASTTrue : ASTFalse;
+      else if(getthebit == one)
+	output = pushNeg ? ASTFalse : ASTTrue;
+      else {
+	output = CreateNode(BVGETBIT,term,thebit);
+	output = pushNeg ? CreateNode(NOT,output) : output;
+      }
+      break;
+    }
+    case EQ:{
+      output = CreateSimplifiedEQ(left,right);
+      output = LhsMinusRhs(output);
+      output = ITEOpt_InEqs(output);
+      if(output == ASTTrue)
+	output = pushNeg ? ASTFalse : ASTTrue;
+      else if (output == ASTFalse)
+	output = pushNeg ? ASTTrue : ASTFalse;
+      else
+	output = pushNeg ? CreateNode(NOT,output) : output;
+      break;  
+    } 
+    case NEQ: {
+      output = CreateSimplifiedEQ(left,right);
+      output = LhsMinusRhs(output);
+      if(output == ASTTrue)
+      	output = pushNeg ? ASTTrue : ASTFalse;
+      else if (output == ASTFalse)
+      	output = pushNeg ? ASTFalse : ASTTrue;
+      else
+	output = pushNeg ? output : CreateNode(NOT,output);
+      break;
+    }
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVSLT:
+    case BVSLE:
+    case BVSGT:
+    case BVSGE: {
+      //output = CreateNode(kind,left,right);
+      //output = pushNeg ? CreateNode(NOT,output) : output;      
+      output = CreateSimplifiedINEQ(kind,left,right,pushNeg);
+      break;
+    }
+    default:
+      FatalError("SimplifyAtomicFormula: NO atomic formula of the kind: ",ASTUndefined,kind);
+      break;      
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;
+  } //end of SimplifyAtomicFormula()
+
+  ASTNode BeevMgr::CreateSimplifiedINEQ(Kind k, 
+					const ASTNode& left, 
+					const ASTNode& right, 
+					bool pushNeg) {
+    ASTNode output;
+    if(BVCONST == left.GetKind() && BVCONST == right.GetKind()) {
+      output = BVConstEvaluator(CreateNode(k,left,right));
+      output = pushNeg ? (ASTFalse == output) ? ASTTrue : ASTFalse : output;
+      return output;
+    }
+
+    unsigned len = left.GetValueWidth();
+    ASTNode zero = CreateZeroConst(len);
+    ASTNode one = CreateOneConst(len);
+    ASTNode max = CreateMaxConst(len);
+    switch(k){
+    case BVLT:
+      if(right == zero) {
+	output = pushNeg ? ASTTrue : ASTFalse;
+      }
+      else if(left == right) {
+	output = pushNeg ? ASTTrue : ASTFalse;
+      }
+      else if(one == right) {
+	output = CreateSimplifiedEQ(left,zero);
+	output = pushNeg ? CreateNode(NOT,output) : output;
+      }
+      else {
+	output = pushNeg ? CreateNode(BVLE,right,left) : CreateNode(BVLT,left,right);
+      }
+      break;
+    case BVLE:
+      if(left == zero) {
+	output = pushNeg ? ASTFalse : ASTTrue;
+      }
+      else if(left == right) {
+	output = pushNeg ? ASTFalse : ASTTrue;
+      }
+      else if(max == right) {
+	output = pushNeg ? ASTFalse : ASTTrue;
+      }
+      else if(zero == right) {
+	output = CreateSimplifiedEQ(left,zero);
+	output = pushNeg ? CreateNode(NOT,output) : output;
+      }
+      else {
+	output = pushNeg ? CreateNode(BVLT,right,left) : CreateNode(BVLE,left,right);
+      }
+      break;
+    case BVGT:
+      if(left == zero) {
+	output = pushNeg ? ASTTrue : ASTFalse;
+      }
+      else if(left == right) {
+	output = pushNeg ? ASTTrue : ASTFalse;
+      }
+      else {
+      output = pushNeg ? CreateNode(BVLE,left,right) : CreateNode(BVLT,right,left);
+      }
+      break;
+    case BVGE:
+      if(right == zero) {
+	output = pushNeg ? ASTFalse : ASTTrue;
+      }
+      else if(left == right) {
+	output = pushNeg ? ASTFalse : ASTTrue;
+      }
+      else {
+      output = pushNeg ? CreateNode(BVLT,left,right) : CreateNode(BVLE,right,left);
+      }
+      break;
+    case BVSLT:
+    case BVSLE:
+    case BVSGE:
+    case BVSGT: {
+      output = CreateNode(k,left,right);
+      output = pushNeg ? CreateNode(NOT,output) : output;
+    }
+      break;
+    default:
+      FatalError("Wrong Kind");
+      break;
+    }
+
+    return output;
+  }
+
+  //takes care of some simple ITE Optimizations in the context of equations
+  ASTNode BeevMgr::ITEOpt_InEqs(const ASTNode& in) {
+    CountersAndStats("ITEOpts_InEqs");
+
+    if(!(EQ == in.GetKind() && optimize)) {
+      return in;
+    }
+
+    ASTNode output;
+    if(CheckSimplifyMap(in,output,false)) {
+      return output;
+    }
+
+    ASTNode in1 = in[0];
+    ASTNode in2 = in[1];
+    Kind k1 = in1.GetKind();
+    Kind k2 = in2.GetKind();
+    if(in1 == in2) {
+      //terms are syntactically the same
+      output = ASTTrue;    
+    }
+    else if(BVCONST == k1 && BVCONST == k2) {
+      //here the terms are definitely not syntactically equal but may
+      //be semantically equal.
+      output = ASTFalse;
+    }
+    else if(ITE == k1 && 
+	    BVCONST == in1[1].GetKind() && 
+	    BVCONST == in1[2].GetKind() && BVCONST == k2) {
+      //if one side is a BVCONST and the other side is an ITE over
+      //BVCONST then we can do the following optimization:
+      //
+      // c = ITE(cond,c,d) <=> cond
+      //
+      // similarly ITE(cond,c,d) = c <=> cond
+      //
+      // c = ITE(cond,d,c) <=> NOT(cond) 
+      //
+      //similarly ITE(cond,d,c) = d <=> NOT(cond)
+      ASTNode cond = in1[0];
+      if(in1[1] == in2) {
+	//ITE(cond, c, d) = c <=> cond
+	output = cond;
+      }
+      else if(in1[2] == in2) {
+	cond = SimplifyFormula(cond,true);
+	output = cond;
+      }
+      else {
+	//last resort is to CreateNode
+	output = CreateNode(EQ,in1,in2);   
+      }    
+    }    
+    else if(ITE == k2 && 
+	    BVCONST == in2[1].GetKind() && 
+	    BVCONST == in2[2].GetKind() && BVCONST == k1) {
+      ASTNode cond = in2[0];
+      if(in2[1] == in1) {
+	//ITE(cond, c, d) = c <=> cond
+	output = cond;
+      }
+      else if(in2[2] == in1) {
+	cond = SimplifyFormula(cond,true);
+	output = cond;
+      }
+      else {
+	//last resort is to CreateNode
+	output = CreateNode(EQ,in1,in2);   
+      }    
+    }
+    else {
+      //last resort is to CreateNode
+      output = CreateNode(EQ,in1,in2);   
+    }
+    
+    UpdateSimplifyMap(in,output,false);
+    return output;
+ } //End of ITEOpts_InEqs()
+
+  //Tries to simplify the input to TRUE/FALSE. if it fails, then
+  //return the constructed equality
+  ASTNode BeevMgr::CreateSimplifiedEQ(const ASTNode& in1, const ASTNode& in2) {
+    CountersAndStats("CreateSimplifiedEQ");        
+    Kind k1 = in1.GetKind();
+    Kind k2 = in2.GetKind();
+
+    if(!optimize) {
+      return CreateNode(EQ,in1,in2);
+    }
+    
+    if(in1 == in2)
+      //terms are syntactically the same
+      return ASTTrue;    
+    
+    //here the terms are definitely not syntactically equal but may be
+    //semantically equal.    
+    if(BVCONST == k1 && BVCONST == k2)
+      return ASTFalse;
+    
+    //last resort is to CreateNode
+    return CreateNode(EQ,in1,in2);
+  }
+  
+  //accepts cond == t1, then part is t2, and else part is t3
+  ASTNode BeevMgr::CreateSimplifiedTermITE(const ASTNode& in0, 
+					   const ASTNode& in1, const ASTNode& in2) {
+    ASTNode t0 = in0;
+    ASTNode t1 = in1;
+    ASTNode t2 = in2;
+    CountersAndStats("CreateSimplifiedITE");
+    if(!optimize) {
+      if(t1.GetValueWidth() != t2.GetValueWidth()) {
+	cerr << "t2 is : = " << t2;
+	FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
+      }
+      if(t1.GetIndexWidth() != t2.GetIndexWidth()) {
+	cerr << "t2 is : = " << t2;
+	FatalError("CreateSimplifiedTermITE: the lengths of then and else branches don't match",t1);
+      }
+      return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
+    }
+
+    if(t0 == ASTTrue)
+      return t1;
+    if (t0 == ASTFalse)
+      return t2;    
+    if(t1 == t2)
+      return t1;    
+    if(CheckAlwaysTrueFormMap(t0)) {
+	return t1;
+    }     
+    if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) || 
+       (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
+      return t2;
+    }
+    
+    return CreateTerm(ITE,t1.GetValueWidth(),t0,t1,t2);
+  }
+
+  ASTNode BeevMgr::SimplifyAndOrFormula(const ASTNode& a, bool pushNeg) {
+    ASTNode output;
+    //cerr << "input:\n" << a << endl;
+
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    ASTVec c, outvec;
+    c = a.GetChildren();
+    ASTNode flat = FlattenOneLevel(a);
+    c = flat.GetChildren();
+    SortByExprNum(c);
+
+    Kind k = a.GetKind();
+    bool isAnd = (k == AND) ? true : false;
+
+    ASTNode annihilator = isAnd ? 
+      (pushNeg ? ASTTrue : ASTFalse): 
+      (pushNeg ? ASTFalse : ASTTrue);
+
+    ASTNode identity = isAnd ? 
+      (pushNeg ? ASTFalse : ASTTrue): 
+      (pushNeg ? ASTTrue : ASTFalse);
+
+    //do the work
+    ASTVec::const_iterator next_it;
+    for(ASTVec::const_iterator i=c.begin(),iend=c.end();i!=iend;i++) {
+      ASTNode aaa = *i;
+      next_it = i+1;
+      bool nextexists = (next_it < iend);
+      
+      aaa = SimplifyFormula(aaa,pushNeg);
+      if(annihilator == aaa) {
+	//memoize
+	UpdateSimplifyMap(*i,annihilator,pushNeg);
+	UpdateSimplifyMap(a, annihilator,pushNeg);
+	//cerr << "annihilator1: output:\n" << annihilator << endl;
+	return annihilator;
+      }
+      ASTNode bbb = ASTFalse;
+      if(nextexists) {
+      	bbb = SimplifyFormula(*next_it,pushNeg);
+      }      
+      if(nextexists &&  bbb == aaa) {
+      	//skip the duplicate aaa. *next_it will be included
+      }
+      else if(nextexists && 
+      	      ((bbb.GetKind() == NOT && bbb[0] == aaa))) {
+      	//memoize
+      	UpdateSimplifyMap(a, annihilator,pushNeg);
+      	//cerr << "annihilator2: output:\n" << annihilator << endl;
+      	return annihilator;
+      }
+      else if(identity == aaa) {
+	// //drop identites
+      }
+      else if((!isAnd && !pushNeg) ||
+	      (isAnd && pushNeg)) { 
+	outvec.push_back(aaa);	
+      }
+      else if((isAnd && !pushNeg) ||
+	      (!isAnd && pushNeg)) {
+	outvec.push_back(aaa);	
+      }
+      else {
+	outvec.push_back(aaa);
+      }
+    }
+
+    switch(outvec.size()) {
+    case 0: {
+      //only identities were dropped 
+      output = identity;
+      break;
+    }
+    case 1: {
+      output = SimplifyFormula(outvec[0],false);
+      break;
+    }
+    default: {
+      output = (isAnd) ? 
+	(pushNeg ? CreateNode(OR,outvec) : CreateNode(AND,outvec)): 
+	(pushNeg ? CreateNode(AND,outvec) : CreateNode(OR,outvec));
+      //output = FlattenOneLevel(output);
+      break;
+    }
+    }
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    //cerr << "output:\n" << output << endl;
+    return output;
+  } //end of SimplifyAndOrFormula
+
+
+  ASTNode BeevMgr::SimplifyNotFormula(const ASTNode& a, bool pushNeg) {
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    if(!(a.Degree() == 1 && NOT == a.GetKind())) 
+      FatalError("SimplifyNotFormula: input vector with more than 1 node",ASTUndefined);
+
+    //if pushNeg is set then there is NOT on top
+    unsigned int NotCount = pushNeg ? 1 : 0;
+    ASTNode o = a;
+    //count the number of NOTs in 'a'
+    while(NOT == o.GetKind()) {
+      o = o[0];
+      NotCount++;
+    }
+
+    //pushnegation if there are odd number of NOTs
+    bool pn = (NotCount % 2 == 0) ? false : true;
+
+    if(CheckAlwaysTrueFormMap(o)) {
+      output = pn ? ASTFalse : ASTTrue;
+      return output;
+    }
+
+    if(CheckSimplifyMap(o,output,pn)) {
+      return output;
+    }
+
+    if (ASTTrue == o) {
+      output = pn ? ASTFalse : ASTTrue;
+    }
+    else if (ASTFalse == o) {
+      output = pn ? ASTTrue : ASTFalse;
+    }
+    else {
+      output = SimplifyFormula(o,pn);
+    }
+    //memoize
+    UpdateSimplifyMap(o,output,pn);
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;
+  }
+
+  ASTNode BeevMgr::SimplifyXorFormula(const ASTNode& a, bool pushNeg) {
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    if (a.GetChildren().size() > 2) {
+      FatalError("Simplify got an XOR with more than two children.");
+    }
+
+    ASTNode a0 = SimplifyFormula(a[0],false);
+    ASTNode a1 = SimplifyFormula(a[1],false);        
+    output = pushNeg ? CreateNode(IFF,a0,a1) : CreateNode(XOR,a0,a1);
+    
+    if(XOR == output.GetKind()) {
+      a0 = output[0];
+      a1 = output[1];
+      if(a0 == a1)
+	output = ASTFalse;
+      else if((a0 == ASTTrue  && a1 == ASTFalse) ||
+	      (a0 == ASTFalse && a1 == ASTTrue))
+	output = ASTTrue;
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;
+  }
+
+  ASTNode BeevMgr::SimplifyNandFormula(const ASTNode& a, bool pushNeg) {
+    ASTNode output,a0,a1;
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    //the two NOTs cancel out
+    if(pushNeg) {
+      a0 = SimplifyFormula(a[0],false);
+      a1 = SimplifyFormula(a[1],false);
+      output = CreateNode(AND,a0,a1);
+    }
+    else {
+      //push the NOT implicit in the NAND
+      a0 = SimplifyFormula(a[0],true);
+      a1 = SimplifyFormula(a[1],true);
+      output = CreateNode(OR,a0,a1);
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;
+  }
+
+  ASTNode BeevMgr::SimplifyNorFormula(const ASTNode& a, bool pushNeg) {
+    ASTNode output,a0,a1;
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    //the two NOTs cancel out
+    if(pushNeg) {
+      a0 = SimplifyFormula(a[0],false);
+      a1 = SimplifyFormula(a[1],false);
+      output = CreateNode(OR,a0,a1);
+    }
+    else {
+      //push the NOT implicit in the NAND
+      a0 = SimplifyFormula(a[0],true);
+      a1 = SimplifyFormula(a[1],true);
+      output = CreateNode(AND,a0,a1);
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;
+  }
+
+  ASTNode BeevMgr::SimplifyImpliesFormula(const ASTNode& a, bool pushNeg) {
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    if(!(a.Degree()==2 && IMPLIES==a.GetKind()))
+      FatalError("SimplifyImpliesFormula: vector with wrong num of nodes",ASTUndefined);
+    
+    ASTNode c0,c1;
+    if(pushNeg) {
+      c0 = SimplifyFormula(a[0],false);
+      c1 = SimplifyFormula(a[1],true);
+      output = CreateNode(AND,c0,c1);
+    }
+    else {
+      c0 = SimplifyFormula(a[0],false);
+      c1 = SimplifyFormula(a[1],false);
+      if(ASTFalse == c0) {
+	output = ASTTrue;
+      }
+      else if (ASTTrue == c0) {
+	output = c1;
+      }
+      else if (c0 == c1) {
+	output = ASTTrue;
+      }
+      else if(CheckAlwaysTrueFormMap(c0)) {
+	// c0 AND (~c0 OR c1) <==> c1
+	//
+	//applying modus ponens
+	output = c1;
+      }
+      else if(CheckAlwaysTrueFormMap(c1)	||
+	      CheckAlwaysTrueFormMap(CreateNode(NOT,c0)) ||
+	      (NOT == c0.GetKind() && CheckAlwaysTrueFormMap(c0[0]))) {
+	//(~c0 AND (~c0 OR c1)) <==> TRUE
+	//
+	//(c0 AND ~c0->c1) <==> TRUE
+	output = ASTTrue;
+      }
+      else if (CheckAlwaysTrueFormMap(CreateNode(NOT,c1)) ||
+	       (NOT == c1.GetKind() && CheckAlwaysTrueFormMap(c1[0]))) {
+	//(~c1 AND c0->c1) <==> (~c1 AND ~c1->~c0) <==> ~c0
+	//(c1 AND c0->~c1) <==> (c1 AND c1->~c0) <==> ~c0
+	output = CreateNode(NOT,c0);
+      }
+      else {
+	if(NOT == c0.GetKind()) {
+	  output = CreateNode(OR,c0[0],c1);
+	}
+	else {
+	  output = CreateNode(OR,CreateNode(NOT,c0),c1);
+	}
+      }
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;
+  }
+
+  ASTNode BeevMgr::SimplifyIffFormula(const ASTNode& a, bool pushNeg) {
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,pushNeg))
+      return output;
+
+    if(!(a.Degree()==2 && IFF==a.GetKind()))
+      FatalError("SimplifyIffFormula: vector with wrong num of nodes",ASTUndefined);
+    
+    ASTNode c0 = a[0];
+    ASTNode c1 = SimplifyFormula(a[1],false);
+
+    if(pushNeg)
+      c0 = SimplifyFormula(c0,true);
+    else 
+      c0 = SimplifyFormula(c0,false);
+
+    if(ASTTrue == c0) {
+      output = c1;
+    }
+    else if (ASTFalse == c0) {
+      output = SimplifyFormula(c1,true);
+    }
+    else if (ASTTrue == c1) {
+      output = c0;
+    }
+    else if (ASTFalse == c1) {
+      output = SimplifyFormula(c0,true);
+    }
+    else if (c0 == c1) {
+      output = ASTTrue;
+    }
+    else if((NOT == c0.GetKind() && c0[0] == c1) ||
+	    (NOT == c1.GetKind() && c0 == c1[0])) {
+      output = ASTFalse;
+    }
+    else if(CheckAlwaysTrueFormMap(c0)) {
+      output = c1;
+    }
+    else if(CheckAlwaysTrueFormMap(c1)) {
+      output = c0;
+    }
+    else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c0))) {
+      output = CreateNode(NOT,c1);
+    }
+    else if(CheckAlwaysTrueFormMap(CreateNode(NOT,c1))) {
+      output = CreateNode(NOT,c0);
+    }
+    else {
+      output = CreateNode(IFF,c0,c1);
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;
+  }
+
+  ASTNode BeevMgr::SimplifyIteFormula(const ASTNode& b, bool pushNeg) {
+    if(!optimize)
+      return b;
+
+    ASTNode output;
+    if(CheckSimplifyMap(b,output,pushNeg))
+      return output;
+
+    if(!(b.Degree() == 3 && ITE == b.GetKind()))
+      FatalError("SimplifyIteFormula: vector with wrong num of nodes",ASTUndefined);    
+    
+    ASTNode a = b;
+    ASTNode t0 = SimplifyFormula(a[0],false);
+    ASTNode t1,t2;
+    if(pushNeg) {
+      t1 = SimplifyFormula(a[1],true);
+      t2 = SimplifyFormula(a[2],true);
+    }
+    else {
+      t1 = SimplifyFormula(a[1],false);
+      t2 = SimplifyFormula(a[2],false);
+    }
+    
+    if(ASTTrue == t0) {
+      output = t1;
+    }
+    else if (ASTFalse == t0) {
+      output = t2;
+    }
+    else if (t1 == t2) {
+      output = t1;
+    }
+    else if(ASTTrue == t1 && ASTFalse == t2) {
+      output = t0;
+    }
+    else if(ASTFalse == t1 && ASTTrue == t2) {
+      output = SimplifyFormula(t0,true);
+    }
+    else if(ASTTrue == t1) {
+      output = CreateNode(OR,t0,t2);
+    }
+    else if(ASTFalse == t1) {
+      output = CreateNode(AND,CreateNode(NOT,t0),t2);
+    }
+    else if(ASTTrue == t2) {
+      output = CreateNode(OR,CreateNode(NOT,t0),t1);
+    }
+    else if(ASTFalse == t2) {
+      output = CreateNode(AND,t0,t1);
+    }
+    else if(CheckAlwaysTrueFormMap(t0)) {
+      output = t1;
+    }
+    else if(CheckAlwaysTrueFormMap(CreateNode(NOT,t0)) ||
+    	    (NOT == t0.GetKind() && CheckAlwaysTrueFormMap(t0[0]))) {
+      output = t2;
+    }
+    else {
+      output = CreateNode(ITE,t0,t1,t2);
+    }
+
+    //memoize
+    UpdateSimplifyMap(a,output,pushNeg);
+    return output;    
+  }
+
+  //one level deep flattening
+  ASTNode BeevMgr::FlattenOneLevel(const ASTNode& a) {
+    Kind k = a.GetKind();
+    if(!(BVPLUS == k || 
+	 AND == k || OR == k
+	 //|| BVAND == k 
+	 //|| BVOR == k
+	 )
+       ) {
+      return a;
+    }
+    
+    ASTNode output;
+    // if(CheckSimplifyMap(a,output,false)) {
+    //       //check memo table
+    //       //cerr << "output of SimplifyTerm Cache: " << output << endl;
+    //       return output;
+    //     }
+
+    ASTVec c = a.GetChildren();
+    ASTVec o;
+    for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+      ASTNode aaa = *it;
+      if(k == aaa.GetKind()) {
+	ASTVec ac = aaa.GetChildren();
+	o.insert(o.end(),ac.begin(),ac.end());
+      }
+      else
+	o.push_back(aaa);      
+    } 
+    
+    if(is_Form_kind(k))
+      output = CreateNode(k,o);
+    else
+      output = CreateTerm(k,a.GetValueWidth(),o);
+
+    //UpdateSimplifyMap(a,output,false);
+    return output;
+    //memoize
+  } //end of flattenonelevel()
+
+  ASTNode BeevMgr::SimplifyTerm_TopLevel(const ASTNode& b) {
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    ASTNode out = SimplifyTerm(b);
+    SimplifyNegMap.clear();
+    SimplifyMap.clear();
+    return out;
+  }
+
+  //This function simplifies terms based on their kind
+  ASTNode BeevMgr::SimplifyTerm(const ASTNode& inputterm) {
+    //cout << "SimplifyTerm: input: " << a << endl;
+    if(!optimize) {
+      return inputterm;
+    }
+
+    BVTypeCheck(inputterm);
+    ASTNode output;
+    if(wordlevel_solve && CheckSolverMap(inputterm,output)) {
+      //cout << "SimplifyTerm: output: " << output << endl;
+      return SimplifyTerm(output);     
+    }
+
+    if(CheckSimplifyMap(inputterm,output,false)) {
+      //cerr << "output of SimplifyTerm Cache: " << output << endl;
+      return output;
+    }
+
+    Kind k = inputterm.GetKind();    
+    if(!is_Term_kind(k)) {
+      FatalError("SimplifyTerm: You have input a Non-term",ASTUndefined);
+    }
+
+    unsigned int inputValueWidth = inputterm.GetValueWidth();
+    switch(k) {
+    case BVCONST:
+      output = inputterm;
+      break;
+    case SYMBOL:
+      if(CheckSolverMap(inputterm,output)) {
+	return SimplifyTerm(output);
+      }
+      output = inputterm;
+      break;
+    case BVMULT:
+    case BVPLUS:{
+      if(BVMULT == k && 2 != inputterm.Degree()) {
+	FatalError("SimplifyTerm: We assume that BVMULT is binary",inputterm);
+      }
+      
+      ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+      SortByExprNum(c);
+      ASTVec constkids, nonconstkids;
+
+      //go through the childnodes, and separate constant and
+      //nonconstant nodes. combine the constant nodes using the
+      //constevaluator. if the resultant constant is zero and k ==
+      //BVPLUS, then ignore it (similarily for 1 and BVMULT).  else,
+      //add the computed constant to the nonconst vector, flatten,
+      //sort, and create BVPLUS/BVMULT and return
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	ASTNode aaa = SimplifyTerm(*it);
+	if(BVCONST == aaa.GetKind()) {
+	  constkids.push_back(aaa);
+	}
+	else {
+	  nonconstkids.push_back(aaa);
+	}
+      }
+      
+      ASTNode one = CreateOneConst(inputValueWidth);
+      ASTNode max = CreateMaxConst(inputValueWidth);
+      ASTNode zero = CreateZeroConst(inputValueWidth);
+
+      //initialize constoutput to zero, in case there are no elements
+      //in constkids
+      ASTNode constoutput = (k == BVPLUS) ? zero : one;
+
+      if(1 == constkids.size()) {
+	//only one element in constkids
+	constoutput = constkids[0];
+      } 
+      else if (1 < constkids.size()) {
+	//many elements in constkids. simplify it
+	constoutput = CreateTerm(k,inputterm.GetValueWidth(),constkids);
+	constoutput = BVConstEvaluator(constoutput);
+      }
+
+      if(BVMULT == k && zero == constoutput) {
+	output = zero;
+      }
+      else if(BVMULT == k && 
+	      1 == nonconstkids.size() && 
+	      constoutput == max) {
+	//useful special case opt: when input is BVMULT(max_const,t),
+	//then output = BVUMINUS(t). this is easier on the bitblaster
+	output = CreateTerm(BVUMINUS,inputValueWidth,nonconstkids);
+      }
+      else {
+	if(0 < nonconstkids.size()) {
+	  //nonconstkids is not empty. First, combine const and
+	  //nonconstkids
+	  if(BVPLUS == k && constoutput != zero) {
+	    nonconstkids.push_back(constoutput);
+	  }
+	  else if(BVMULT == k && constoutput != one) {
+	    nonconstkids.push_back(constoutput);
+	  }
+
+	  if(1 == nonconstkids.size()) {
+	    //exactly one element in nonconstkids. output is exactly
+	    //nonconstkids[0]
+	    output = nonconstkids[0];
+	  }
+	  else {
+	    //more than 1 element in nonconstkids. create BVPLUS term
+	    SortByExprNum(nonconstkids);
+	    output = CreateTerm(k,inputValueWidth,nonconstkids);
+	    output = FlattenOneLevel(output);
+	    output = DistributeMultOverPlus(output,true);
+	    output = CombineLikeTerms(output);
+ 	  }
+	}
+	else {
+	  //nonconstkids was empty, all childnodes were constant, hence
+	  //constoutput is the output.
+	  output = constoutput;
+	}
+      }
+      if(BVMULT == output.GetKind() 
+	 || BVPLUS == output.GetKind()
+	 ) {
+	ASTVec d = output.GetChildren();
+	SortByExprNum(d);
+      	output = CreateTerm(output.GetKind(),output.GetValueWidth(),d);
+      }
+      break;
+    }
+    case BVSUB: {
+      ASTVec c = inputterm.GetChildren();
+      ASTNode a0 = SimplifyTerm(inputterm[0]);
+      ASTNode a1 = SimplifyTerm(inputterm[1]);
+      unsigned int l = inputValueWidth;
+      if(a0 == a1)
+	output = CreateZeroConst(l);
+      else {
+	//covert x-y into x+(-y) and simplify. this transformation
+	//triggers more simplifications
+	a1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a1));
+	output = SimplifyTerm(CreateTerm(BVPLUS,l,a0,a1));
+      }
+      break;
+    }
+    case BVUMINUS: {
+      //important to treat BVUMINUS as a special case, because it
+      //helps in arithmetic transformations. e.g.  x + BVUMINUS(x) is
+      //actually 0. One way to reveal this fact is to strip bvuminus
+      //out, and replace with something else so that combineliketerms
+      //can catch this fact.
+      ASTNode a0 = SimplifyTerm(inputterm[0]);
+      Kind k1 = a0.GetKind();
+      unsigned int l = a0.GetValueWidth();
+      ASTNode one = CreateOneConst(l);
+      switch(k1) {
+      case BVUMINUS:
+	output = a0[0];
+	break;
+      case BVCONST: {
+	output = BVConstEvaluator(CreateTerm(BVUMINUS,l,a0));
+	break;
+      }
+      case BVNEG: {
+	output = SimplifyTerm(CreateTerm(BVPLUS,l,a0[0],one));
+	break;
+      }
+      case BVMULT: {
+	if(BVUMINUS == a0[0].GetKind()) {
+	  output = CreateTerm(BVMULT,l,a0[0][0],a0[1]);
+	}
+	else if(BVUMINUS == a0[1].GetKind()) {
+	  output = CreateTerm(BVMULT,l,a0[0],a0[1][0]);
+	}
+	else {
+	  ASTNode a00 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[0]));	
+	  output = CreateTerm(BVMULT,l,a00,a0[1]);
+	}
+	break;
+      }
+      case BVPLUS: {
+	//push BVUMINUS over all the monomials of BVPLUS. Simplify
+	//along the way
+	//
+	//BVUMINUS(a1x1 + a2x2 + ...) <=> BVPLUS(BVUMINUS(a1x1) +
+	//BVUMINUS(a2x2) + ...
+	ASTVec c = a0.GetChildren();
+	ASTVec o;
+	for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	  //Simplify(BVUMINUS(a1x1))
+	  ASTNode aaa = SimplifyTerm(CreateTerm(BVUMINUS,l,*it));
+	  o.push_back(aaa);
+	}
+	//simplify the bvplus
+	output = SimplifyTerm(CreateTerm(BVPLUS,l,o));	
+	break;
+      }
+      case BVSUB: {
+	//BVUMINUS(BVSUB(x,y)) <=> BVSUB(y,x)
+	output = SimplifyTerm(CreateTerm(BVSUB,l,a0[1],a0[0]));
+	break;
+      }
+      case ITE: {
+	//BVUMINUS(ITE(c,t1,t2)) <==> ITE(c,BVUMINUS(t1),BVUMINUS(t2))
+	ASTNode c = a0[0];
+	ASTNode t1 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[1]));
+	ASTNode t2 = SimplifyTerm(CreateTerm(BVUMINUS,l,a0[2]));
+	output = CreateSimplifiedTermITE(c,t1,t2);
+	break;
+      }
+      default: {
+	output = CreateTerm(BVUMINUS,l,a0);
+	break;
+      }
+      }
+      break;
+    }
+    case BVEXTRACT:{
+      //it is important to take care of wordlevel transformation in
+      //BVEXTRACT. it exposes oppurtunities for later simplification
+      //and solving (variable elimination)
+      ASTNode a0 = SimplifyTerm(inputterm[0]);
+      Kind k1 = a0.GetKind();
+      unsigned int a_len = inputValueWidth;
+      
+      //indices for BVEXTRACT
+      ASTNode i = inputterm[1];
+      ASTNode j = inputterm[2];
+      ASTNode zero = CreateBVConst(32,0);
+      //recall that the indices of BVEXTRACT are always 32 bits
+      //long. therefore doing a GetBVUnsigned is ok.
+      unsigned int i_val = GetUnsignedConst(i);
+      unsigned int j_val = GetUnsignedConst(j);
+
+      // a0[i:0] and len(a0)=i+1, then return a0
+      if(0 == j_val && a_len == a0.GetValueWidth())
+	return a0;
+
+      switch(k1) {
+      case BVCONST: {
+	//extract the constant
+	output = BVConstEvaluator(CreateTerm(BVEXTRACT,a_len,a0,i,j));
+	break;
+      }
+      case BVCONCAT:{
+	//assumes concatenation is binary
+	//
+	//input is of the form a0[i:j]
+	//
+	//a0 is the conatentation t@u, and a0[0] is t, and a0[1] is u
+	ASTNode t = a0[0];
+	ASTNode u = a0[1];
+	unsigned int len_a0 = a0.GetValueWidth();
+	unsigned int len_u = u.GetValueWidth();
+
+	if(len_u > i_val) {
+	  //Apply the following rule:
+	  // (t@u)[i:j] <==> u[i:j], if len(u) > i
+	  //
+	  output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
+	}
+	else if(len_a0 > i_val && j_val >= len_u) {
+	  //Apply the rule:
+	  // (t@u)[i:j] <==> t[i-len_u:j-len_u], if len(t@u) > i >= j >= len(u)
+	  i = CreateBVConst(32, i_val - len_u);
+	  j = CreateBVConst(32, j_val - len_u);
+	  output = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
+	}
+	else {
+	  //Apply the rule:
+	  // (t@u)[i:j] <==> t[i-len_u:0] @ u[len_u-1:j]
+	  i = CreateBVConst(32,i_val-len_u);
+	  ASTNode m = CreateBVConst(32, len_u-1);
+	  t = SimplifyTerm(CreateTerm(BVEXTRACT,i_val-len_u+1,t,i,zero));
+	  u = SimplifyTerm(CreateTerm(BVEXTRACT,len_u-j_val,u,m,j));
+	  output = CreateTerm(BVCONCAT,a_len,t,u);
+	}
+	break;
+      }
+      case BVPLUS:
+      case BVMULT: {	
+	// (BVMULT(n,t,u))[i:j] <==> BVMULT(i+1,t[i:0],u[i:0])[i:j]
+	//similar rule for BVPLUS
+	ASTVec c = a0.GetChildren();
+	ASTVec o;
+	for(ASTVec::iterator jt=c.begin(),jtend=c.end();jt!=jtend;jt++) {
+	  ASTNode aaa = *jt;
+	  aaa = SimplifyTerm(CreateTerm(BVEXTRACT,i_val+1,aaa,i,zero));
+	  o.push_back(aaa);
+	}
+	output = CreateTerm(a0.GetKind(),i_val+1,o);	
+	if(j_val != 0) {
+	  //add extraction only if j is not zero
+	  output = CreateTerm(BVEXTRACT,a_len,output,i,j);
+	}
+	break;
+      }
+      case BVAND:
+      case BVOR:
+      case BVXOR: {
+	//assumes these operators are binary
+	//
+	// (t op u)[i:j] <==> t[i:j] op u[i:j]
+	ASTNode t = a0[0];
+	ASTNode u = a0[1];
+	t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
+	u = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,u,i,j));
+	BVTypeCheck(t);
+	BVTypeCheck(u);
+	output = CreateTerm(k1,a_len,t,u);
+	break;
+      }
+      case BVNEG:{
+	// (~t)[i:j] <==> ~(t[i:j])
+	ASTNode t = a0[0];
+	t = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,t,i,j));
+	output = CreateTerm(BVNEG,a_len,t);
+	break;
+      }
+      // case BVSX:{
+// 	//(BVSX(t,n)[i:j] <==> BVSX(t,i+1), if n >= i+1 and j=0 
+// 	ASTNode t = a0[0];
+// 	unsigned int bvsx_len = a0.GetValueWidth();
+// 	if(bvsx_len < a_len) {
+// 	  FatalError("SimplifyTerm: BVEXTRACT over BVSX:" 
+// 		     "the length of BVSX term must be greater than extract-len",inputterm);
+// 	}
+// 	if(j != zero) {
+// 	  output = CreateTerm(BVEXTRACT,a_len,a0,i,j);	  
+// 	}
+// 	else {
+// 	  output = CreateTerm(BVSX,a_len,t,CreateBVConst(32,a_len));
+// 	}
+// 	break;
+//       }
+      case ITE: {
+	ASTNode t0 = a0[0];
+	ASTNode t1 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[1],i,j));
+	ASTNode t2 = SimplifyTerm(CreateTerm(BVEXTRACT,a_len,a0[2],i,j));
+	output = CreateSimplifiedTermITE(t0,t1,t2);
+	break;
+      }
+      default: {
+	output = CreateTerm(BVEXTRACT,a_len,a0,i,j);
+	break;
+      }
+      }
+      break;
+    }
+    case BVNEG: {
+      ASTNode a0 = SimplifyTerm(inputterm[0]);
+      unsigned len = inputValueWidth;
+      switch(a0.GetKind()) {
+      case BVCONST:
+	output = BVConstEvaluator(CreateTerm(BVNEG,len,a0));
+	break;
+      case BVNEG:
+	output = a0[0];
+	break;
+      // case ITE: {
+// 	ASTNode cond = a0[0];
+// 	ASTNode thenpart = SimplifyTerm(CreateTerm(BVNEG,len,a0[1]));
+// 	ASTNode elsepart = SimplifyTerm(CreateTerm(BVNEG,len,a0[2]));
+// 	output = CreateSimplifiedTermITE(cond,thenpart,elsepart);	
+// 	break;
+//       }
+      default:
+	output = CreateTerm(BVNEG,len,a0);
+	break;
+      }
+      break;
+    }
+    case BVSX:{
+      //a0 is the expr which is being sign extended
+      ASTNode a0 = SimplifyTerm(inputterm[0]);
+      //a1 represents the length of the term BVSX(a0)
+      ASTNode a1 = inputterm[1];
+      //output length of the BVSX term
+      unsigned len = inputValueWidth;
+      
+      if(a0.GetValueWidth() == len) {
+	//nothing to signextend
+	return a0;
+      }
+
+      switch(a0.GetKind()) {
+      case BVCONST:
+	output = BVConstEvaluator(CreateTerm(BVSX,len,a0,a1));
+	break;
+      case BVNEG:
+	output = CreateTerm(a0.GetKind(),len,CreateTerm(BVSX,len,a0[0],a1));
+	break;
+      case BVAND:
+      case BVOR:
+	//assuming BVAND and BVOR are binary
+	output = CreateTerm(a0.GetKind(),len,
+			    CreateTerm(BVSX,len,a0[0],a1),
+			    CreateTerm(BVSX,len,a0[1],a1));
+	break;
+      case BVPLUS: {	
+	//BVSX(m,BVPLUS(n,BVSX(t1),BVSX(t2))) <==> BVPLUS(m,BVSX(m,t1),BVSX(m,t2))
+	ASTVec c = a0.GetChildren();
+	bool returnflag = false;
+	for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	  if(BVSX != it->GetKind()) {
+	    returnflag = true;
+	    break;
+	  }
+	}
+	if(returnflag) {
+	  output = CreateTerm(BVSX,len,a0,a1);
+	}
+	else {
+	  ASTVec o;
+	  for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	    ASTNode aaa = SimplifyTerm(CreateTerm(BVSX,len,*it,a1));
+	    o.push_back(aaa);
+	  }
+	  output = CreateTerm(a0.GetKind(),len,o);
+	}
+	break;
+      }
+      case BVSX: {
+	//if you have BVSX(m,BVSX(n,a)) then you can drop the inner
+	//BVSX provided m is greater than n.
+	a0 = SimplifyTerm(a0[0]);
+	output = CreateTerm(BVSX,len,a0,a1);
+	break;
+      }
+      case ITE: {
+	ASTNode cond = a0[0];
+	ASTNode thenpart = SimplifyTerm(CreateTerm(BVSX,len,a0[1],a1));
+	ASTNode elsepart = SimplifyTerm(CreateTerm(BVSX,len,a0[2],a1));
+	output = CreateSimplifiedTermITE(cond,thenpart,elsepart);
+	break;
+      }
+      default:
+	output = CreateTerm(BVSX,len,a0,a1);
+	break;
+      }    
+      break;
+    }
+    case BVAND:
+    case BVOR:{
+      ASTNode max = CreateMaxConst(inputValueWidth);
+      ASTNode zero = CreateZeroConst(inputValueWidth);
+
+      ASTNode identity = (BVAND == k) ? max : zero;
+      ASTNode annihilator = (BVAND == k) ? zero : max;
+      ASTVec c = FlattenOneLevel(inputterm).GetChildren();
+      SortByExprNum(c);
+      ASTVec o;
+      bool constant = true;
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	ASTNode aaa = SimplifyTerm(*it);
+	if(BVCONST != aaa.GetKind()) {
+	  constant = false;
+	}
+
+	if(aaa == annihilator) {
+	  output = annihilator;
+	  //memoize
+	  UpdateSimplifyMap(inputterm,output,false);
+	  //cerr << "output of SimplifyTerm: " << output << endl;
+	  return output;
+	}
+	
+	if(aaa != identity) {
+	  o.push_back(aaa);
+	}
+      }
+      
+      switch(o.size()) {
+      case 0:
+	output = identity;
+	break;
+      case 1:
+	output = o[0];
+	break;
+      default:
+	SortByExprNum(o);
+	output = CreateTerm(k,inputValueWidth,o);
+	if(constant) {
+	  output = BVConstEvaluator(output);
+	}     
+	break;
+      }
+      break;
+    }
+    case BVCONCAT:{
+      ASTNode t = SimplifyTerm(inputterm[0]);
+      ASTNode u = SimplifyTerm(inputterm[1]);
+      Kind tkind = t.GetKind();
+      Kind ukind = u.GetKind();
+      
+      
+      if(BVCONST == tkind && BVCONST == ukind) {
+	output = BVConstEvaluator(CreateTerm(BVCONCAT,inputValueWidth,t,u));
+      }
+      else if(BVEXTRACT == tkind && 
+	      BVEXTRACT == ukind && 
+	      t[0] == u[0]) {
+	//to handle the case x[m:n]@x[n-1:k] <==> x[m:k]
+	ASTNode t_hi = t[1];
+	ASTNode t_low = t[2];
+	ASTNode u_hi = u[1];
+	ASTNode u_low = u[2];
+	ASTNode c = BVConstEvaluator(CreateTerm(BVPLUS,32,u_hi,CreateOneConst(32)));
+	if(t_low == c) {
+	  output = CreateTerm(BVEXTRACT,inputValueWidth,t[0],t_hi,u_low);
+	}
+	else {
+	  output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
+	}
+      }
+      else {
+	output = CreateTerm(BVCONCAT,inputValueWidth,t,u);
+      }
+      break;
+    }
+    case BVXOR:
+    case BVXNOR:
+    case BVNAND:
+    case BVNOR:
+    case BVLEFTSHIFT:
+    case BVRIGHTSHIFT:
+    case BVVARSHIFT:
+    case BVSRSHIFT:
+    case BVDIV:
+    case BVMOD: {
+      ASTVec c = inputterm.GetChildren();
+      ASTVec o;
+      bool constant = true;
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	ASTNode aaa = SimplifyTerm(*it);
+	if(BVCONST != aaa.GetKind()) {
+	  constant = false;
+	}
+	o.push_back(aaa);
+      }
+      output = CreateTerm(k,inputValueWidth,o);
+      if(constant)
+	output = BVConstEvaluator(output);
+      break;
+    }
+    case READ: {
+      ASTNode out1;
+      //process only if not  in the substitution map. simplifymap
+      //has been checked already
+      if(!CheckSubstitutionMap(inputterm,out1)) {
+	if(WRITE == inputterm[0].GetKind()) {
+	  //get rid of all writes
+	  ASTNode nowrites = RemoveWrites_TopLevel(inputterm);
+	  out1 = nowrites;
+	}
+	else if (ITE == inputterm[0].GetKind()){
+	  ASTNode cond = SimplifyFormula(inputterm[0][0],false);
+	  ASTNode arr1 = SimplifyTerm(inputterm[0][1]);
+	  ASTNode arr2 = SimplifyTerm(inputterm[0][2]);
+
+	  ASTNode index = SimplifyTerm(inputterm[1]);
+	  
+	  ASTNode read1 = CreateTerm(READ,inputValueWidth,arr1,index);
+	  ASTNode read2 = CreateTerm(READ,inputValueWidth,arr2,index);
+	  out1 = CreateSimplifiedTermITE(cond,read1,read2);
+	}
+	else {
+	  //arr is a SYMBOL for sure
+	  ASTNode arr = inputterm[0];
+	  ASTNode index = SimplifyTerm(inputterm[1]);
+	  out1 = CreateTerm(READ,inputValueWidth,arr,index);     
+	}
+      }
+      //it is possible that after all the procesing the READ term
+      //reduces to READ(Symbol,const) and hence we should check the
+      //substitutionmap once again.      
+      if(!CheckSubstitutionMap(out1,output))
+	output = out1;      
+      break;
+    }
+    case ITE: {
+      ASTNode t0 = SimplifyFormula(inputterm[0],false);
+      ASTNode t1 = SimplifyTerm(inputterm[1]);
+      ASTNode t2 = SimplifyTerm(inputterm[2]);
+      output = CreateSimplifiedTermITE(t0,t1,t2);      
+      break;
+    }
+    case SBVMOD:
+    case SBVDIV: {
+      ASTVec c = inputterm.GetChildren();
+      ASTVec o;
+      for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	ASTNode aaa = SimplifyTerm(*it);
+	o.push_back(aaa);
+      }
+      output = CreateTerm(k,inputValueWidth,o);
+      break;
+    }
+    case WRITE:     
+    default:
+      FatalError("SimplifyTerm: Control should never reach here:", inputterm, k);
+      return inputterm;
+      break;
+    }
+
+    //memoize
+    UpdateSimplifyMap(inputterm,output,false);
+    //cerr << "SimplifyTerm: output" << output << endl;
+    return output;
+  } //end of SimplifyTerm()
+
+
+  //At the end of each simplification call, we want the output to be
+  //always smaller or equal to the input in size.
+  void BeevMgr::CheckSimplifyInvariant(const ASTNode& a, const ASTNode& output) {
+    //Don't do the check in optimized mode
+    if(optimize)
+      return;
+
+    if(NodeSize(a,true) < NodeSize(output,true)) {
+      cerr << "lhs := " << a << endl;
+      cerr << "NodeSize of lhs is: " << NodeSize(a, true) << endl;
+      cerr << endl;
+      cerr << "rhs := " << output << endl;
+      cerr << "NodeSize of rhs is: " << NodeSize(output, true) << endl;
+      FatalError("SimplifyFormula: The nodesize shoudl decrease from lhs to rhs: ",ASTUndefined);
+    }
+  }
+
+  //this function assumes that the input is a vector of childnodes of
+  //a BVPLUS term. it combines like terms and returns a bvplus
+  //term. e.g. 1.x + 2.x is converted to 3.x
+  ASTNode BeevMgr::CombineLikeTerms(const ASTNode& a) {
+    if(BVPLUS != a.GetKind())
+      return a;
+    
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,false)) {
+      //check memo table
+      //cerr << "output of SimplifyTerm Cache: " << output << endl;
+      return output;
+    }
+    
+    ASTVec c = a.GetChildren();
+    //map from variables to vector of constants
+    ASTNodeToVecMap vars_to_consts;
+    //vector to hold constants
+    ASTVec constkids;
+    ASTVec outputvec;
+
+    //useful constants
+    unsigned int len = c[0].GetValueWidth();
+    ASTNode one = CreateOneConst(len);
+    ASTNode zero = CreateZeroConst(len);
+    ASTNode max = CreateMaxConst(len);
+
+    //go over the childnodes of the input bvplus, and collect like
+    //terms in a map. the key of the map are the variables, and the
+    //values are stored in a ASTVec
+    for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
+      ASTNode aaa = *it;
+      if(SYMBOL == aaa.GetKind()) {
+	vars_to_consts[aaa].push_back(one);
+      }
+      else if(BVMULT == aaa.GetKind() && 
+	      BVUMINUS == aaa[0].GetKind() &&
+	      BVCONST == aaa[0][0].GetKind()) {
+	//(BVUMINUS(c))*(y) <==> compute(BVUMINUS(c))*y
+	ASTNode compute_const = BVConstEvaluator(aaa[0]);
+	vars_to_consts[aaa[1]].push_back(compute_const);
+      }
+      else if(BVMULT == aaa.GetKind() && 
+	      BVUMINUS == aaa[1].GetKind() &&
+	      BVCONST == aaa[0].GetKind()) {
+	//c*(BVUMINUS(y)) <==> compute(BVUMINUS(c))*y
+	ASTNode cccc = BVConstEvaluator(CreateTerm(BVUMINUS,len,aaa[0]));
+	vars_to_consts[aaa[1][0]].push_back(cccc);      
+      }      
+      else if(BVMULT == aaa.GetKind() && BVCONST == aaa[0].GetKind()) {
+	//assumes that BVMULT is binary
+	vars_to_consts[aaa[1]].push_back(aaa[0]);
+      } 
+      else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[0].GetKind()) {
+	//(-1*x)*(y) <==> -1*(xy)
+	ASTNode cccc = CreateTerm(BVMULT,len,aaa[0][0],aaa[1]);
+	ASTVec cNodes = cccc.GetChildren();
+	SortByExprNum(cNodes);
+	vars_to_consts[cccc].push_back(max);
+      }
+      else if(BVMULT == aaa.GetKind() && BVUMINUS == aaa[1].GetKind()) {
+	//x*(-1*y) <==> -1*(xy)
+	ASTNode cccc = CreateTerm(BVMULT,len,aaa[0],aaa[1][0]);
+	ASTVec cNodes = cccc.GetChildren();
+	SortByExprNum(cNodes);
+	vars_to_consts[cccc].push_back(max);      
+      }
+      else if(BVCONST == aaa.GetKind()) {
+	constkids.push_back(aaa);
+      }
+      else if(BVUMINUS == aaa.GetKind()) {
+	//helps to convert BVUMINUS into a BVMULT. here the max
+	//constant represents -1. this transformation allows us to
+	//conclude that x + BVUMINUS(x) is 0.
+	vars_to_consts[aaa[0]].push_back(max);
+      }
+      else 
+	vars_to_consts[aaa].push_back(one);
+    } //end of for loop
+
+    //go over the map from variables to vector of values. combine the
+    //vector of values, multiply to the variable, and put the
+    //resultant monomial in the output BVPLUS.
+    for(ASTNodeToVecMap::iterator it=vars_to_consts.begin(),itend=vars_to_consts.end();
+	it!=itend;it++){
+      ASTVec ccc = it->second;
+      
+      ASTNode constant;
+      if(1 < ccc.size()) {
+	constant = CreateTerm(BVPLUS,ccc[0].GetValueWidth(),ccc);
+	constant = BVConstEvaluator(constant);
+      }
+      else
+	constant = ccc[0];
+      
+      //constant * var
+      ASTNode monom;
+      if(zero == constant) 
+	monom = zero;
+      else if (one == constant)
+	monom = it->first;
+      else
+	monom = 
+	  SimplifyTerm(CreateTerm(BVMULT,constant.GetValueWidth(),constant,it->first));
+      if(zero != monom) {
+	outputvec.push_back(monom);
+      }
+    } //end of for loop
+
+    if(constkids.size() > 1) {
+      ASTNode output = CreateTerm(BVPLUS,constkids[0].GetValueWidth(),constkids);
+      output = BVConstEvaluator(output);
+      if(output != zero)
+	outputvec.push_back(output);
+    }
+    else if (constkids.size() == 1) {
+      if(constkids[0] != zero)
+	outputvec.push_back(constkids[0]);
+    }
+
+    if (outputvec.size() > 1) {
+      output = CreateTerm(BVPLUS,len,outputvec);
+    }
+    else if(outputvec.size() == 1) {
+      output = outputvec[0];
+    }
+    else {
+      output = zero;
+    }
+
+    //memoize
+    //UpdateSimplifyMap(a,output,false);
+    return output;
+  } //end of CombineLikeTerms()
+
+  //accepts lhs and rhs, and returns lhs - rhs = 0. The function
+  //assumes that lhs and rhs have already been simplified. although
+  //this assumption is not needed for correctness, it is essential for
+  //performance. The function also assumes that lhs is a BVPLUS
+  ASTNode BeevMgr::LhsMinusRhs(const ASTNode& eq) {
+    //if input is not an equality, simply return it
+    if(EQ != eq.GetKind())
+      return eq;
+
+    ASTNode lhs = eq[0];
+    ASTNode rhs = eq[1];
+    Kind k_lhs = lhs.GetKind();
+    Kind k_rhs = rhs.GetKind();
+    //either the lhs has to be a BVPLUS or the rhs has to be a
+    //BVPLUS
+    if(!(BVPLUS == k_lhs || 
+	 BVPLUS == k_rhs ||
+	 (BVMULT == k_lhs && 
+	  BVMULT == k_rhs)
+	 )) {
+      return eq;
+    }
+
+    ASTNode output;
+    if(CheckSimplifyMap(eq,output,false)) {
+      //check memo table
+      //cerr << "output of SimplifyTerm Cache: " << output << endl;
+      return output;
+    }
+    
+    //if the lhs is not a BVPLUS, but the rhs is a BVPLUS, then swap
+    //the lhs and rhs
+    bool swap_flag = false;
+    if(BVPLUS != k_lhs && BVPLUS == k_rhs) {
+      ASTNode swap = lhs;
+      lhs = rhs;
+      rhs = swap;
+      swap_flag = true;
+    }
+
+    unsigned int len = lhs.GetValueWidth();
+    ASTNode zero = CreateZeroConst(len);
+    //right is -1*(rhs): Simplify(-1*rhs)
+    rhs = SimplifyTerm(CreateTerm(BVUMINUS,len,rhs));
+
+    ASTVec lvec = lhs.GetChildren();
+    ASTVec rvec = rhs.GetChildren();
+    ASTNode lhsplusrhs;
+    if(BVPLUS != lhs.GetKind() && BVPLUS != rhs.GetKind()) {
+      lhsplusrhs = CreateTerm(BVPLUS,len,lhs,rhs); 
+    }
+    else if(BVPLUS == lhs.GetKind() && BVPLUS == rhs.GetKind()) {
+      //combine the childnodes of the left and the right
+      lvec.insert(lvec.end(),rvec.begin(),rvec.end());
+      lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
+    }
+    else if(BVPLUS == lhs.GetKind() && BVPLUS != rhs.GetKind()){
+      lvec.push_back(rhs);
+      lhsplusrhs = CreateTerm(BVPLUS,len,lvec);
+    }
+    else {
+      //Control should never reach here
+      FatalError("LhsMinusRhs: Control should never reach here\n");
+    }
+
+    //combine like terms
+    output = CombineLikeTerms(lhsplusrhs);
+    output = SimplifyTerm(output);
+    //
+    //Now make output into: lhs-rhs = 0
+    output = CreateSimplifiedEQ(output,zero);
+    //sort if BVPLUS
+    if(BVPLUS == output.GetKind()) {
+      ASTVec outv = output.GetChildren();
+      SortByExprNum(outv);
+      output = CreateTerm(BVPLUS,len,outv);
+    }
+    
+    //memoize
+    //UpdateSimplifyMap(eq,output,false);
+    return output;  
+  } //end of LhsMinusRHS()
+
+  //THis function accepts a BVMULT(t1,t2) and distributes the mult
+  //over plus if either or both t1 and t2 are BVPLUSes.
+  //
+  // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
+  //
+  // (y1 + y2 + ...+ yn)*x <==> x*y1 + x*y2 + ... + x*yn
+  //
+  // The function assumes that the BVPLUSes have been flattened
+  ASTNode BeevMgr::DistributeMultOverPlus(const ASTNode& a, bool startdistribution) {
+    if(!startdistribution)
+      return a;
+    Kind k = a.GetKind();
+    if(BVMULT != k)
+      return a;
+
+    ASTNode left = a[0];
+    ASTNode right = a[1];
+    Kind left_kind = left.GetKind();
+    Kind right_kind = right.GetKind();
+
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,false)) {
+      //check memo table
+      //cerr << "output of SimplifyTerm Cache: " << output << endl;
+      return output;
+    }
+
+    //special case optimization: c1*(c2*t1) <==> (c1*c2)*t1
+    if(BVCONST == left_kind && 
+       BVMULT == right_kind && 
+       BVCONST == right[0].GetKind()) {
+      ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[0]));
+      c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[1]);
+      return c;
+      left = c[0];
+      right = c[1];
+      left_kind = left.GetKind();
+      right_kind = right.GetKind();    
+    }
+
+    //special case optimization: c1*(t1*c2) <==> (c1*c2)*t1
+    if(BVCONST == left_kind && 
+       BVMULT == right_kind && 
+       BVCONST == right[1].GetKind()) {
+      ASTNode c = BVConstEvaluator(CreateTerm(BVMULT,a.GetValueWidth(),left,right[1]));
+      c = CreateTerm(BVMULT,a.GetValueWidth(),c,right[0]);
+      return c;
+      left = c[0];
+      right = c[1];
+      left_kind = left.GetKind();
+      right_kind = right.GetKind();    
+    }
+
+    //atleast one of left or right have to be BVPLUS
+    if(!(BVPLUS == left_kind || BVPLUS == right_kind)) {
+      return a;
+    }
+    
+    //if left is BVPLUS and right is not, then swap left and right. we
+    //can do this since BVMULT is communtative
+    ASTNode swap;
+    if(BVPLUS == left_kind && BVPLUS != right_kind) {
+      swap = left;
+      left = right;
+      right = swap;
+    }
+    left_kind = left.GetKind();
+    right_kind = right.GetKind();
+
+    //by this point we are gauranteed that right is a BVPLUS, but left
+    //may not be
+    ASTVec rightnodes = right.GetChildren();
+    ASTVec outputvec;
+    unsigned len = a.GetValueWidth();
+    ASTNode zero = CreateZeroConst(len);
+    ASTNode one = CreateOneConst(len);
+    if(BVPLUS != left_kind) {
+      //if the multiplier is not a BVPLUS then we have a special case
+      // x*(y1 + y2 + ...+ yn) <==> x*y1 + x*y2 + ... + x*yn
+      if(zero == left) {
+	outputvec.push_back(zero);
+      }
+      else if(one == left) {
+	outputvec.push_back(left);
+      }
+      else {
+	for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
+	    j!=jend;j++) {
+	  ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,left,*j));
+	  outputvec.push_back(out);
+	}
+      }
+    }
+    else {
+      ASTVec leftnodes = left.GetChildren();
+      // (x1 + x2 + ... + xm)*(y1 + y2 + ...+ yn) <==> x1*y1 + x1*y2 +
+      // ... + x2*y1 + ... + xm*yn
+      for(ASTVec::iterator i=leftnodes.begin(),iend=leftnodes.end();
+	  i!=iend;i++) {
+	ASTNode multiplier = *i;
+	for(ASTVec::iterator j=rightnodes.begin(),jend=rightnodes.end();
+	    j!=jend;j++) {
+	  ASTNode out = SimplifyTerm(CreateTerm(BVMULT,len,multiplier,*j));
+	  outputvec.push_back(out);
+	}
+      }
+    }
+    
+    //compute output here
+    if(outputvec.size() > 1) {
+      output = CombineLikeTerms(CreateTerm(BVPLUS,len,outputvec));
+      output = SimplifyTerm(output);
+    }
+    else
+      output = SimplifyTerm(outputvec[0]);
+
+    //memoize
+    //UpdateSimplifyMap(a,output,false);
+    return output;
+  } //end of distributemultoverplus()
+
+  //converts the BVSX(len, a0) operator into ITE( check top bit,
+  //extend a0 by 1, extend a0 by 0)
+  ASTNode BeevMgr::ConvertBVSXToITE(const ASTNode& a) {
+    if(BVSX != a.GetKind())
+      return a;
+
+    ASTNode output;
+    if(CheckSimplifyMap(a,output,false)) {
+      //check memo table
+      //cerr << "output of ConvertBVSXToITE Cache: " << output << endl;
+      return output;
+    }
+    
+    ASTNode a0 = a[0];
+    unsigned a_len = a.GetValueWidth();
+    unsigned a0_len = a0.GetValueWidth();
+    
+    if(a0_len > a_len){
+      FatalError("Trying to sign_extend a larger BV into a smaller BV");
+      return ASTUndefined; //to stop the compiler from producing bogus warnings
+    }
+    
+    //sign extend
+    unsigned extensionlen = a_len-a0_len;
+    if(0 == extensionlen) {
+      UpdateSimplifyMap(a,output,false);
+      return a;
+    }
+
+    std::string ones;
+    for(unsigned c=0; c < extensionlen;c++)
+      ones += '1';			   
+    std::string zeros;
+    for(unsigned c=0; c < extensionlen;c++)
+      zeros += '0';
+			   
+    //string of oness of length extensionlen
+    BEEV::ASTNode BVOnes = CreateBVConst(ones.c_str(),2);
+    //string of zeros of length extensionlen
+    BEEV::ASTNode BVZeros = CreateBVConst(zeros.c_str(),2);
+			   
+    //string of ones BVCONCAT a0
+    BEEV::ASTNode concatOnes = CreateTerm(BEEV::BVCONCAT,a_len,BVOnes,a0);
+    //string of zeros BVCONCAT a0
+    BEEV::ASTNode concatZeros = CreateTerm(BEEV::BVCONCAT,a_len,BVZeros,a0);
+
+    //extract top bit of a0
+    BEEV::ASTNode hi = CreateBVConst(32,a0_len-1);
+    BEEV::ASTNode low = CreateBVConst(32,a0_len-1);
+    BEEV::ASTNode topBit = CreateTerm(BEEV::BVEXTRACT,1,a0,hi,low);
+
+    //compare topBit of a0 with 0bin1
+    BEEV::ASTNode condition = CreateSimplifiedEQ(CreateBVConst(1,1),topBit);
+
+    //ITE(topbit = 0bin1, 0bin1111...a0, 0bin000...a0)
+    output = CreateSimplifiedTermITE(condition,concatOnes,concatZeros);
+    UpdateSimplifyMap(a,output,false);
+    return output;
+  } //end of ConvertBVSXToITE()
+
+
+  ASTNode BeevMgr::RemoveWrites_TopLevel(const ASTNode& term) {
+    if(READ != term.GetKind() && WRITE != term[0].GetKind()) {
+      FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+    }
+    
+    if(!Begin_RemoveWrites && 
+       !SimplifyWrites_InPlace_Flag && 
+       !start_abstracting) {
+      return term;
+    }
+    else if(!Begin_RemoveWrites && 
+	    SimplifyWrites_InPlace_Flag && 
+	    !start_abstracting) {
+      //return term;
+      return SimplifyWrites_InPlace(term);
+    }
+    else {
+      return RemoveWrites(term);
+    }
+  } //end of RemoveWrites_TopLevel()
+
+  ASTNode BeevMgr::SimplifyWrites_InPlace(const ASTNode& term) {
+    ASTNodeMultiSet WriteIndicesSeenSoFar;
+    bool SeenNonConstWriteIndex = false;
+
+    if(READ != term.GetKind() && 
+	WRITE != term[0].GetKind()) {
+      FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+    }
+    
+    ASTNode output;
+    if(CheckSimplifyMap(term,output,false)) {
+      return output;
+    }
+
+    ASTVec writeIndices, writeValues;
+    unsigned int width = term.GetValueWidth();
+    ASTNode write = term[0];
+    unsigned indexwidth = write.GetIndexWidth();
+    ASTNode readIndex = SimplifyTerm(term[1]);
+        
+    do {
+      ASTNode writeIndex = SimplifyTerm(write[1]);
+      ASTNode writeVal = SimplifyTerm(write[2]);
+          
+      //compare the readIndex and the current writeIndex and see if they
+      //simplify to TRUE or FALSE or UNDETERMINABLE at this stage
+      ASTNode compare_readwrite_indices = 
+	SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
+    
+      //if readIndex and writeIndex are equal
+      if(ASTTrue == compare_readwrite_indices && !SeenNonConstWriteIndex) {
+	UpdateSimplifyMap(term,writeVal,false);
+	return writeVal;
+      }
+
+      if(!(ASTTrue == compare_readwrite_indices || 
+	   ASTFalse == compare_readwrite_indices)) {
+	SeenNonConstWriteIndex = true;
+      }
+
+      //if (readIndex=writeIndex <=> FALSE)
+      if(ASTFalse == compare_readwrite_indices 
+	 ||
+	 (WriteIndicesSeenSoFar.find(writeIndex) != WriteIndicesSeenSoFar.end())
+	 ) {
+	//drop the current level write
+	//do nothing
+      }
+      else {
+	writeIndices.push_back(writeIndex);
+	writeValues.push_back(writeVal);
+      }
+      
+      //record the write indices seen so far
+      //if(BVCONST == writeIndex.GetKind()) {
+	WriteIndicesSeenSoFar.insert(writeIndex);
+	//}
+
+      //Setup the write for the new iteration, one level inner write
+      write = write[0];
+    }while (SYMBOL != write.GetKind());
+
+    ASTVec::reverse_iterator it_index = writeIndices.rbegin();
+    ASTVec::reverse_iterator itend_index = writeIndices.rend();
+    ASTVec::reverse_iterator it_values = writeValues.rbegin();
+    ASTVec::reverse_iterator itend_values = writeValues.rend();
+
+    //"write" must be a symbol at the control point before the
+    //begining of the "for loop"
+
+    for(;it_index!=itend_index;it_index++,it_values++) {
+      write = CreateTerm(WRITE,width,write,*it_index,*it_values);
+      write.SetIndexWidth(indexwidth);
+    }
+
+    output = CreateTerm(READ,width,write,readIndex);
+    UpdateSimplifyMap(term,output,false);
+    return output;
+  } //end of SimplifyWrites_In_Place() 
+
+  //accepts a read over a write and returns a term without the write
+  //READ(WRITE(A i val) j) <==> ITE(i=j,val,READ(A,j)). We use a memo
+  //table for this function called RemoveWritesMemoMap
+  ASTNode BeevMgr::RemoveWrites(const ASTNode& input) {   
+    //unsigned int width = input.GetValueWidth();
+    if(READ != input.GetKind() || WRITE != input[0].GetKind()) {
+      FatalError("RemovesWrites: Input must be a READ over a WRITE",input);
+    }
+
+    ASTNodeMap::iterator it;
+    ASTNode output = input;
+    if(CheckSimplifyMap(input,output,false)) {
+      return output;
+    }
+        
+    if(!start_abstracting && Begin_RemoveWrites) {
+      output= ReadOverWrite_To_ITE(input);
+    }
+
+    if(start_abstracting) {
+      ASTNode newVar;
+      if(!CheckSimplifyMap(input,newVar,false)) {
+	newVar = NewVar(input.GetValueWidth());
+	ReadOverWrite_NewName_Map[input] = newVar;
+	NewName_ReadOverWrite_Map[newVar] = input;
+
+	UpdateSimplifyMap(input,newVar,false);
+	ASTNodeStats("New Var Name which replace Read_Over_Write: ", newVar);
+      }
+      output = newVar;
+    } //end of start_abstracting if condition
+
+    //memoize
+    UpdateSimplifyMap(input,output,false);
+    return output;
+  } //end of RemoveWrites()
+
+  ASTNode BeevMgr::ReadOverWrite_To_ITE(const ASTNode& term) {
+    unsigned int width = term.GetValueWidth();
+    ASTNode input = term;
+    if(READ != term.GetKind() || WRITE != term[0].GetKind()) {
+      FatalError("RemovesWrites: Input must be a READ over a WRITE",term);
+    }
+
+    ASTNodeMap::iterator it;
+    ASTNode output;
+    // if(CheckSimplifyMap(term,output,false)) {
+    //       return output;
+    //     }
+    
+    ASTNode partialITE = term;
+    ASTNode writeA = ASTTrue;
+    ASTNode oldRead = term;
+    //iteratively expand read-over-write
+    do {
+      ASTNode write = input[0];
+      ASTNode readIndex = SimplifyTerm(input[1]);
+      //DO NOT CALL SimplifyTerm() on write[0]. You will go into an
+      //infinite loop
+      writeA = write[0];
+      ASTNode writeIndex = SimplifyTerm(write[1]);
+      ASTNode writeVal = SimplifyTerm(write[2]);
+      
+      ASTNode cond = SimplifyFormula(CreateSimplifiedEQ(writeIndex,readIndex),false);
+      ASTNode newRead = CreateTerm(READ,width,writeA,readIndex);
+      ASTNode newRead_memoized = newRead;
+      if(CheckSimplifyMap(newRead, newRead_memoized,false)) {
+	newRead = newRead_memoized;
+      }
+      
+      if(ASTTrue == cond && (term == partialITE)) {
+	//found the write-value in the first iteration itself. return
+	//it
+	output = writeVal;
+	UpdateSimplifyMap(term,output,false);
+	return output;
+      }
+      
+      if(READ == partialITE.GetKind() && WRITE == partialITE[0].GetKind()) {
+	//first iteration or (previous cond==ASTFALSE and partialITE is a "READ over WRITE")
+	partialITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
+      }
+      else if (ITE == partialITE.GetKind()){
+	//ITE(i1 = j, v1, R(A,j))
+	ASTNode ElseITE = CreateSimplifiedTermITE(cond, writeVal, newRead);
+	//R(W(A,i1,v1),j) <==> ITE(i1 = j, v1, R(A,j))
+	UpdateSimplifyMap(oldRead,ElseITE,false);
+	//ITE(i2 = j, v2, R(W(A,i1,v1),j)) <==> ITE(i2 = j, v2, ITE(i1 = j, v1, R(A,j)))
+	partialITE = SimplifyTerm(partialITE);
+      }
+      else {
+	FatalError("RemoveWrites: Control should not reach here\n");
+      }
+      
+      if(ASTTrue == cond) {
+	//no more iterations required
+	output = partialITE;
+	UpdateSimplifyMap(term,output,false);
+	return output;
+      }
+      
+      input = newRead;
+      oldRead = newRead;
+    } while(READ == input.GetKind() && WRITE == input[0].GetKind());
+    
+    output = partialITE;
+    
+    //memoize
+    //UpdateSimplifyMap(term,output,false);
+    return output;
+  } //ReadOverWrite_To_ITE()
+
+  //compute the multiplicative inverse of the input
+  ASTNode BeevMgr::MultiplicativeInverse(const ASTNode& d) {
+    ASTNode c = d;
+    if(BVCONST != c.GetKind()) {
+      FatalError("Input must be a constant", c);
+    }
+
+    if(!BVConstIsOdd(c)) {
+      FatalError("MultiplicativeInverse: Input must be odd: ",c);
+    }
+    
+    //cerr << "input to multinverse function is: " << d << endl;
+    ASTNode inverse;
+    if(CheckMultInverseMap(d,inverse)) {
+      //cerr << "found the inverse of: " << d << "and it is: " << inverse << endl;
+      return inverse;
+    }
+
+    inverse = c;
+    unsigned inputwidth = c.GetValueWidth();
+
+#ifdef NATIVE_C_ARITH
+    ASTNode one = CreateOneConst(inputwidth);
+    while(c != one) {
+      //c = c*c
+      c = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,c,c));
+      //inverse = invsere*c
+      inverse = BVConstEvaluator(CreateTerm(BVMULT,inputwidth,inverse,c));
+    }
+#else
+    //Compute the multiplicative inverse of c using the extended
+    //euclidian algorithm
+    //
+    //create a '0' which is 1 bit long
+    ASTNode onebit_zero = CreateZeroConst(1);
+    //zero pad t0, i.e. 0 @ t0
+    c = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,c));
+
+    //construct 2^(inputwidth), i.e. a bitvector of length
+    //'inputwidth+1', which is max(inputwidth)+1
+    //
+    //all 1's 
+    ASTNode max = CreateMaxConst(inputwidth);
+    //zero pad max
+    max = BVConstEvaluator(CreateTerm(BVCONCAT,inputwidth+1,onebit_zero,max));
+    //Create a '1' which has leading zeros of length 'inputwidth'
+    ASTNode inputwidthplusone_one = CreateOneConst(inputwidth+1);    
+    //add 1 to max
+    max = CreateTerm(BVPLUS,inputwidth+1,max,inputwidthplusone_one);
+    max = BVConstEvaluator(max);
+    
+    ASTNode zero = CreateZeroConst(inputwidth+1);
+    ASTNode max_bvgt_0 = CreateNode(BVGT,max,zero);
+    ASTNode quotient, remainder;
+    ASTNode x, x1, x2;
+
+    //x1 initialized to zero
+    x1 = zero;
+    //x2 initialized to one
+    x2 = CreateOneConst(inputwidth+1);
+    while (ASTTrue == BVConstEvaluator(max_bvgt_0)) {
+      //quotient = (c divided by max)
+      quotient = BVConstEvaluator(CreateTerm(BVDIV,inputwidth+1, c, max));
+
+      //remainder of (c divided by max)
+      remainder = BVConstEvaluator(CreateTerm(BVMOD,inputwidth+1, c, max));
+
+      //x = x2 - q*x1
+      x = CreateTerm(BVSUB,inputwidth+1,x2,CreateTerm(BVMULT,inputwidth+1,quotient,x1));
+      x = BVConstEvaluator(x);
+
+      //fix the inputs to the extended euclidian algo
+      c = max;
+      max = remainder;
+      max_bvgt_0 = CreateNode(BVGT,max,zero);
+      
+      x2 = x1;
+      x1 = x;
+    }
+    
+    ASTNode hi = CreateBVConst(32,inputwidth-1);
+    ASTNode low = CreateZeroConst(32);
+    inverse = CreateTerm(BVEXTRACT,inputwidth,x2,hi,low);
+    inverse = BVConstEvaluator(inverse);
+#endif
+
+    UpdateMultInverseMap(d,inverse);
+    //cerr << "output of multinverse function is: " << inverse << endl;
+    return inverse;
+  } //end of MultiplicativeInverse()
+
+  //returns true if the input is odd
+  bool BeevMgr::BVConstIsOdd(const ASTNode& c) {
+    if(BVCONST != c.GetKind()) {
+      FatalError("Input must be a constant", c);
+    }
+   
+    ASTNode zero = CreateZeroConst(1);
+    ASTNode hi = CreateZeroConst(32);
+    ASTNode low = hi;
+    ASTNode lowestbit = CreateTerm(BVEXTRACT,1,c,hi,low);
+    lowestbit =  BVConstEvaluator(lowestbit);
+
+    if(lowestbit == zero) {
+      return false;
+    }
+    else {
+      return true;
+    }
+  } //end of BVConstIsOdd()
+
+  //The big substitution function
+  ASTNode BeevMgr::CreateSubstitutionMap(const ASTNode& a){
+    if(!optimize)
+      return a;
+
+    ASTNode output = a;
+    //if the variable has been solved for, then simply return it
+    if(CheckSolverMap(a,output))
+      return output;
+
+    //traverse a and populate the SubstitutionMap 
+    Kind k = a.GetKind();
+    if(SYMBOL == k && BOOLEAN_TYPE == a.GetType()) {
+      bool updated = UpdateSubstitutionMap(a,ASTTrue);
+      output = updated ? ASTTrue : a;      
+      return output;          
+    }
+    if(NOT == k
+       && SYMBOL == a[0].GetKind()) {
+      bool updated = UpdateSubstitutionMap(a[0],ASTFalse);
+      output = updated ? ASTTrue : a;      
+      return output;          
+    }
+    
+    if(IFF == k) {
+      ASTVec c = a.GetChildren();
+      SortByExprNum(c);
+      if(SYMBOL != c[0].GetKind() || 
+    	 VarSeenInTerm(c[0],SimplifyFormula_NoRemoveWrites(c[1],false))) {
+	return a;
+      }
+      bool updated = UpdateSubstitutionMap(c[0],c[1]);
+      output = updated ? ASTTrue : a;      
+      return output;      
+    }
+    
+    if(EQ == k) {
+      //fill the arrayname readindices vector if e0 is a
+      //READ(Arr,index) and index is a BVCONST
+      ASTVec c = a.GetChildren();
+      SortByExprNum(c);
+      FillUp_ArrReadIndex_Vec(c[0],c[1]);
+
+      if(SYMBOL == c[0].GetKind() && 
+	 VarSeenInTerm(c[0],SimplifyTerm(c[1]))) {
+	return a;
+      }
+
+      if(1 == TermOrder(c[0],c[1]) &&
+	 READ == c[0].GetKind() &&
+	 VarSeenInTerm(c[0][0],SimplifyTerm(c[1]))) {
+	return a;
+      }
+      bool updated = UpdateSubstitutionMap(c[0],c[1]);      
+      output = updated ? ASTTrue : a;      
+      return output;      
+    }
+
+    if(AND == k){
+      ASTVec o;
+      ASTVec c = a.GetChildren();
+      for(ASTVec::iterator it = c.begin(),itend=c.end();it!=itend;it++) {
+	UpdateAlwaysTrueFormMap(*it);
+	ASTNode aaa = CreateSubstitutionMap(*it);
+	
+	if(ASTTrue != aaa) {
+	  if(ASTFalse == aaa)
+	    return ASTFalse;
+	  else
+	    o.push_back(aaa);
+	}
+      }
+      if(o.size() == 0)
+	return ASTTrue;
+
+      if(o.size() == 1)
+	return o[0];
+      
+      return CreateNode(AND,o);
+    }
+    return output;
+  } //end of CreateSubstitutionMap()
+
+
+  bool BeevMgr::VarSeenInTerm(const ASTNode& var, const ASTNode& term) {
+    if(READ == term.GetKind() && 
+       WRITE == term[0].GetKind() && !Begin_RemoveWrites) {
+      return false;
+    }
+
+    if(READ == term.GetKind() && 
+       WRITE == term[0].GetKind() && Begin_RemoveWrites) {
+      return true;
+    }
+
+    ASTNodeMap::iterator it;    
+    if((it = TermsAlreadySeenMap.find(term)) != TermsAlreadySeenMap.end()) {
+      if(it->second == var) {
+	return false;
+      }
+    }
+
+    if(var == term) {
+      return true;
+    }
+
+    for(ASTVec::const_iterator it=term.begin(),itend=term.end();it!=itend;it++){
+      if(VarSeenInTerm(var,*it)) {
+	return true;
+      }
+      else {
+	TermsAlreadySeenMap[*it] = var;
+      }
+    }
+
+    TermsAlreadySeenMap[term] = var;
+    return false;
+  }
+};//end of namespace