Beispiel #1
0
bool PropagateEqualities::searchTerm(const ASTNode& lhs, const ASTNode& rhs)
{
  const unsigned width = lhs.GetValueWidth();

  if (lhs == rhs)
    return true;

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

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

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

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

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

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

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

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

  return false;
}
int
ASTPiecewiseFunctionNode::addChild(ASTBase* child, bool inRead)
{
  // now here what I want to do is just keep track of the number
  // of children being added so the mNumPiece and mHasOtherwise
  // variables can be given appropriate values

  // but not if we are reading a stream because then we already know

  if (inRead == false)
  {
    if (child->getType() != AST_CONSTRUCTOR_PIECE && 
        child->getType() != AST_CONSTRUCTOR_OTHERWISE)
    {
      // this child does not have a piece/otherwise but if 
      // the rest of the function does then it needs to fit in with that

      unsigned int currentNum = getNumChildren();

      if (usingChildConstructors() == false)
      {
        if ((currentNum+1)%2 == 0)
        {
          setNumPiece(getNumPiece()+1);
          setHasOtherwise(false);
        }
        else
        {
          setHasOtherwise(true);
        }
     
        return ASTFunctionBase::addChild(child);
      }
      else
      {
        ASTBase * lastChild = 
          ASTFunctionBase::getChild(ASTFunctionBase::getNumChildren()-1);
        if (lastChild == NULL)
        { // we have a serious issue going on but may as well just
          // add the child
          return ASTFunctionBase::addChild(child);
        }
        else if (lastChild->getType() == AST_CONSTRUCTOR_PIECE)
        {
          ASTNode * piece = dynamic_cast<ASTNode*>(lastChild);

          if (piece == NULL)
          {
            return LIBSBML_OPERATION_FAILED;
          }
          if (piece->getNumChildren() == 1)
          {
            return piece->addChild((ASTNode*)(child));
          }
          else
          {
            ASTNode * otherwise = new ASTNode(AST_CONSTRUCTOR_OTHERWISE);
            if (otherwise->addChild((ASTNode*)(child)) == LIBSBML_OPERATION_SUCCESS)
            {
              setHasOtherwise(true);
              return ASTFunctionBase::addChild(otherwise);
            }
            else
            {
              return LIBSBML_OPERATION_FAILED;
            }
          }
        }
        else
        {
          ASTNode * otherwise = dynamic_cast<ASTNode*>(lastChild);

          if (otherwise == NULL || otherwise->getNumChildren() != 1)
          {
            return LIBSBML_OPERATION_FAILED;
          }

          ASTNode * piece = new ASTNode(AST_CONSTRUCTOR_PIECE);
          // add teh child from teh otherwise
          if (piece->addChild(otherwise->getChild(0)) != LIBSBML_OPERATION_SUCCESS)
          {
            return LIBSBML_OPERATION_FAILED;
          }
          else
          {
            if (piece->addChild((ASTNode*)(child)) == LIBSBML_OPERATION_SUCCESS)
            {
              this->removeChild(currentNum-1);
              setHasOtherwise(false);
              setNumPiece(getNumPiece() + 1);
              return ASTFunctionBase::addChild(piece);
            }
            else
            {
              return LIBSBML_OPERATION_FAILED;
            }
          }
        }
      }
    }
    else
    {
      if (child->getType() == AST_CONSTRUCTOR_PIECE)
      {
        setNumPiece(getNumPiece()+1);
      }
      else
      {
        setHasOtherwise(true);
      }
    
      return ASTFunctionBase::addChild(child);
    }
  }
  else
  {
    return ASTFunctionBase::addChild(child);
  }
}
int 
ASTPiecewiseFunctionNode::removeChild(unsigned int n)
{
  int removed = LIBSBML_INDEX_EXCEEDS_SIZE;
  /* HACK TO REPLICATE OLD AST */
  /* do not return a node with teh piece or otherwise type
   * return the correct child of the piece type
   * or the child of the otherwise
   */

  unsigned int numChildren = ASTFunctionBase::getNumChildren();
  // determine index that we actually want
  unsigned int childNo = (unsigned int)(n/2);
  unsigned int pieceIndex = (unsigned int)(n%2);
  unsigned int size = getNumChildren();
  if (size == 0)
  {
    return LIBSBML_OPERATION_FAILED;
  }

  if (n < size)
  {
    if (getHasOtherwise() == true && childNo == numChildren - 1)
    {
      removed = ASTFunctionBase::removeChild(childNo);
      mHasOtherwise = false;
    }
    else if (ASTFunctionBase::getChild(childNo)->getType() 
                                                 == AST_CONSTRUCTOR_PIECE)
    {
      ASTBase * base = ASTFunctionBase::getChild(childNo);
      ASTNode * piece = dynamic_cast<ASTNode*>(base);

      if (piece != NULL)
      {
        if (piece->getNumChildren() > pieceIndex)
        {
          removed = piece->removeChild(pieceIndex);
          if (removed == LIBSBML_OPERATION_SUCCESS &&
            piece->getNumChildren() == 0)
          {
            removed = this->ASTFunctionBase::removeChild(childNo);
            mNumPiece = mNumPiece - 1;
          }
        }
        else
        {
          removed = LIBSBML_OPERATION_FAILED;
        }
      }
      else
      {
        removed = LIBSBML_OPERATION_FAILED;
      }
    }
    else if (n < numChildren)
    {
      removed =  ASTFunctionBase::removeChild(n);
    }
    else
    {
      removed = LIBSBML_OPERATION_FAILED;
    }
  }

  return removed;
}
Beispiel #4
0
  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;
  }
