about summary refs log tree commit diff homepage
path: root/stp/simplifier/bvsolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'stp/simplifier/bvsolver.cpp')
-rw-r--r--stp/simplifier/bvsolver.cpp714
1 files changed, 0 insertions, 714 deletions
diff --git a/stp/simplifier/bvsolver.cpp b/stp/simplifier/bvsolver.cpp
deleted file mode 100644
index 369251db..00000000
--- a/stp/simplifier/bvsolver.cpp
+++ /dev/null
@@ -1,714 +0,0 @@
-/********************************************************************
- * 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