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; }
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; }
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; }
/* 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
/******************************************************** * 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
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; } }
//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()
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)); }
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; }
/* 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); } } } }
/** @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); } }
// 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; }
//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; } }
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; }
// 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()