bool
ASTNaryFunctionNode::isLog10() const
{
  bool valid = false;

  if (getType() == AST_FUNCTION_LOG)
  {
    // a log can have either one child that is not the logbase qualifier
    // or two where teh first is the logbase of 10
    if (getNumChildren() == 1)
    {
      ASTBase * base1 = ASTFunctionBase::getChild(0);
      if (base1->isQualifier() == false)
      {
        valid = true;
      }
    }
    else if (getNumChildren() == 2)
    {
      ASTBase * base1 = ASTFunctionBase::getChild(0);
      ASTFunction* fun = dynamic_cast<ASTFunction*>(base1);
      if (fun != NULL)
      {
        if (fun->getType() == AST_QUALIFIER_LOGBASE
          && fun->getNumChildren() == 1)
        {
          ASTBase *base2 = fun->getChild(0);
          if (base2->getType() == AST_INTEGER)
          {
            ASTNumber *child = static_cast<ASTNumber*>(base2);
            if (child->getInteger() == 10)
            {
              valid = true;
            }
          }
        }
      }
      else
      {
        // here we are working the ASTNode so the casting
        // is more difficult

        ASTNode* newAST = dynamic_cast<ASTNode*>(base1);
        if (newAST != NULL && newAST->getType() == AST_QUALIFIER_LOGBASE
          && newAST->getNumChildren() == 1 )
        {
          ASTNode* newAST1 = newAST->getChild(0);
          if (newAST1->getType() == AST_INTEGER)
          {
            if (newAST1->getInteger() == 10)
            {
              valid = true;
            }
          }
        }
        else
        {
          if (newAST != NULL && newAST->getType() == AST_INTEGER)
          {
            if (newAST->getInteger() == 10)
            {
              valid = true;
            }
          }
        }

      }
    }
  }

  return valid;
}
Beispiel #6
0
int Submodel::convertTimeAndExtentWith(const ASTNode* tcf, const ASTNode* xcf, const ASTNode* klmod)
{
  if (tcf==NULL && xcf==NULL) return LIBSBML_OPERATION_SUCCESS;
  Model* model = getInstantiation();
  if (model==NULL) {
    //getInstantiation sets its own error messages.
    return LIBSBML_OPERATION_FAILED;
  }
  ASTNode* tcftimes = NULL;
  ASTNode* tcfdiv = NULL;
  if (tcf != NULL) {
    tcftimes = new ASTNode(AST_TIMES);
    tcftimes->addChild(tcf->deepCopy());
    tcfdiv = new ASTNode(AST_DIVIDE);
    tcfdiv->addChild(tcf->deepCopy());
  }
  ASTNode* rxndivide = NULL;
  if (klmod != NULL) {
    rxndivide = new ASTNode(AST_DIVIDE);
    ASTNode rxnref(AST_NAME);
    rxndivide->addChild(rxnref.deepCopy());
    rxndivide->addChild(klmod->deepCopy());
  }
  List* allelements = model->getAllElements();
  for (unsigned int el=0; el<allelements->getSize(); el++) {
    SBase* element = static_cast<SBase*>(allelements->get(el));
    assert(element != NULL);
    ASTNode* ast1 = NULL;
    ASTNode* ast2 = NULL;
    Constraint* constraint = NULL;
    Delay* delay = NULL;
    EventAssignment* ea = NULL;
    InitialAssignment* ia = NULL;
    KineticLaw* kl = NULL;
    Priority* priority = NULL;
    RateRule* rrule = NULL;
    Rule* rule = NULL;
    Submodel* submodel = NULL;
    Trigger* trigger = NULL;
    string cf = "";
    //Reaction math will be converted below, in the bits with the kinetic law.  But because of that, we need to handle references *to* the reaction:  even if it has no kinetic law, the units have changed, and this needs to be reflected by the flattening routine.
    if (rxndivide != NULL && element->getTypeCode()==SBML_REACTION && element->isSetId()) {
      rxndivide->getChild(0)->setName(element->getId().c_str());
      for (unsigned int sube=0; sube<allelements->getSize(); sube++) {
        SBase* subelement = static_cast<SBase*>(allelements->get(sube));
        subelement->replaceSIDWithFunction(element->getId(), rxndivide);
      }
    }

    //Submodels need their timeConversionFactor and extentConversionFactor attributes converted.  We're moving top-down, so all we need to do here is fix the conversion factor attributes themselves, pointing them to new parameters if need be.
    if ((tcf !=NULL || xcf != NULL) && element->getTypeCode()==SBML_COMP_SUBMODEL) {
      submodel = static_cast<Submodel*>(element);
      if (tcf != NULL) {
        if (submodel->isSetTimeConversionFactor()) {
          createNewConversionFactor(cf, tcf, submodel->getTimeConversionFactor(), model);
          submodel->setTimeConversionFactor(cf);
        }
        else {
          submodel->setTimeConversionFactor(tcf->getName());
        }
      }
      if (xcf != NULL) {
        if (submodel->isSetExtentConversionFactor()) {
          createNewConversionFactor(cf, xcf, submodel->getExtentConversionFactor(), model);
          submodel->setExtentConversionFactor(cf);
        }
        else {
          submodel->setExtentConversionFactor(xcf->getName());
        }
      }
    }
    if (tcf==NULL) {
      if (klmod !=NULL && element->getTypeCode()==SBML_KINETIC_LAW) {
        kl = static_cast<KineticLaw*>(element);
        if (kl->isSetMath()) {
          ast1 = new ASTNode(AST_TIMES);
          ast1->addChild(klmod->deepCopy());
          ast1->addChild(kl->getMath()->deepCopy());
          kl->setMath(ast1);
          delete ast1;
        }
      }
    }
    else {
      // All math 'time' and 'delay' csymbols must still be converted.
      // Also, several constructs are modified directly.
      switch(element->getTypeCode()) {
        //This would be a WHOLE LOT SIMPLER if there was a 'hasMath' class in libsbml.  But even so, it would have to
        // handle the kinetic laws, rate rules, and delays separately.
      case SBML_KINETIC_LAW:
        //Kinetic laws are multiplied by 'klmod'.
        kl = static_cast<KineticLaw*>(element);
        ast1 = kl->getMath()->deepCopy();
        convertCSymbols(ast1, tcfdiv, tcftimes);
        if (klmod !=NULL) {
          kl = static_cast<KineticLaw*>(element);
          if (kl->isSetMath()) {
            ast2 = new ASTNode(AST_TIMES);
            ast2->addChild(klmod->deepCopy());
            ast2->addChild(ast1);
            kl->setMath(ast2);
            delete ast2;
          }
        }
        else {
          kl->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_DELAY:
        //Delays are multiplied by the time conversion factor.
        delay = static_cast<Delay*>(element);
        if (delay->isSetMath()) {
          ast1 = delay->getMath()->deepCopy();
          convertCSymbols(ast1, tcfdiv, tcftimes);
          tcftimes->addChild(ast1);
          delay->setMath(tcftimes);
          tcftimes->removeChild(1);
        }
        break;
      case SBML_RATE_RULE:
        //Rate rules are divided by the time conversion factor.
        rrule = static_cast<RateRule*>(element);
        if (rrule->isSetMath()) {
          ast1 = rrule->getMath()->deepCopy();
          tcfdiv->insertChild(0, rrule->getMath()->deepCopy());
          rrule->setMath(tcfdiv);
          tcfdiv->removeChild(0);
        }
        //Fall through to:
      case SBML_ASSIGNMENT_RULE:
      case SBML_ALGEBRAIC_RULE:
        //Rules in general need csymbols converted.
        rule = static_cast<Rule*>(element);
        if (rule->isSetMath()) {
          ast1 = rule->getMath()->deepCopy();
          convertCSymbols(ast1, tcfdiv, tcftimes);
          rule->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_EVENT_ASSIGNMENT:
        //Event assignments need csymbols converted.
        ea = static_cast<EventAssignment*>(element);
        if (ea->isSetMath()) {
          ast1 = ea->getMath()->deepCopy();
          convertCSymbols(ast1, tcfdiv, tcftimes);
          ea->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_INITIAL_ASSIGNMENT:
        //Initial assignments need csymbols converted.
        ia = static_cast<InitialAssignment*>(element);
        if (ia->isSetMath()) {
          ast1 = ia->getMath()->deepCopy();
          convertCSymbols(ast1, tcfdiv, tcftimes);
          ia->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_CONSTRAINT:
        //Constraints need csymbols converted.
        constraint = static_cast<Constraint*>(element);
        if (constraint->isSetMath()) {
          ast1 = constraint->getMath()->deepCopy();
          convertCSymbols(ast1, tcfdiv, tcftimes);
          constraint->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_PRIORITY:
        //Priorities need csymbols converted.
        priority = static_cast<Priority*>(element);
        if (priority->isSetMath()) {
          ast1 = priority->getMath()->deepCopy();
          convertCSymbols(ast1, tcfdiv, tcftimes);
          priority->setMath(ast1);
          delete ast1;
        }
        break;
      case SBML_TRIGGER:
        //Triggers need csymbols converted.
        trigger = static_cast<Trigger*>(element);
        if (trigger->isSetMath()) {
          ast1 = trigger->getMath()->deepCopy();
          convertCSymbols(ast1, tcfdiv, tcftimes);
          trigger->setMath(ast1);
          delete ast1;
        }
        break;
      default:
        //Do nothing!  If we wanted to call a plugin routine, this would be the place.  The only other alternative is to #ifdef some code in here that deals with the math-containing package objects explicitly.  Which might be the best option, all told.
        break;
      }
    }
  }

  delete allelements;

  return LIBSBML_OPERATION_SUCCESS;
}
Beispiel #7
0
  /* 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.
   *
   * If this returns, this ALWAYS returns true. If there is an error it
   * will call FatalError() and abort.
   */
  bool BVTypeCheck(const ASTNode& n)
  {
    Kind k = n.GetKind();
    //The children of bitvector terms are in turn bitvectors.
    const 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 true;
          case ITE:
  			if (n.Degree() != 3)
  				FatalError("BVTypeCheck: should have exactly 3 args\n", n);
        	if (BOOLEAN_TYPE != n[0].GetType() || (n[1].GetType() != 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.GetChildren().size() !=2)
              FatalError("2 params to 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);
              }
            if (ARRAY_TYPE != n[0].GetType())
              FatalError("First parameter to read should be an array", n[0]);
            if (BITVECTOR_TYPE != n[1].GetType())
              FatalError("Second parameter to read should be a bitvector", n[1]);
            break;
          case WRITE:
            if (n.GetChildren().size() !=3)
              FatalError("3 params to 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);
            if (ARRAY_TYPE != n[0].GetType())
              FatalError("First parameter to read should be an array", n[0]);
            if (BITVECTOR_TYPE != n[1].GetType())
              FatalError("Second parameter to read should be a bitvector", n[1]);
            if (BITVECTOR_TYPE != n[2].GetType())
              FatalError("Third parameter to read should be a bitvector", n[2]);

            break;

          case BVDIV:
          case BVMOD:
          case BVSUB:

          case SBVDIV:
          case SBVREM:
          case SBVMOD:

          case BVLEFTSHIFT:
          case BVRIGHTSHIFT:
          case BVSRSHIFT:
          case BVVARSHIFT:
        	  if (n.Degree() != 2)
        		  FatalError("BVTypeCheck: should have exactly 2 args\n", n);
        	  // run on.
          case BVOR:
          case BVAND:
          case BVXOR:
          case BVNOR:
          case BVNAND:
          case BVXNOR:

          case BVPLUS:
          case BVMULT:
            {
              if (!(v.size() >= 2))
                FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have at least two arguments\n", n);
              unsigned int width = n.GetValueWidth();
              for (ASTVec::const_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:
          case BVZX:
			//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: BV[SZ]X(t,bv[sz]x_len) : length of 't' must be <= bv[sz]x_len\n",
						n);
			}
			if ((v.size() != 2))
				FatalError(
						"BVTypeCheck:BV[SZ]X must have two arguments. The second is the new width\n",
						n);
			break;

		case BVCONCAT:
			checkChildrenAreBV(v, n);
			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:
			checkChildrenAreBV(v, n);
			if (n.Degree() != 1)
				FatalError("BVTypeCheck: should have exactly 1 args\n", n);
			break;
		case BVEXTRACT:
			checkChildrenAreBV(v, n);
			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() != n[1].GetUnsignedConst()
					- n[2].GetUnsignedConst() + 1)
				FatalError("BVTypeCheck: length mismatch\n", n);
			if (n[1].GetUnsignedConst() >= n[0].GetValueWidth())
				FatalError(
						"BVTypeCheck: Top index of select is greater or equal to the bitwidth.\n",
						n);
			break;
		default:
			cerr << _kind_names[k];
			FatalError("No type checking for type");
			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 true;
          case PARAMBOOL:
            if(2 != n.Degree())
              FatalError("BVTypeCheck: PARAMBOOL formula can have exactly two childNodes", n);
            break;
          case EQ:
  			if (n.Degree() != 2)
  				FatalError("BVTypeCheck: should have exactly 2 args\n", n);
        	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 (n.Degree() != 2)
  				FatalError("BVTypeCheck: should have exactly 2 args\n", n);
            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;
          case FOR:
            //FIXME: Todo
            break;
          default:
            FatalError("BVTypeCheck: Unrecognized kind: ");
            break;
          }
      }
    return true;
  } //End of TypeCheck function
Beispiel #8
0
  /********************************************************
   * TransformFormula()
   *
   * Get rid of DIV/MODs, ARRAY read/writes, FOR constructs
   ********************************************************/
  ASTNode ArrayTransformer::TransformFormula(const ASTNode& simpleForm)
  {
    assert(TransformMap != NULL);

    const 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::const_iterator iter;
    if ((iter = TransformMap->find(simpleForm)) != TransformMap->end())
      return iter->second;

    ASTNode result;

    switch (k)
      {
      case TRUE:
      case FALSE:
        {
          result = simpleForm;
          break;
        }
      case NOT:
        {
          ASTVec c;
          c.push_back(TransformFormula(simpleForm[0]));
          result = nf->CreateNode(NOT, c);
          break;
        }
      case BOOLEXTRACT:
        {
          ASTVec c;
          c.push_back(TransformTerm(simpleForm[0]));
          c.push_back(simpleForm[1]);
          result = nf->CreateNode(BOOLEXTRACT, c);
          break;
        }
      case BVLT:
      case BVLE:
      case BVGT:
      case BVGE:
      case BVSLT:
      case BVSLE:
      case BVSGT:
      case BVSGE:
        {
          ASTVec c;
          c.push_back(TransformTerm(simpleForm[0]));
          c.push_back(TransformTerm(simpleForm[1]));
          result = nf->CreateNode(k, c);
          break;
        }
      case EQ:
        {
          ASTNode term1 = TransformTerm(simpleForm[0]);
          ASTNode term2 = TransformTerm(simpleForm[1]);
          if (bm->UserFlags.optimize_flag)
        	  result = simp->CreateSimplifiedEQ(term1, term2);
          else
        	  result = nf->CreateNode(EQ,term1, term2);
          break;
        }
      case AND: // These could shortcut. Not sure if the extra effort is justified.
      case OR:
      case NAND:
      case NOR:
      case IFF:
      case XOR:
      case ITE:
      case IMPLIES:
        {
          ASTVec vec;
          vec.reserve(simpleForm.Degree());

          for (ASTVec::const_iterator 
                 it = simpleForm.begin(), 
                 itend = simpleForm.end(); it != itend; it++)
            {
              vec.push_back(TransformFormula(*it));
            }

          result = nf->CreateNode(k, vec);
          break;
        }
      case PARAMBOOL:
        {
          //If the parameteric boolean variable is of the form
          //VAR(const), then convert it into a Boolean variable of the
          //form "VAR(const)".
          //
          //Else if the paramteric boolean variable is of the form
          //VAR(expression), then simply return it
          if(BVCONST == simpleForm[1].GetKind())
            {
              result = 
                bm->NewParameterized_BooleanVar(simpleForm[0],simpleForm[1]);
            }
          else
            {
              result = simpleForm;
            }
          break;
        }
      default:
        {
          if (k == SYMBOL && BOOLEAN_TYPE == simpleForm.GetType())
            result = simpleForm;
          else
            {
              FatalError("TransformFormula: Illegal kind: ", 
                         ASTUndefined, k);
              std::cerr << "The input is: " << simpleForm << std::endl;
              std::cerr << "The valuewidth of input is : " 
                   << simpleForm.GetValueWidth() << std::endl;
            }
          break;
        }
      } //end of Switch

    assert(!result.IsNull());
    if (simpleForm.Degree() > 0)
      (*TransformMap)[simpleForm] = result;
    return result;
  } //End of TransformFormula
Beispiel #9
0
  ASTNode ArrayTransformer::TransformTerm(const ASTNode& term)
  {
    assert(TransformMap != NULL);

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

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

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

    if (term.Degree() > 0)
      (*TransformMap)[term] = result;
    if (term.GetValueWidth() != result.GetValueWidth())
      FatalError("TransformTerm: "\
                 "result and input terms are of different length", result);
    if (term.GetIndexWidth() != result.GetIndexWidth())
      {
        std::cerr << "TransformTerm: input term is : " << term << std::endl;
        FatalError("TransformTerm: "\
                   "result & input terms have different index length", result);
      }
    return result;
  } //End of TransformTerm
/*
 * Checks the MathML of the ASTnode 
 * is appropriate for the function being performed
 *
 * If an inconsistency is found, an error message is logged.
 */
void
NumericArgsMathCheck::checkMath (const Model& m, const ASTNode& node, const SBase & sb)
{
  // does not apply in L3V2 for general consistency checking
  // BUT we want to use it for telling a converter that this occurs in L3V2
  if (this->mValidator.getCategory() == LIBSBML_CAT_MATHML_CONSISTENCY)
  {
    if (m.getLevel() == 3 && m.getVersion() > 1) return;
  }
  else
  {
    if (m.getLevel() != 3) return;
    else if (m.getVersion() == 1) return;
  }

  ASTNodeType_t type = node.getType();

  switch (type) 
  {
    case AST_PLUS:
    case AST_MINUS:
    case AST_TIMES:
    case AST_DIVIDE:
    case AST_POWER:
    case AST_FUNCTION_POWER:
    case AST_FUNCTION_ROOT:
    case AST_FUNCTION_ABS:
    case AST_FUNCTION_EXP:
    case AST_FUNCTION_LN:
    case AST_FUNCTION_LOG:
    case AST_FUNCTION_CEILING:
    case AST_FUNCTION_FLOOR:
    case AST_FUNCTION_FACTORIAL:
    case AST_FUNCTION_COS:
    case AST_FUNCTION_COT:
    case AST_FUNCTION_CSC:
    case AST_FUNCTION_SEC:
    case AST_FUNCTION_SIN:
    case AST_FUNCTION_TAN: 
    case AST_FUNCTION_COSH:
    case AST_FUNCTION_COTH:
    case AST_FUNCTION_CSCH:
    case AST_FUNCTION_SECH:
    case AST_FUNCTION_SINH:
    case AST_FUNCTION_TANH: 
    case AST_FUNCTION_ARCCOSH:
    case AST_FUNCTION_ARCCOTH:
    case AST_FUNCTION_ARCCSCH:
    case AST_FUNCTION_ARCSECH:
    case AST_FUNCTION_ARCSINH:
    case AST_FUNCTION_ARCTANH:
    case AST_FUNCTION_ARCCOS:
    case AST_FUNCTION_ARCCOT:
    case AST_FUNCTION_ARCCSC:
    case AST_FUNCTION_ARCSEC:
    case AST_FUNCTION_ARCSIN:
    case AST_FUNCTION_ARCTAN: 

      checkNumericArgs(m, node, sb);
      break;


    case AST_FUNCTION:

      checkFunction(m, node, sb);
      break;

    default:

      checkChildren(m, node, sb);
      break;

  }
}
Beispiel #11
0
  //Translates signed BVDIV,BVMOD and BVREM into unsigned variety
  ASTNode ArrayTransformer::TranslateSignedDivModRem(const ASTNode& in,  NodeFactory* nf, STPMgr *bm)
  {
    assert(in.GetChildren().size() ==2);

    const ASTNode& dividend = in[0];
    const ASTNode& divisor = in[1];
    const unsigned len = in.GetValueWidth();

    ASTNode hi1 = bm->CreateBVConst(32, len - 1);
    ASTNode one = bm->CreateOneConst(1);
    ASTNode zero = bm->CreateZeroConst(1);
    // create the condition for the dividend
    ASTNode cond_dividend = 
      nf->CreateNode(EQ, one, nf->CreateTerm(BVEXTRACT, 1, dividend, hi1, hi1));
    // create the condition for the divisor
    ASTNode cond_divisor = 
      nf->CreateNode(EQ, one,
                     nf->CreateTerm(BVEXTRACT, 1, divisor, hi1, hi1));

    if (SBVREM == in.GetKind())
      {
        //BVMOD is an expensive operation. So have the fewest bvmods
        //possible. Just one.

        //Take absolute value.
        ASTNode pos_dividend = 
          nf->CreateTerm(ITE, len,
                         cond_dividend, 
                         nf->CreateTerm(BVUMINUS, len, dividend),
                         dividend);
        ASTNode pos_divisor = 
          nf->CreateTerm(ITE, len,
                         cond_divisor, 
                         nf->CreateTerm(BVUMINUS, len, divisor),
                         divisor);

        //create the modulus term
        ASTNode modnode = 
          nf->CreateTerm(BVMOD, len,
                         pos_dividend, pos_divisor);

        //If the dividend is <0 take the unary minus.
        ASTNode n = 
          nf->CreateTerm(ITE, len,
                         cond_dividend, 
                         nf->CreateTerm(BVUMINUS, len, modnode),
                         modnode);
        	return n;
      }

    // This is the modulus of dividing rounding to -infinity.
    else if (SBVMOD == in.GetKind())
      {

    	/*
			(bvsmod s t) abbreviates
				  (let ((?msb_s ((_ extract |m-1| |m-1|) s))
						(?msb_t ((_ extract |m-1| |m-1|) t)))
					(let ((abs_s (ite (= ?msb_s #b0) s (bvneg s)))
						  (abs_t (ite (= ?msb_t #b0) t (bvneg t))))
					  (let ((u (bvurem abs_s abs_t)))
						(ite (= u (_ bv0 m))
							 u
						(ite (and (= ?msb_s #b0) (= ?msb_t #b0))
							 u
						(ite (and (= ?msb_s #b1) (= ?msb_t #b0))
							 (bvadd (bvneg u) t)
						(ite (and (= ?msb_s #b0) (= ?msb_t #b1))
							 (bvadd u t)
							 (bvneg u))))))))
    	 */

        //Take absolute value.
        ASTNode pos_dividend = 
          nf->CreateTerm(ITE, len,
                         cond_dividend, 
                         nf->CreateTerm(BVUMINUS, len, dividend),
                         dividend);
        ASTNode pos_divisor = 
          nf->CreateTerm(ITE, len,
                         cond_divisor, 
                         nf->CreateTerm(BVUMINUS, len, divisor),
                         divisor);

        ASTNode urem_node = 
          nf->CreateTerm(BVMOD, len,
                         pos_dividend, pos_divisor);

        // If the dividend is <0, then we negate the whole thing.
        ASTNode rev_node = 
          nf->CreateTerm(ITE, len,
                         cond_dividend, 
                         nf->CreateTerm(BVUMINUS, len, urem_node),
                         urem_node);

        // if It's XOR <0, and it doesn't perfectly divide, then add t (not its absolute value).
        ASTNode xor_node = 
          nf->CreateNode(XOR, cond_dividend, cond_divisor);
        ASTNode neZ = nf->CreateNode(NOT, nf->CreateNode(EQ, rev_node, bm->CreateZeroConst(divisor.GetValueWidth())));
        ASTNode cond = nf->CreateNode(AND,xor_node ,neZ);
        ASTNode n = 
          nf->CreateTerm(ITE, len,
        		  cond,
                         nf->CreateTerm(BVPLUS, len, rev_node, divisor),
                         rev_node);

        	return n;
      }
    else if (SBVDIV == in.GetKind())
      {
        //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)

        //Take absolute value.
        ASTNode pos_dividend = 
          nf->CreateTerm(ITE, len,
                         cond_dividend, 
                         nf->CreateTerm(BVUMINUS, len, dividend),
                         dividend);
        ASTNode pos_divisor = 
          nf->CreateTerm(ITE, len,
                         cond_divisor, 
                         nf->CreateTerm(BVUMINUS, len, divisor),
                         divisor);

        ASTNode divnode = 
          nf->CreateTerm(BVDIV, len, pos_dividend, pos_divisor);

        // A little confusing. Only negate the result if they are XOR <0.
        ASTNode xor_node = 
          nf->CreateNode(XOR, cond_dividend, cond_divisor);
        ASTNode n = 
          nf->CreateTerm(ITE, len,
                         xor_node, 
                         nf->CreateTerm(BVUMINUS, len, divnode),
                         divnode);

        	return n;
      }

    FatalError("TranslateSignedDivModRem:"\
               "input must be signed DIV/MOD/REM", in);
    return bm->ASTUndefined;

  }//end of TranslateSignedDivModRem()
Beispiel #12
0
void dealWithL1Stoichiometry(Model & m, bool l2)
{
  unsigned int idCount = 0;
  char newid[15];
  std::string id;

  for (unsigned int i = 0; i < m.getNumReactions(); i++)
  {
    Reaction *r = m.getReaction(i);
    unsigned int j;

    for (j = 0; j < r->getNumReactants(); j++)
    {
      SpeciesReference *sr = r->getReactant(j);
      if (sr->getDenominator() != 1)
      {
        long stoich = static_cast<long>(sr->getStoichiometry());
        int denom = sr->getDenominator();
        ASTNode *node = new ASTNode();
        node->setValue(stoich, denom);   
        if (l2 == true)
        {
          StoichiometryMath * sm = sr->createStoichiometryMath();
          sm->setMath(node);
        }
        else
        {
          sprintf(newid, "speciesRefId_%u", idCount);
          id.assign(newid);
          idCount++;
          sr->setId(id);
          InitialAssignment * ar = m.createInitialAssignment();
          ar->setSymbol(id);
          ar->setMath(node);
          sr->unsetStoichiometry();
        }
      }
    }
    for (j = 0; j < r->getNumProducts(); j++)
    {
      SpeciesReference *sr = r->getProduct(j);
      if (sr->getDenominator() != 1)
      {
        long stoich = static_cast<long>(sr->getStoichiometry());
        int denom = sr->getDenominator();
        ASTNode *node = new ASTNode();
        node->setValue(stoich, denom);   
        if (l2 == true)
        {
          StoichiometryMath * sm = sr->createStoichiometryMath();
          sm->setMath(node);
        }
        else
        {
          sprintf(newid, "speciesRefId_%u", idCount);
          id.assign(newid);
          idCount++;
          sr->setId(id);
          InitialAssignment * ar = m.createInitialAssignment();
          ar->setSymbol(id);
          ar->setMath(node);
          sr->unsetStoichiometry();
        }
      }
    }
  }
}
END_TEST


START_TEST(test_SBMLTransforms_evaluateAST)
{
  double temp;
  ASTNode * node = new ASTNode();
  node->setValue((int)(2));
  
  fail_unless(SBMLTransforms::evaluateASTNode(node) == 2);

  node->setValue((double) (3.2));

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 3.2));

  node->setValue((long)(1), (long)(4));

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.25));

  node->setValue((double) (4.234), (int) (2));

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 423.4));

  node->setType(AST_NAME_AVOGADRO);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 6.02214179e23));

  node->setType(AST_NAME_TIME);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node->setType(AST_NAME);

  fail_unless(isnan(SBMLTransforms::evaluateASTNode(node)));

  node->setType(AST_CONSTANT_E);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), exp(1.0)));

  node->setType(AST_CONSTANT_FALSE);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node->setType(AST_CONSTANT_PI);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 4.0*atan(1.0)));

  node->setType(AST_CONSTANT_TRUE);

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("2.5 + 6.1");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 8.6));

  node = SBML_parseFormula("-4.3");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), -4.3));

  node = SBML_parseFormula("9.2-4.3");

  temp = 9.2-4.3;
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("2*3");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 6));

  node = SBML_parseFormula("1/5");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.2));

  node = SBML_parseFormula("pow(2, 3)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 8));

  node = SBML_parseFormula("3^3");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 27));

  node = SBML_parseFormula("abs(-9.456)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 9.456));

  node = SBML_parseFormula("ceil(9.456)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 10));

  node = SBML_parseFormula("exp(2.0)");
  
  temp = exp(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("floor(2.04567)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 2));

  node = SBML_parseFormula("ln(2.0)");

  temp = log(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("log10(100.0)");

  temp = log10(100.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sin(2.0)");

  temp = sin(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("cos(4.1)");

  temp = cos(4.1);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("tan(0.345)");

  temp = tan(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsin(0.456)");

  temp = asin(0.456);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccos(0.41)");

  temp = acos(0.41);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arctan(0.345)");

  temp = atan(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sinh(2.0)");

  temp = sinh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("cosh(4.1)");

  temp = cosh(4.1);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("tanh(0.345)");

  temp = tanh(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("and(1, 0)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("or(1, 0)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("not(1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("xor(1, 0)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("xor(1, 1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("eq(1, 2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("eq(1, 1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("geq(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("geq(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("geq(2,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("gt(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("gt(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("leq(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("leq(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("leq(2,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("lt(2,1)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("lt(2,4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));
  
  node = SBML_parseFormula("neq(2,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 0.0));

  node = SBML_parseFormula("neq(3,2)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 1.0));

  node = SBML_parseFormula("cot(2.0)");

  temp = 1.0/tan(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("csc(4.1)");

  temp = 1.0/sin(4.1);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("sec(0.345)");

  temp = 1.0/cos(0.345);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("coth(2.0)");

  temp = cosh(2.0)/sinh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));
  
  node = SBML_parseFormula("sech(2.0)");

  temp = 1.0/cosh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("csch(2.0)");

  temp = 1.0/sinh(2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccot(2.0)");

  temp = atan(1/2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccsc(2.0)");

  temp = asin(1/2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsec(2.0)");

  temp = acos(1/2.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccosh(2.0)");

  temp = log(2.0 + pow(3.0, 0.5));
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arccoth(2.0)");

  temp = 0.5 * log(3.0);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsech(0.2)");

  temp = log(2*pow(6, 0.5)+5);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));
  
  node = SBML_parseFormula("arccsch(0.2)");

  /* temp = log(5 +pow(26, 0.5));
   * only matches to 15 dp and therefore fails !!
   */
  temp = 2.312438341272753;
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arcsinh(3.0)");

  temp = log(3.0 +pow(10.0, 0.5));
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node = SBML_parseFormula("arctanh(0.2)");

  temp = 0.5 * log(1.5);
  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), temp));

  node->setType(AST_FUNCTION_DELAY);

  fail_unless(isnan(SBMLTransforms::evaluateASTNode(node)));

  node = SBML_parseFormula("factorial(3)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 6));
  
  node->setType(AST_FUNCTION_PIECEWISE);

  fail_unless(isnan(SBMLTransforms::evaluateASTNode(node)));

  node = SBML_parseFormula("root(2, 4)");

  fail_unless(equalDouble(SBMLTransforms::evaluateASTNode(node), 2));
  
}
Beispiel #14
0
string Bench_Print1(ostream& os, const ASTNode& n,
                    map<ASTNode, string>* alreadyOutput)
{

  assert(((n.GetKind() == SYMBOL) || (n.GetKind() == BVCONST) ||
          n.GetValueWidth() <= 1));
  assert(!n.IsNull());

  map<ASTNode, string>::iterator it;
  if ((it = alreadyOutput->find(n)) != alreadyOutput->end())
    return it->second;

  if (n.GetKind() == BVCONST)
  {
    (*alreadyOutput)[n] = bvconstToString(n);
    return (*alreadyOutput)[n];
  }

  if (n.GetKind() == SYMBOL)
  {
    (*alreadyOutput)[n] = symbolToString(n);
    return (*alreadyOutput)[n];
  }

  if (n.GetKind() == TRUE)
  {
    return "vdd";
  }

  if (n.GetKind() == FALSE)
  {
    return "gnd";
  }

  if (n.GetKind() == BOOLEXTRACT)
  {
    assert(n[1].GetKind() == BVCONST);
    std::stringstream nn;
    nn << Bench_Print1(os, n[0], alreadyOutput) << "_"
       << Bench_Print1(os, n[1], alreadyOutput);
    (*alreadyOutput)[n] = nn.str();
    return (*alreadyOutput)[n];
  }

  std::stringstream nodeNameSS;
  nodeNameSS << "n" << n.GetNodeNum();

  string thisNode = nodeNameSS.str();
  (*alreadyOutput)[n] = thisNode;

  assert(n.Degree() > 0);
  std::stringstream output;

  // The bench format doesn't accept propositional ITEs.
  if (n.GetKind() == ITE)
  {
    assert(n.Degree() == 3);
    string p = Bench_Print1(os, n[0], alreadyOutput);
    string p1 = Bench_Print1(os, n[1], alreadyOutput);
    string p2 = Bench_Print1(os, n[2], alreadyOutput);

    os << thisNode << "_1 = AND(" << p << "," << p1 << ")" << endl;
    os << thisNode << "_2"
       << " = NOT(" << p << ")," << endl;
    os << thisNode << "_3"
       << " = AND(" << thisNode << "_2"
       << "," << p2 << ")" << endl;
    os << thisNode << "="
       << "OR(," << thisNode << "_1"
       << "," << thisNode << "_3)" << endl;
  }
  else
  {
    if (n.Degree() > 2)
    {
      assert(n.GetKind() == AND || n.GetKind() == XOR ||
             n.GetKind() == OR); // must be associative.
      std::deque<string> names;

      for (unsigned i = 0; i < n.Degree(); i++)
        names.push_back(Bench_Print1(os, n[i], alreadyOutput));

      int id = 0;

      while (names.size() > 2)
      {
        string a = names.front();
        names.pop_front();

        string b = names.front();
        names.pop_front();

        std::stringstream thisName;
        thisName << thisNode << "___" << id++;

        output << thisName.str() << "=" << name(n.GetKind()) << "(" << a << ","
               << b << ")" << endl;

        names.push_back(thisName.str());
      }

      assert(names.size() == 2);
      // last two now.

      string a = names.front();
      names.pop_front();
      string b = names.front();
      names.pop_front();

      output << thisNode << "=" << name(n.GetKind()) << "(" << a << "," << b
             << ")" << endl;
      os << output.str();
    }
    else
    {
      output << thisNode << "=" << name(n.GetKind()) << "(";
      for (unsigned i = 0; i < n.Degree(); i++)
      {
        if (i >= 1)
          output << " , ";
        output << Bench_Print1(os, n[i], alreadyOutput);
      }
      os << output.str() << ")" << endl;
    }
  }
  return thisNode;
}
bool CodeGeneratorVisitor::performStep(ASTNode& node)
{
   node.accept(*this);

   return true;
}
Beispiel #16
0
  /* 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)
   *
   */
  ASTNode ArrayTransformer::TransformArrayRead(const ASTNode& term)
  {
    assert(TransformMap != NULL);

    const unsigned int width = term.GetValueWidth();

    if (READ != term.GetKind())
      return term;

    ASTNodeMap::const_iterator iter;
    if ((iter = TransformMap->find(term)) != TransformMap->end())
      return iter->second;

    //'term' is of the form READ(arrName, readIndex)
    const ASTNode & arrName = term[0];
    const ASTNode & readIndex = TransformTerm(term[1]);

    ASTNode result;

    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)
           *
           *                        .....
           */

          {
            ArrType::const_iterator it;
            if ((it = arrayToIndexToRead.find(arrName)) != arrayToIndexToRead.end())
              {
                std::map<ASTNode, ArrayRead>::const_iterator it2;
                  if ((it2 = it->second.find(readIndex)) != it->second.end())
                    {
                      result = it2->second.ite;
                      break;
                    }
              }
          }

          // Make up a new abstract variable. Build symbolic name
          // corresponding to array read. The symbolic name has 2
          // components: stringname, and a count

          ASTNode CurrentSymbol = bm->CreateFreshVariable(
                          term.GetIndexWidth(),
                          term.GetValueWidth(),
                          "array_" + string(arrName.GetName()));

          result = CurrentSymbol;

          if (!bm->UserFlags.ackermannisation)
            {
              // result is a variable here; it is an ite in the
              // else-branch
            }
          else if (bm->UserFlags.isSet("old_ack","0"))
            {

            /* oops.
             * This version of ack. doesn't do what I thought it did. The STP 0.1 version of Ack. produces simpler
             * expressions. I've put that in the next block. Trevor's thesis measures AckITE using this implementation,
             * rather than the next one like it should have!!!!
             */

              // Full Array transform if we're not doing read refinement.

              //list of array-read indices corresponding to arrName, seen while
              //traversing the AST tree. we need this list to construct the ITEs
              const arrTypeMap& new_read_Indices = arrayToIndexToRead[arrName];

              arrTypeMap::const_iterator it2 = new_read_Indices.begin();
              arrTypeMap::const_iterator it2end = new_read_Indices.end();
              for (; it2 != it2end; it2++)
                {
                  ASTNode cond =  simp->CreateSimplifiedEQ(readIndex, it2->first);
                  if (ASTFalse == cond)
                    continue;

                  if (ASTTrue == cond)
                    {
                      result = it2->second.ite;
                      break;
                    }

                  result =
                    simp->CreateSimplifiedTermITE(cond, it2->second.ite, result);
                }
            }
          else
           {
            // Full Array transform if we're not doing read refinement.

            //list of array-read indices corresponding to arrName, seen while
            //traversing the AST tree. we need this list to construct the ITEs
            vector<std::pair<ASTNode, ASTNode > > p = ack_pair[arrName];

            vector<std::pair<ASTNode, ASTNode > >::const_reverse_iterator it2 = p.rbegin();
            vector<std::pair<ASTNode, ASTNode > >::const_reverse_iterator it2end = p.rend();
            for (; it2 != it2end; it2++)
              {
                ASTNode cond =  simp->CreateSimplifiedEQ(readIndex, it2->first);
                if (ASTFalse == cond)
                  continue;

                if (ASTTrue == cond)
                  {
                    result = it2->second;
                    break;
                  }

                result =
                  simp->CreateSimplifiedTermITE(cond, it2->second, result);
              }

           ack_pair[arrName].push_back(make_pair(readIndex,CurrentSymbol));
           }

          assert(arrName.GetType() == ARRAY_TYPE);
          arrayToIndexToRead[arrName].insert(make_pair(readIndex,ArrayRead (result, CurrentSymbol)));
          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 j))
           */

          /* 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 writeIndex = TransformTerm(arrName[1]);
          ASTNode writeVal = TransformTerm(arrName[2]);

          if (ARRAY_TYPE != arrName[0].GetType())
            FatalError("TransformArray: "\
                       "An array write is being attempted on a non-array:", 
                       term);

          //if ((SYMBOL == arrName[0].GetKind()
               //|| WRITE == arrName[0].GetKind()))
            {
              ASTNode cond = 
                simp->CreateSimplifiedEQ(writeIndex, readIndex);
              assert(BVTypeCheck(cond));

              // If the condition is true, it saves iteratively transforming through
              // all the (possibly nested) arrays.
              if (ASTTrue == cond)
              {
            	  result = writeVal;
              }
              else
              {
				  ASTNode readTerm =
					nf->CreateTerm(READ, width, arrName[0], readIndex);
				  assert(BVTypeCheck(readTerm));

				  // The simplifying node factory may have produced
				  // something that's not a READ.
				  ASTNode readPushedIn = TransformTerm(readTerm);
				  assert(BVTypeCheck(readPushedIn));

				  result =
					simp->CreateSimplifiedTermITE(cond, writeVal, readPushedIn);
              }
            }

            // Trevor: I've removed this code because I don't see the advantage in working
            // inside out. i.e. transforming read(write(ite(p,A,B),i,j),k), into
            // read(ite(p,write(A,i,j),write(B,i,j),k). That is bringing up the ite.
            // Without this code it will become: ite(i=k, j, read(ite(p,A,B),k))

            #if 0
          else if (ITE == arrName[0].GetKind())
            {
              // pull out the ite from the write // pushes the write
              // through.
              ASTNode writeTrue =
                nf->CreateNode(WRITE, (arrName[0][1]), writeIndex, writeVal);
              writeTrue.SetIndexWidth(writeIndex.GetValueWidth());
              writeTrue.SetValueWidth(writeVal.GetValueWidth());
              assert(ARRAY_TYPE == writeTrue.GetType());

              ASTNode writeFalse = 
                nf->CreateNode(WRITE, (arrName[0][2]), writeIndex, writeVal);
              writeFalse.SetIndexWidth(writeIndex.GetValueWidth());
              writeFalse.SetValueWidth(writeVal.GetValueWidth());
              assert(ARRAY_TYPE == writeFalse.GetType());

              result =  (writeTrue == writeFalse) ?
                writeTrue : simp->CreateSimplifiedTermITE(TransformFormula(arrName[0][0]),
                                              writeTrue, writeFalse);
              result.SetIndexWidth(writeIndex.GetValueWidth());
              result.SetValueWidth(writeVal.GetValueWidth());
              assert(ARRAY_TYPE == result.GetType());

              result = 
                nf->CreateTerm(READ, writeVal.GetValueWidth(),
                               result, readIndex);
              BVTypeCheck(result);
              result = TransformArrayRead(result);
            }
          else
            FatalError("TransformArray: Write over bad type.");
	#endif
          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))
           */

          // pull out the ite from the read // pushes the read through.

          //(ITE cond thn els)

          ASTNode cond = arrName[0];
          cond = TransformFormula(cond);

          const ASTNode& thn = arrName[1];
          const ASTNode& els = arrName[2];

		  //(READ thn j)
		  ASTNode thnRead = nf->CreateTerm(READ, width, thn, readIndex);
		  assert(BVTypeCheck(thnRead));

		  //(READ els j)
		  ASTNode elsRead = nf->CreateTerm(READ, width, els, readIndex);
		  assert(BVTypeCheck(elsRead));

		  /* We try to call TransformTerm only if necessary, because it
		   * introduces a new symbol for each read. The amount of work we
		   * need to do later is based on the square of the number of symbols.
		   */
          if (ASTTrue == cond)
          {
			  result = TransformTerm(thnRead);
          }
          else if (ASTFalse == cond)
          {
			  result = TransformTerm(elsRead);
          }
          else
          {
			  thnRead = TransformTerm(thnRead);
			  elsRead = TransformTerm(elsRead);

			  //(ITE cond (READ thn j) (READ els j))
			  result = simp->CreateSimplifiedTermITE(cond, thnRead, elsRead);
		  }
          break;
        }
      default:
        FatalError("TransformArray: "\
                   "The READ is NOT over SYMBOL/WRITE/ITE", term);
        break;
      }
/*
 * Checks that all variables referenced in FunctionDefinition bodies are
 * bound variables (function arguments).
 */
void
FunctionDefinitionVars::check_ (const Model& m, const FunctionDefinition& fd)
{
  if ( fd.getLevel() == 1         ) return;
  if ( !fd.isSetMath()            ) return;
  if ( fd.getBody()  == NULL      ) return;
  //if (  fd.getNumArguments() == 0 ) return;


  List* variables = fd.getBody()->getListOfNodes( ASTNode_isName );


  for (unsigned int n = 0; n < variables->getSize(); ++n)
  {
    ASTNode* node = static_cast<ASTNode*>( variables->get(n) );
    string   name = node->getName() ? node->getName() : "";

    if ( fd.getArgument(name) == NULL ) 
    {
      /* if this is the csymbol time - technically it is allowed 
       * in L2v1 and L2v2
       */
      if (node->getType() == AST_NAME_TIME)
      {
        if (fd.getLevel() > 2
          || (fd.getLevel() == 2 && fd.getVersion() > 2))
        {
          logUndefined(fd, name);
        }
      }
      else
      {
        logUndefined(fd, name);
      }
    }
  }

  if ((m.getLevel() == 2 && m.getVersion() == 5)
    || (m.getLevel() == 3 && m.getVersion() > 1))
  { // check we dont use delay csymbol
    delete variables;
    variables = fd.getBody()->getListOfNodes( ASTNode_isFunction );
    
    for (unsigned int n = 0; n < variables->getSize(); ++n)
    {
      ASTNode* node = static_cast<ASTNode*>( variables->get(n) );

      if (node->getType() == AST_FUNCTION_DELAY)
      {
        logUndefined(fd, node->getName());
      }
    }
  }


  //Check we don't use a function defined in a plugin (like rateOf)
  delete variables;
  variables = fd.getBody()->getListOfNodes(ASTNode_isFunction);

  for (unsigned int n = 0; n < variables->getSize(); ++n)
  {
    ASTNode* node = static_cast<ASTNode*>(variables->get(n));

    const ASTBasePlugin* plugin = node->getASTPlugin(node->getType());
    if (plugin != NULL)
    {
      if (plugin->allowedInFunctionDefinition(node->getType()) == 0)
      {
        logUndefined(fd, node->getName());
      }
    }
  }
  delete variables;
}
void 
AssignmentCycles::checkForImplicitCompartmentReference(const Model& m)
{
  mIdMap.clear();

  unsigned int i, ns;
  std::string id;

  for (i = 0; i < m.getNumInitialAssignments(); i++)
  {
    if (m.getInitialAssignment(i)->isSetMath())
    {
      id = m.getInitialAssignment(i)->getSymbol();
      if (m.getCompartment(id) 
        && m.getCompartment(id)->getSpatialDimensions() > 0)
      {
        List* variables = m.getInitialAssignment(i)->getMath()
                                        ->getListOfNodes( ASTNode_isName );
        for (ns = 0; ns < variables->getSize(); ns++)
        {
          ASTNode* node = static_cast<ASTNode*>( variables->get(ns) );
          string   name = node->getName() ? node->getName() : "";
          if (!name.empty() && !alreadyExistsInMap(mIdMap, pair<const std::string, std::string>(id, name)))
            mIdMap.insert(pair<const std::string, std::string>(id, name));
        }
        delete variables;
      }
    }
  }

  for (i = 0; i < m.getNumRules(); i++)
  {
    if (m.getRule(i)->isSetMath() && m.getRule(i)->isAssignment())
    {
      id = m.getRule(i)->getVariable();
      if (m.getCompartment(id) 
        && m.getCompartment(id)->getSpatialDimensions() > 0)
      {
        List* variables = m.getRule(i)->getMath()->getListOfNodes( ASTNode_isName );
        for (ns = 0; ns < variables->getSize(); ns++)
        {
          ASTNode* node = static_cast<ASTNode*>( variables->get(ns) );
          string   name = node->getName() ? node->getName() : "";
          if (!name.empty() && !alreadyExistsInMap(mIdMap, pair<const std::string, std::string>(id, name)))
            mIdMap.insert(pair<const std::string, std::string>(id, name));
        }
        delete variables;
      }
    }
  }

  IdIter it;
  IdRange range;

  for (i = 0; i < m.getNumCompartments(); i++)
  {
    std::string id = m.getCompartment(i)->getId();
    range = mIdMap.equal_range(id);
    for (it = range.first; it != range.second; it++)
    {
      const Species *s = m.getSpecies((*it).second);
      if (s && s->getCompartment() == id
        && s->getHasOnlySubstanceUnits() == false)
      {
        logImplicitReference(m, id, s);
      }
    }
  }
}
Beispiel #19
0
/** @cond doxygenLibsbmlInternal */
int 
Replacing::updateIDs(SBase* oldnames, SBase* newnames)
{
  int ret = LIBSBML_OPERATION_SUCCESS;
  SBMLDocument* doc = getSBMLDocument();
  if (oldnames->isSetId() && !newnames->isSetId()) {
    if (doc) {
      string error = "Unable to transform IDs in Replacing::updateIDs during replacement:  the '" + oldnames->getId() + "' element's replacement does not have an ID set.";
      doc->getErrorLog()->logPackageError("comp", CompMustReplaceIDs, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_OBJECT;
  }
  if (oldnames->isSetMetaId() && !newnames->isSetMetaId()) {
    if (doc) {
      string error = "Unable to transform IDs in Replacing::updateIDs during replacement:  the replacement of the element with metaid '" + oldnames->getMetaId() + "' does not have a metaid.";
      doc->getErrorLog()->logPackageError("comp", CompMustReplaceMetaIDs, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_OBJECT;
  }
  //LS DEBUG Somehow we need to check identifiers from other packages here (like spatial id's).  How, exactly, is anyone's guess.
  Model* replacedmod = const_cast<Model*>(CompBase::getParentModel(oldnames));
  KineticLaw* replacedkl;
  ASTNode newkl;
  if (replacedmod==NULL) {
    if (doc) {
      string error = "Unable to transform IDs in Replacing::updateIDs during replacement:  the replacement of '" + oldnames->getId() + "' does not have a valid model.";
      doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn());
    }
    return LIBSBML_INVALID_OBJECT;
  }
  List* allElements = replacedmod->getAllElements();
  string oldid = oldnames->getId();
  string newid = newnames->getId();
  if (!oldid.empty()) {
    switch(oldnames->getTypeCode()) {
    case SBML_UNIT_DEFINITION:
      replacedmod->renameUnitSIdRefs(oldid, newid);
      for (unsigned int e=0; e<allElements->getSize(); e++) {
        SBase* element = static_cast<SBase*>(allElements->get(e));
        element->renameUnitSIdRefs(oldid, newid);
      }
      break;
    case SBML_LOCAL_PARAMETER:
      replacedkl = static_cast<KineticLaw*>(oldnames->getAncestorOfType(SBML_KINETIC_LAW));
      if (replacedkl->isSetMath()) {
        newkl = *replacedkl->getMath();
        newkl.renameSIdRefs(oldid, newid);
        replacedkl->setMath(&newkl);
      }
      break;
    case SBML_COMP_PORT:
      break;
      //LS DEBUG And here is where we would need some sort of way to check if the id wasn't an SId for some objects.
    default:
      replacedmod->renameSIdRefs(oldnames->getId(), newnames->getId());
      for (unsigned int e=0; e<allElements->getSize(); e++) {
        SBase* element = static_cast<SBase*>(allElements->get(e));
        element->renameSIdRefs(oldid, newid);
      }
    }
  }
  string oldmetaid = oldnames->getMetaId();
  string newmetaid = newnames->getMetaId();
  if (oldnames->isSetMetaId()) {
    replacedmod->renameMetaIdRefs(oldmetaid, newmetaid);
    for (unsigned int e=0; e<allElements->getSize(); e++) {
      SBase* element = static_cast<SBase*>(allElements->get(e));
      element->renameMetaIdRefs(oldmetaid, newmetaid);
    }
  }
  //LS DEBUG And here is where we would need some sort of way to check for ids that were not 'id' or 'metaid'.
  delete allElements;
  return ret;
}
/*
  * Checks that the units of the piecewise function are consistent
  *
  * If inconsistent units are found, an error message is logged.
  */
void 
ArgumentsUnitsCheck::checkUnitsFromPiecewise (const Model& m, 
                                        const ASTNode& node, 
                                        const SBase & sb, bool inKL, int reactNo)
{
  /* check that node has children */
  if (node.getNumChildren() == 0)
  {
    return;
  }

  /* piecewise(a0, a1, a2, a3, ...)
   * a0 and a2, a(n_even) must have same units
   * a1, a3, a(n_odd) must be dimensionless
   */
  unsigned int n;
  UnitDefinition *dim = new UnitDefinition(m.getSBMLNamespaces());
  Unit *unit = new Unit(m.getSBMLNamespaces());
  unit->setKind(UNIT_KIND_DIMENSIONLESS);
  unit->initDefaults();
  UnitDefinition * tempUD;
  UnitDefinition * tempUD1 = NULL;
  dim->addUnit(unit);
  
  UnitFormulaFormatter *unitFormat = new UnitFormulaFormatter(&m);

  tempUD = unitFormat->getUnitDefinition(node.getChild(0), inKL, reactNo);

  for(n = 2; n < node.getNumChildren(); n+=2)
  {
    tempUD1 = unitFormat->getUnitDefinition(node.getChild(n), inKL, reactNo);
  
    if (!unitFormat->getContainsUndeclaredUnits())
    {
      if (!UnitDefinition::areEquivalent(tempUD, tempUD1)) 
      {
        logInconsistentPiecewise(node, sb);
      }
    }
    delete tempUD1;
  }

  delete tempUD;

  for(n = 1; n < node.getNumChildren(); n+=2)
  {
    tempUD = unitFormat->getUnitDefinition(node.getChild(n), inKL, reactNo);

    if (!UnitDefinition::areEquivalent(tempUD, dim)) 
    {
      logInconsistentPiecewiseCondition(node, sb);
    }
    delete tempUD;
  }
 
  delete dim;
  delete unit;
  delete unitFormat;

  for(n = 0; n < node.getNumChildren(); n++)
  {
    checkUnits(m, *node.getChild(n), sb, inKL, reactNo);
  }

}
Beispiel #21
0
  // helper function for printing C code (copied from PL_Print1())
  void C_Print1(ostream& os, const ASTNode n, int indentation, bool letize)
  {

    unsigned int upper, lower, num_bytes;
    Kind LHSkind, RHSkind;

    //os << spaces(indentation);
    //os << endl << spaces(indentation);
    if (!n.IsDefined())
      {
        os << "<undefined>";
        return;
      }

    //if this node is present in the letvar Map, then print the letvar
    STPMgr *bm = n.GetSTPMgr();

    //this is to print letvars for shared subterms inside the printing
    //of "(LET v0 = term1, v1=term1@term2,...
    if ((bm->NodeLetVarMap1.find(n) != bm->NodeLetVarMap1.end()) && !letize)
      {
        C_Print1(os, (bm->NodeLetVarMap1[n]), indentation, letize);
        return;
      }

    //this is to print letvars for shared subterms inside the actual
    //term to be printed
    if ((bm->NodeLetVarMap.find(n) != bm->NodeLetVarMap.end()) && letize)
      {
        C_Print1(os, (bm->NodeLetVarMap[n]), indentation, letize);
        return;
      }

    //otherwise print it normally
    Kind kind = n.GetKind();
    const ASTVec &c = n.GetChildren();
    switch (kind)
      {
      case BOOLEXTRACT:
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        C_Print1(os, c[0], indentation, letize);
        os << "{";
        C_Print1(os, c[1], indentation, letize);
        os << "}";
        break;
      case BITVECTOR:
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        os << "BITVECTOR(";
        unsigned char * str;
        str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
        os << str << ")";
        CONSTANTBV::BitVector_Dispose(str);
        break;
      case BOOLEAN:
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        os << "BOOLEAN";
        break;
      case FALSE:
        os << "0";
        break;
      case TRUE:
        os << "1";
        break;
      case BVCONST:
      case SYMBOL:
        // print in C friendly format:
        n.nodeprint(os, true);
        break;
      case READ:
        C_Print1(os, c[0], indentation, letize);
        os << "[";
        C_Print1(os, c[1], indentation, letize);
        os << "]";
        break;
      case WRITE:
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " WITH [";
        C_Print1(os, c[1], indentation, letize);
        os << "] := ";
        C_Print1(os, c[2], indentation, letize);
        os << ")";
        os << endl;
        break;
      case BVUMINUS:
        os << kind << "( ";
        C_Print1(os, c[0], indentation, letize);
        os << ")";
        break;
      case NOT:
        os << "!(";
        C_Print1(os, c[0], indentation, letize);
        os << ") " << endl;
        break;
      case BVNEG:
        os << " ~(";
        C_Print1(os, c[0], indentation, letize);
        os << ")";
        break;
      case BVCONCAT:
        // stopgap for un-implemented features
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " @ ";
        C_Print1(os, c[1], indentation, letize);
        os << ")" << endl;
        break;
      case BVOR:
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " | ";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVAND:
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " & ";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVEXTRACT:

        // we only accept indices that are byte-aligned
        // (e.g., [15:8], [23:16])
        // and round down to byte indices rather than bit indices
        upper = c[1].GetUnsignedConst();
        lower = c[2].GetUnsignedConst();
        assert(upper > lower);
        assert(lower % 8 == 0);
        assert((upper + 1) % 8 == 0);
        num_bytes = (upper - lower + 1) / 8;
        assert (num_bytes > 0);

        // for multi-byte extraction, use the ADDRESS
        if (num_bytes > 1)
          {
            os << "&";
            C_Print1(os, c[0], indentation, letize);
            os << "[" << lower / 8 << "]";
          }
        // for single-byte extraction, use the VALUE
        else
          {
            C_Print1(os, c[0], indentation, letize);
            os << "[" << lower / 8 << "]";
          }

        break;
      case BVLEFTSHIFT:
        // stopgap for un-implemented features
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " << ";
        os << c[1].GetUnsignedConst();
        os << ")";
        break;
      case BVRIGHTSHIFT:
        // stopgap for un-implemented features
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << " >> ";
        os << c[1].GetUnsignedConst();
        os << ")";
        break;
      case BVMULT:
      case BVSUB:
      case BVPLUS:
      case SBVDIV:
      case SBVREM:
      case BVDIV:
      case BVMOD:
        os << kind << "(";
        os << n.GetValueWidth();
        for (ASTVec::const_iterator
               it = c.begin(), itend = c.end(); it != itend; it++)
          {
            os << ", " << endl;
            C_Print1(os, *it, indentation, letize);
          }
        os << ")" << endl;
        break;
      case ITE:
        os << "if (";
        C_Print1(os, c[0], indentation, letize);
        os << ")" << endl;
        os << "{";
        C_Print1(os, c[1], indentation, letize);
        os << endl << "} else {";
        C_Print1(os, c[2], indentation, letize);
        os << endl << "}";
        break;
      case BVLT:
        // convert to UNSIGNED before doing comparison!
        os << "((unsigned char)";
        C_Print1(os, c[0], indentation, letize);
        os << " < ";
        os << "(unsigned char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVLE:
        // convert to UNSIGNED before doing comparison!
        os << "((unsigned char)";
        C_Print1(os, c[0], indentation, letize);
        os << " <= ";
        os << "(unsigned char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVGT:
        // convert to UNSIGNED before doing comparison!
        os << "((unsigned char)";
        C_Print1(os, c[0], indentation, letize);
        os << " > ";
        os << "(unsigned char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVGE:
        // convert to UNSIGNED before doing comparison!
        os << "((unsigned char)";
        C_Print1(os, c[0], indentation, letize);
        os << " >= ";
        os << "(unsigned char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVXOR:
      case BVNAND:
      case BVNOR:
      case BVXNOR:
        // stopgap for un-implemented features
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        break;
      case BVSLT:
        // convert to SIGNED before doing comparison!
        os << "((signed char)";
        C_Print1(os, c[0], indentation, letize);
        os << " < ";
        os << "(signed char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVSLE:
        // convert to SIGNED before doing comparison!
        os << "((signed char)";
        C_Print1(os, c[0], indentation, letize);
        os << " <= ";
        os << "(signed char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVSGT:
        // convert to SIGNED before doing comparison!
        os << "((signed char)";
        C_Print1(os, c[0], indentation, letize);
        os << " > ";
        os << "(signed char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case BVSGE:
        // convert to SIGNED before doing comparison!
        os << "((signed char)";
        C_Print1(os, c[0], indentation, letize);
        os << " >= ";
        os << "(signed char)";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        break;
      case EQ:
        // tricky tricky ... if it's a single-byte comparison,
        // simply do ==, but if it's multi-byte, must do memcmp
        LHSkind = c[0].GetKind();
        RHSkind = c[1].GetKind();

        num_bytes = 0;

        // try to figure out whether it's a single-byte or multi-byte
        // comparison
        if (LHSkind == BVEXTRACT)
          {
            upper = c[0].GetChildren()[1].GetUnsignedConst();
            lower = c[0].GetChildren()[2].GetUnsignedConst();
            num_bytes = (upper - lower + 1) / 8;
          }
        else if (RHSkind == BVEXTRACT)
          {
            upper = c[1].GetChildren()[1].GetUnsignedConst();
            lower = c[1].GetChildren()[2].GetUnsignedConst();
            num_bytes = (upper - lower + 1) / 8;
          }

        if (num_bytes > 1)
          {
            os << "(memcmp(";
            C_Print1(os, c[0], indentation, letize);
            os << ", ";
            C_Print1(os, c[1], indentation, letize);
            os << ", ";
            os << num_bytes;
            os << ") == 0)";
          }
        else if (num_bytes == 1)
          {
            os << "(";
            C_Print1(os, c[0], indentation, letize);
            os << " == ";
            C_Print1(os, c[1], indentation, letize);
            os << ")";
          }
        else
          {
            FatalError("C_Print1: ugh problem in implementing ==");
          }

        break;
      case AND:
      case OR:
      case NAND:
      case NOR:
      case XOR:
        {
          os << "(";
          C_Print1(os, c[0], indentation, letize);
          ASTVec::const_iterator it = c.begin();
          ASTVec::const_iterator itend = c.end();

          it++;
          for (; it != itend; it++)
            {
              switch (kind)
                {
                case AND:
                  os << " && ";
                  break;
                case OR:
                  os << " || ";
                  break;
                case NAND:
                  FatalError("unsupported boolean type in C_Print1");
                  break;
                case NOR:
                  FatalError("unsupported boolean type in C_Print1");
                  break;
                case XOR:
                  FatalError("unsupported boolean type in C_Print1");
                  break;
                default:
                  FatalError("unsupported boolean type in C_Print1");
                }
              C_Print1(os, *it, indentation, letize);
            }
          os << ")";
          break;
        }
      case IFF:
        // stopgap for un-implemented features
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        os << "(";
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << ")";
        os << " <=> ";
        os << "(";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        os << ")";
        os << endl;
        break;
      case IMPLIES:
        // stopgap for un-implemented features
        FatalError("C_Print1: printing not implemented for this kind: ", n);
        os << "(";
        os << "(";
        C_Print1(os, c[0], indentation, letize);
        os << ")";
        os << " => ";
        os << "(";
        C_Print1(os, c[1], indentation, letize);
        os << ")";
        os << ")";
        os << endl;
        break;
      case BVSX:
        // stopgap for un-implemented features
        FatalError("C_Print1: printing not implemented for this kind: ", n);

        os << kind << "(";
        C_Print1(os, c[0], indentation, letize);
        os << ",";
        os << n.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("C_Print1: printing not implemented for this kind: ", n);
        break;
      }
  } //end of C_Print1()
ASTNode* TestASTTraverser::buildTree()
{
	ASTNode* assignNode = new ASTNode("", ASSIGN, 1);
	ASTNode* plusNode = new ASTNode("", PLUS, 0);
	ASTNode* minusNode = new ASTNode("", MINUS, 0);
	ASTNode* varNodeA = new ASTNode("a", VARIABLE, 0);
	ASTNode* varNodeB = new ASTNode("b", VARIABLE, 0);
	ASTNode* varNodeC = new ASTNode("c", VARIABLE, 0);
	ASTNode* constantNode = new ASTNode("1", CONSTANT, 0);

	assignNode->joinChild(varNodeA);
	varNodeA->joinNext(minusNode);
	minusNode->joinChild(plusNode);
	plusNode->joinChild(varNodeB);
	varNodeB->joinNext(varNodeC);
	plusNode->joinNext(constantNode);

	return assignNode;
}
Beispiel #23
0
  //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
bool
ASTBinaryFunctionNode::isSqrt() const
{
  bool valid = false;

  ASTBase * base1 = NULL;

  if (getType() == AST_FUNCTION_ROOT)
  {
    if (getNumChildren() == 2)
    {
      base1 = getChild(0);
      ASTFunction* fun = dynamic_cast<ASTFunction*>(base1);
      if (fun != NULL)
      {
        if (fun->getType() == AST_QUALIFIER_DEGREE 
          && fun->getNumChildren() == 1)
        {
          ASTBase *base2 = fun->getChild(0);
          if (base2->getType() == AST_INTEGER)
          {
            ASTNumber *child = static_cast<ASTNumber*>(base2);
            if (child->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
      }
      else
      {
        // here we are working the ASTNode so the casting
        // is more difficult

        ASTNode* newAST = dynamic_cast<ASTNode*>(base1);
        if (newAST != NULL && newAST->getType() == AST_QUALIFIER_DEGREE 
          && newAST->getNumChildren() == 1)
        {
          ASTNode* newAST1 = newAST->getChild(0);
          if (newAST1->getType() == AST_INTEGER)
          {
            if (newAST1->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
        else
        {
          if (newAST != NULL && newAST->getType() == AST_INTEGER)
          {
            if (newAST->getInteger() == 2)
            {
              valid = true;
            }
          }
        }

      }
    }
  }
  return valid;
}
bool
ASTNaryFunctionNode::isSqrt() const
{
  bool valid = false;

  if (getType() == AST_FUNCTION_ROOT)
  {
    // a sqrt can have either one child that is not the degree qualifier
    // or two where teh first is the degree of 2
    if (getNumChildren() == 1)
    {
      /* HACK to replicate OLD AST whic says a sqrt must have two children*/
      valid = false;
      //ASTBase * base1 = getChild(0);
      //if (base1->isQualifier() == false)
      //{
      //  valid = true;
      //}
    }
    else if (getNumChildren() == 2)
    {
      ASTBase * base1 = ASTFunctionBase::getChild(0);
      ASTFunction* fun = dynamic_cast<ASTFunction*>(base1);
      if (fun != NULL)
      {
        if (fun->getType() == AST_QUALIFIER_DEGREE 
          && fun->getNumChildren() == 1)
        {
          ASTBase *base2 = fun->getChild(0);
          if (base2->getType() == AST_INTEGER)
          {
            ASTNumber *child = static_cast<ASTNumber*>(base2);
            if (child->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
      }
      else
      {
        // here we are working the ASTNode so the casting
        // is more difficult

        ASTNode* newAST = dynamic_cast<ASTNode*>(base1);
        if (newAST != NULL && newAST->getType() == AST_QUALIFIER_DEGREE
          && newAST->getNumChildren() == 1)
        {
          ASTNode* newAST1 = newAST->getChild(0);
          if (newAST1->getType() == AST_INTEGER)
          {
            if (newAST1->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
        else
        {
          if (newAST != NULL && newAST->getType() == AST_INTEGER)
          {
            if (newAST->getInteger() == 2)
            {
              valid = true;
            }
          }
        }
      }
    }
  }

  return valid;
}
ASTNode SubstitutionMap::replace(const ASTNode& n, ASTNodeMap& fromTo,
                                 ASTNodeMap& cache, NodeFactory* nf,
                                 bool stopAtArrays, bool preventInfinite)
{
  const Kind k = n.GetKind();
  if (k == BVCONST || k == TRUE || k == FALSE)
    return n;

  ASTNodeMap::const_iterator it;

  if ((it = cache.find(n)) != cache.end())
    return it->second;

  if ((it = fromTo.find(n)) != fromTo.end())
  {
    const ASTNode& r = it->second;
    assert(r.GetIndexWidth() == n.GetIndexWidth());

    if (preventInfinite)
      cache.insert(make_pair(n, r));

    ASTNode replaced =
        replace(r, fromTo, cache, nf, stopAtArrays, preventInfinite);
    if (replaced != r)
    {
      fromTo.erase(n);
      fromTo[n] = replaced;
    }

    if (preventInfinite)
      cache.erase(n);

    cache.insert(make_pair(n, replaced));
    return replaced;
  }

  // These can't be created like regular nodes are
  if (k == SYMBOL)
    return n;

  const unsigned int indexWidth = n.GetIndexWidth();
  if (stopAtArrays && indexWidth > 0) // is an array.
  {
    return n;
  }

  const ASTVec& children = n.GetChildren();
  assert(children.size() > 0);
  // Should have no leaves left here.

  ASTVec new_children;
  new_children.reserve(children.size());

  for (ASTVec::const_iterator it = children.begin(); it != children.end(); it++)
  {
    new_children.push_back(
        replace(*it, fromTo, cache, nf, stopAtArrays, preventInfinite));
  }

  assert(new_children.size() == children.size());

  // This code short-cuts if the children are the same. Nodes with the same
  // children,
  // won't have necessarily given the same node if the simplifyingNodeFactory is
  // enabled
  // now, but wasn't enabled when the node was created. Shortcutting saves lots
  // of time.
  if (new_children == children)
  {
    cache.insert(make_pair(n, n));
    return n;
  }

  ASTNode result;
  const unsigned int valueWidth = n.GetValueWidth();

  if (valueWidth == 0) // n.GetType() == BOOLEAN_TYPE
  {
    result = nf->CreateNode(k, new_children);
  }
  else
  {
    // If the index and value width aren't saved, they are reset sometimes (??)
    result = nf->CreateArrayTerm(k, indexWidth, valueWidth, new_children);
  }

  // We may have created something that should be mapped. For instance,
  // if n is READ(A, x), and the fromTo is: {x==0, READ(A,0) == 1}, then
  // by here the result will be READ(A,0). Which needs to be mapped again..
  // I hope that this makes it idempotent.

  if (fromTo.find(result) != fromTo.end())
  {
    // map n->result, if running replace() on result gives us 'n', it will not
    // infinite loop.
    // This is only currently required for the bitblast equivalence stuff.
    if (preventInfinite)
      cache.insert(make_pair(n, result));

    result = replace(result, fromTo, cache, nf, stopAtArrays, preventInfinite);
  }

  assert(result.GetValueWidth() == valueWidth);
  assert(result.GetIndexWidth() == indexWidth);

  // If there is already an "n" element in the cache, the maps semantics are to
  // ignore the next insertion.
  if (preventInfinite)
    cache.erase(n);

  cache.insert(make_pair(n, result));
  return result;
}
ASTBase* 
ASTPiecewiseFunctionNode::getChild (unsigned int n) const
{
  /* HACK TO REPLICATE OLD AST */
  /* do not return a node with teh piece or otherwise type
   * return the correct child of the piece type
   * or the child of the otherwise
   */

  unsigned int numChildren = ASTFunctionBase::getNumChildren();
  if (numChildren == 0)
  {
    return NULL;
  }

  // determine index that we actually want
  unsigned int childNo = (unsigned int)(n/2);
  unsigned int pieceIndex = (unsigned int)(n%2);

  ASTBase * base = NULL;
  if (childNo < numChildren)
  {
    base = ASTFunctionBase::getChild(childNo);
  }


  if (getHasOtherwise() == true && childNo == numChildren - 1)
  {
    if (base == NULL)
    {
      return NULL;
    }

    if (base->getType() == AST_CONSTRUCTOR_OTHERWISE)
    {
      ASTNode * otherwise = dynamic_cast<ASTNode*>(base);

      if (otherwise != NULL)
      {
        if (otherwise->getNumChildren() > 0)
        {
          return otherwise->getChild(0);
        }
        else
        {
          return NULL;
        }
      }
      else
      {
        return NULL;
      }
    }
    else
    {
      return base;
    }
  }
  else if (base != NULL && base->getType() == AST_CONSTRUCTOR_PIECE)
  {
    ASTNode * piece = dynamic_cast<ASTNode*>(base);

    if (piece != NULL)
    {
      if (piece->getNumChildren() > pieceIndex)
      {
        return piece->getChild(pieceIndex);
      }
      else
      {
        return NULL;
      }
    }
    else
    {
      return NULL;
    }
  }
  else if (n < numChildren)
  {
    return ASTFunctionBase::getChild(n);
  }
  else
  {
    return NULL;
  }
}
Beispiel #28
0
bool SymbolCheckVisitor::performStep(ASTNode& node)
{
   node.accept(*this);
   return true;
}
int 
ASTPiecewiseFunctionNode::insertChildForReplace(unsigned int n, ASTBase* newChild)
{
  int inserted = LIBSBML_INDEX_EXCEEDS_SIZE;

  unsigned int numChildren = ASTFunctionBase::getNumChildren();
  unsigned int numChildrenForUser = getNumChildren();

  // determine index that we actually want
  unsigned int childNo = (unsigned int)(n/2);
  unsigned int pieceIndex = (unsigned int)(n%2);

  if (numChildren == numChildrenForUser)
  {
    // we have an old style piecewise function
    childNo = n;
    pieceIndex = n;
  }

  ASTBase * base = NULL;
  if (childNo < numChildren)
  {
    base = ASTFunctionBase::getChild(childNo);
  }


  if (getHasOtherwise() == true && childNo == numChildren - 1)
  {
    if (base == NULL)
    {
      return inserted;
    }

    if (base->getType() == AST_CONSTRUCTOR_OTHERWISE)
    {
      ASTNode * otherwise = dynamic_cast<ASTNode*>(base);

      if (otherwise != NULL)
      {
        inserted = otherwise->replaceChild(0, 
                                            static_cast<ASTNode*>(newChild));
      }
      else
      {
        return inserted;
      }
    }
    else
    {
      inserted = ASTFunctionBase::replaceChild(childNo, newChild);
    }
  }
  else if (base != NULL && base->getType() == AST_CONSTRUCTOR_PIECE)
  {
    ASTNode * piece = dynamic_cast<ASTNode*>(base);

    if (piece != NULL)
    {
      if (piece->getNumChildren() > pieceIndex)
      {
        inserted = piece->replaceChild(pieceIndex, static_cast<ASTNode*>(newChild));
      }
      else
      {
        return inserted;
      }
    }
    else
    {
      return inserted;
    }
  }
  else if (n < numChildren)
  {
    return ASTFunctionBase::replaceChild(n, newChild);
  }
  else
  {
    return inserted;
  }

  return inserted;

  //unsigned int numChildren = ASTFunctionBase::getNumChildren();

  //vector < ASTBase *> copyChildren;
  //unsigned int i;
  //for (i = n; i < numChildren; i++)
  //{
  //  ASTBase * child = getChild(i);
  //  // this might be NULL if we have deleted part of the piece function
  //  if (child != NULL)
  //  {
  //    copyChildren.push_back(getChild(i));
  //  }
  //}
  //for (i = numChildren; i > n; i--)
  //{
  //  ASTFunctionBase::removeChild(i-1);
  //}

  //unsigned int success = addChild(newChild);

  //i = 0;
  //while (success == LIBSBML_OPERATION_SUCCESS && i < copyChildren.size())
  //{
  //  success = addChild(copyChildren.at(i));
  //  i++;
  //}

  //inserted = success;

  //return inserted;
}
Beispiel #30
0
// This doesn't rewrite changes through properly so needs to have a substitution
// applied to its output.
ASTNode PropagateEqualities::propagate(const ASTNode& a, ArrayTransformer* at)
{
  ASTNode output;
  // if the variable has been solved for, then simply return it
  if (simp->CheckSubstitutionMap(a, output))
    return output;

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

  output = a;

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

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

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

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

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

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

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

    if (updated)
      return output;

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

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

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

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

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

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

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

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

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

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

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

  return output;
} // end of CreateSubstitutionMap()