CEvaluationNode * CMathExpression::createMassActionPart(const C_FLOAT64 * pK, const CCallParameters< C_FLOAT64 > * pSpecies) { CEvaluationNode * pPart = new CEvaluationNodeOperator(CEvaluationNode::S_MULTIPLY, "*"); pPart->addChild(createNodeFromValue(pK)); if (pSpecies->size() == 0) return pPart; CEvaluationNode * pNode = pPart; CCallParameters< C_FLOAT64 >::const_iterator itSpecies = pSpecies->begin(); CCallParameters< C_FLOAT64 >::const_iterator endSpecies = pSpecies->end(); for (; itSpecies != endSpecies - 1; ++itSpecies) { CEvaluationNode * p = new CEvaluationNodeOperator(CEvaluationNode::S_MULTIPLY, "*"); p->addChild(createNodeFromValue(itSpecies->value)); pNode->addChild(p); pNode = p; } pNode->addChild(createNodeFromValue(itSpecies->value)); return pPart; }
CEvaluationNode* CEvaluationNode::copyNode(const std::vector<CEvaluationNode*>& children) const { CEvaluationNode *newnode = create(mType, getData()); std::vector<CEvaluationNode*>::const_iterator it = children.begin(), endit = children.end(); while (it != endit) { newnode->addChild(*it); ++it; } return newnode; }
CEvaluationNode* CEvaluationNodeNormalizer::normalizePowerNode(const CEvaluationNodeOperator* pNode) { CEvaluationNode* pResult = NULL; if (pNode != NULL) { CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pChild1 != NULL) { CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling())); if (pChild2 != NULL) { if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER) { if (pChild2->value() - 1.0 < ZERO) { // replace it with the first child pResult = pChild1; delete pChild2; pChild2 = NULL; } else if (pChild2->value() < ZERO) { // replace it by a number node of 1 pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1"); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } else { pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^"); pResult->addChild(pChild1); pResult->addChild(pChild2); } } } if (pResult == NULL) pResult = pNode->copyBranch(); } return pResult; }
// static CEvaluationNode * CEvaluationNodeDelay::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children) { assert(pASTNode->getNumChildren() == children.size()); size_t i = 0, iMax = children.size(); SubType subType = SubType::DELAY; std::string data = "delay"; CEvaluationNode * pConvertedNode = new CEvaluationNodeDelay(subType, data); for (i = 0; i < iMax; ++i) { pConvertedNode->addChild(children[i]); } pConvertedNode->compile(NULL); return pConvertedNode; }
CEvaluationNode* CDerive::subtract(CEvaluationNode *n1, CEvaluationNode *n2, bool simplify) { if (simplify) { if (isZero(n1)) { if (isZero(n2)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); } //else //{ // deleteBranch(n1); // return n2; //} } if (isZero(n2)) { deleteBranch(n2); return n1; } // "numerical" simplification const CEvaluationNodeNumber * tmp1 = dynamic_cast<CEvaluationNodeNumber*>(n1); const CEvaluationNodeNumber * tmp2 = dynamic_cast<CEvaluationNodeNumber*>(n2); if (tmp1 && tmp2) { CEvaluationNode* tmpNN = new CEvaluationNodeNumber(tmp1->getValue() - tmp2->getValue()); return tmpNN; } } CEvaluationNode *newNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MINUS, "-"); newNode->addChild(n1); newNode->addChild(n2); return newNode; }
CEvaluationNode* CDerive::add(CEvaluationNode* n1, CEvaluationNode* n2, bool simplify) { if (simplify) { if (isZero(n1)) { if (isZero(n2)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); } else { deleteBranch(n1); return n2; } } if (isZero(n2)) { deleteBranch(n2); return n1; } // "numerical" simplification const CEvaluationNodeNumber * tmp1 = dynamic_cast<CEvaluationNodeNumber*>(n1); const CEvaluationNodeNumber * tmp2 = dynamic_cast<CEvaluationNodeNumber*>(n2); if (tmp1 && tmp2) { return new CEvaluationNodeNumber(tmp1->getValue() + tmp2->getValue()); } } CEvaluationNode *newNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::PLUS, "+"); newNode->addChild(n1); newNode->addChild(n2); return newNode; }
CEvaluationNode* CDerive::divide(CEvaluationNode* n1, CEvaluationNode* n2, bool simplify) { if (simplify) { if (isZero(n1)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); } /*if (isOne(n1)) { if (isOne(n2)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1"); } else { deleteBranch(n1); return n2; } }*/ if (isOne(n2)) { deleteBranch(n2); return n1; } } CEvaluationNode * tmpNode = NULL; tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::DIVIDE, "/"); tmpNode->addChild(n1); tmpNode->addChild(n2); //tmpNode->compile(NULL); return tmpNode; }
CEvaluationNode* CDerive::multiply(CEvaluationNode* n1, CEvaluationNode* n2, bool simplify) { if (simplify) { if (isZero(n1) || isZero(n2)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); } if (isOne(n1)) { if (isOne(n2)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1"); } else { deleteBranch(n1); return n2; } } if (isOne(n2)) { deleteBranch(n2); return n1; } } CEvaluationNode * tmpNode = NULL; tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); tmpNode->addChild(n1); tmpNode->addChild(n2); //tmpNode->compile(NULL); return tmpNode; }
CEvaluationNode* CDerive::power(CEvaluationNode* n1, CEvaluationNode* n2, bool simplify) { if (simplify) { if (isOne(n2)) { deleteBranch(n2); return n1; } if (isOne(n1)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1"); } if (isZero(n2) && !isZero(n1)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1"); } if (isZero(n1) && !isZero(n2)) { deleteBranch(n1); deleteBranch(n2); return new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); } } CEvaluationNode * tmpNode = NULL; tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^"); tmpNode->addChild(n1); tmpNode->addChild(n2); //tmpNode->compile(NULL); return tmpNode; }
CEvaluationNode* CEvaluationNodeLogical::createNodeFromASTTree(const ASTNode& node) { SubType subType; std::string data = ""; switch (node.getType()) { case AST_LOGICAL_AND: subType = AND; data = "and"; break; case AST_LOGICAL_OR: subType = OR; data = "or"; break; case AST_LOGICAL_XOR: subType = XOR; data = "xor"; break; case AST_RELATIONAL_EQ: subType = EQ; data = "eq"; break; case AST_RELATIONAL_GEQ: subType = GE; data = "ge"; break; case AST_RELATIONAL_GT: subType = GT; data = "gt"; break; case AST_RELATIONAL_LEQ: subType = LE; data = "le"; break; case AST_RELATIONAL_LT: subType = LT; data = "lt"; break; case AST_RELATIONAL_NEQ: subType = NE; data = "ne"; break; default: subType = INVALID; break; } CEvaluationNode* convertedNode = new CEvaluationNodeLogical(subType, data); // convert the two children int i, iMax = node.getNumChildren(); switch (subType) { case AND: case OR: case XOR: // these can have two or more children assert(iMax >= 2); convertedNode->addChild(CEvaluationTree::convertASTNode(*node.getChild(iMax - 1))); convertedNode->addChild(CEvaluationTree::convertASTNode(*node.getChild(iMax - 2))); iMax -= 3; for (i = iMax; i >= 0; --i) { CEvaluationNode* pTmpNode = new CEvaluationNodeLogical(subType, data); pTmpNode->addChild(convertedNode); pTmpNode->addChild(CEvaluationTree::convertASTNode(*node.getChild(i))); convertedNode = pTmpNode; } break; case EQ: case NE: case GE: case GT: case LE: case LT: // all these are binary convertedNode->addChild(CEvaluationTree::convertASTNode(*node.getLeftChild())); convertedNode->addChild(CEvaluationTree::convertASTNode(*node.getRightChild())); break; case INVALID: // do nothing break; } return convertedNode; }
// static CEvaluationNode * CEvaluationNodeLogical::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children) { assert(pASTNode->getNumChildren() == children.size()); size_t i = 0; size_t iMax = children.size(); SubType subType; std::string data = ""; switch (pASTNode->getType()) { case AST_LOGICAL_AND: subType = AND; data = "and"; break; case AST_LOGICAL_OR: subType = OR; data = "or"; break; case AST_LOGICAL_XOR: subType = XOR; data = "xor"; break; case AST_RELATIONAL_EQ: subType = EQ; data = "eq"; break; case AST_RELATIONAL_GEQ: subType = GE; data = "ge"; break; case AST_RELATIONAL_GT: subType = GT; data = "gt"; break; case AST_RELATIONAL_LEQ: subType = LE; data = "le"; break; case AST_RELATIONAL_LT: subType = LT; data = "lt"; break; case AST_RELATIONAL_NEQ: subType = NE; data = "ne"; break; default: subType = INVALID; break; } CEvaluationNode* pNode = NULL; // convert the two children switch (subType) { case AND: case OR: case XOR: // The number of chidren may vary switch (iMax) { case 0: if (subType == AND) pNode = new CEvaluationNodeConstant(CEvaluationNodeConstant::TRUE, "TRUE"); else pNode = new CEvaluationNodeConstant(CEvaluationNodeConstant::FALSE, "FALSE"); break; case 1: pNode = children[0]; break; default: { pNode = new CEvaluationNodeLogical(subType, data); CEvaluationNode * pCurrent = pNode; // We have at least 2 children while (i < iMax - 1) { // add the first value pCurrent->addChild(children[i++]); switch (iMax - i) { case 1: // We have only 1 more child pCurrent->addChild(children[i++]); break; default: // We have at least 2 more children { // create a new node with the same operator CEvaluationNode * pTmp = new CEvaluationNodeLogical(subType, data); pCurrent->addChild(pTmp); pCurrent = pTmp; } break; } } } break; } break; case EQ: case NE: case GE: case GT: case LE: case LT: // all these are binary assert(iMax == 2); pNode = new CEvaluationNodeLogical(subType, data); pNode->addChild(children[0]); pNode->addChild(children[1]); break; case INVALID: // do nothing break; } return pNode; }
CEvaluationNode* CEvaluationNodeNormalizer::normalizeModulusNode(const CEvaluationNodeOperator* pNode) { CEvaluationNode* pResult = NULL; if (pNode != NULL) { CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pChild1 != NULL) { CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling())); if (pChild2 != NULL) { if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER) { // eliminate modulus 1 if (fabs(pChild2->value() - 1.0) < ZERO) { pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } else if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER && (CEvaluationNodeNumber::SubType)CEvaluationNode::subType(pChild1->getType()) == CEvaluationNodeNumber::INTEGER && (CEvaluationNodeNumber::SubType)CEvaluationNode::subType(pChild2->getType()) == CEvaluationNodeNumber::INTEGER) { // if both children are numbers, do the calculation std::ostringstream os; os << (long)pChild1->value() % (long)pChild2->value(); pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, os.str()); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } else { // try to shorten numerator and denominator // TODO find out if a factor is involved if (*pChild1 == *pChild2) { pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } if (pResult == NULL) { pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::MODULUS, "%"); pResult->addChild(pChild1); pResult->addChild(pChild2); } } else { delete pChild1; pChild1 = NULL; } } if (pResult == NULL) pResult = pNode->copyBranch(); } return pResult; }
CEvaluationNode* CEvaluationNodeNormalizer::normalizeDivideNode(const CEvaluationNodeOperator* pNode) { CEvaluationNode* pResult = NULL; if (pNode != NULL) { CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pChild1 != NULL) { CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling())); if (pChild2 != NULL) { if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER) { // eliminate divisions by 1 if (fabs(pChild2->value() - 1.0) < ZERO) { pResult = pChild1; delete pChild2; pChild2 = NULL; } else if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER) { // if both children are numbers, do the calculation std::ostringstream os; os << pChild1->value() / pChild2->value(); pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str()); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } else { // try to shorten numerator and denominator // TODO find out if a factor is involved if (*pChild1 == *pChild2) { pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "1.0"); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } if (pResult == NULL) { pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::DIVIDE, "/"); pResult->addChild(pChild1); pResult->addChild(pChild2); } } else { delete pChild1; pChild1 = NULL; } } if (pResult == NULL) pResult = pNode->copyBranch(); } return pResult; }
CEvaluationNode* CEvaluationNodeNormalizer::normalizePlusNode(const CEvaluationNodeOperator* pNode) { CEvaluationNode* pResult = NULL; if (pNode != NULL) { CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pChild1 != NULL) { CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling())); if (pChild2 != NULL) { // if one of the nodes is a number node of 0, replace the node by the // other child if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER) { if (fabs(pChild1->value()) < ZERO) { pResult = pChild2; delete pChild1; pChild1 = NULL; pChild2 = NULL; } } if (pChild2 != NULL && CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER) { if (fabs(pChild2->value()) < ZERO) { if (pChild2 != pResult) { pResult = pChild1; delete pChild2; } pChild1 = NULL; pChild2 = NULL; } } if (!pResult) { pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::PLUS, "+"); pResult->addChild(pChild1); pResult->addChild(pChild2); } if (pResult->getType() == CEvaluationNode::OPERATOR) { // add all number nodes in a summation chain std::vector<CEvaluationNode*> chainNodes; findChainNodes(dynamic_cast<CEvaluationNodeOperator*>(pResult), chainNodes); CEvaluationNodeNormalizer::eliminateMultipleNumbers((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes); // replace addition of identical items by a multiplication node with the // correct number CEvaluationNodeNormalizer::collectIdenticalBranches((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes); // reorder nodes again CEvaluationNodeNormalizer::reorderNodes(chainNodes); // rebuild pResult; CEvaluationNodeOperator::SubType subType = (CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()); delete pResult; pResult = CEvaluationNodeNormalizer::buildOperatorBranchFromChain(subType, chainNodes); } } else { delete pChild1; pChild1 = NULL; } } if (pResult == NULL) pResult = pNode->copyBranch(); } return pResult; }
CEvaluationNode* CEvaluationNodeNormalizer::normalizeMultiplyNode(const CEvaluationNodeOperator* pNode) { CEvaluationNode* pResult = NULL; if (pNode != NULL) { CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pChild1 != NULL) { CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling())); if (pChild2 != NULL) { // if one of the child nodes is zero, replace the node with a number // node of value 0 // if one of the nodes is a number node of 1, replace the node by the // other child if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER) { if (fabs(pChild1->value() - 1.0) < ZERO) { pResult = pChild2; delete pChild1; pChild1 = NULL; pChild2 = NULL; } else if (fabs(pChild1->value()) < ZERO) { pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); // we are done delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } if (pChild2 && CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER) { if (fabs(pChild2->value() - 1.0) < ZERO) { pResult = pChild1; delete pChild2; pChild2 = NULL; pChild1 = NULL; } else if (fabs(pChild2->value()) < ZERO) { pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); // we are done delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } if (!pResult) { pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); pResult->addChild(pChild1); pResult->addChild(pChild2); } if (pResult->getType() == CEvaluationNode::OPERATOR) { // multiply all number nodes in a multiplication chain std::vector<CEvaluationNode*> chainNodes; findChainNodes(dynamic_cast<CEvaluationNodeOperator*>(pResult), chainNodes); CEvaluationNodeNormalizer::eliminateMultipleNumbers((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes); // replace multiplication of identical items by a power node with the // correct power CEvaluationNodeNormalizer::collectIdenticalBranches((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes); // reorder nodes again CEvaluationNodeNormalizer::reorderNodes(chainNodes); // rebuild pResult; CEvaluationNodeOperator::SubType subType = (CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()); delete pResult; pResult = CEvaluationNodeNormalizer::buildOperatorBranchFromChain(subType, chainNodes); } } } if (pResult == NULL) pResult = pNode->copyBranch(); } return pResult; }
// static CEvaluationNode * CEvaluationNodeFunction::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children) { assert(pASTNode->getNumChildren() == children.size()); size_t iMax = children.size(); int type = (int)pASTNode->getType(); SubType subType; std::string data = ""; if (type == AST_FUNCTION_ROOT) { CEvaluationNode * pNode = NULL; switch (iMax) { case 1: pNode = new CEvaluationNodeFunction(S_SQRT, "sqrt"); pNode->addChild(children[0]); break; case 2: /** * Replaces all root nodes with the corresponding power * operator since COPASI does not have the ROOT function. */ { pNode = new CEvaluationNodeOperator(S_POWER, "^"); pNode->addChild(children[1]); // Value CEvaluationNode * pExponent = new CEvaluationNodeOperator(S_DIVIDE, "/"); pNode->addChild(pExponent); pExponent->addChild(new CEvaluationNodeNumber(S_DOUBLE, "1")); pExponent->addChild(children[0]); // Degree } break; } return pNode; } else if (type == AST_FUNCTION_LOG && iMax == 2) { /** * Replaces all LOG10 (AST_FUNCTION_LOG) nodes that have two * children with the quotient of two LOG10 nodes with the base * as the argument for the divisor LOG10 node. */ CEvaluationNode * pNode = new CEvaluationNodeOperator(S_DIVIDE, "/"); CEvaluationNode * pValue = new CEvaluationNodeFunction(S_LOG10, "log10"); pValue->addChild(children[1]); CEvaluationNode * pBase = new CEvaluationNodeFunction(S_LOG10, "log10"); pBase->addChild(children[0]); pNode->addChild(pValue); pNode->addChild(pBase); return pNode; } switch (type) { case AST_FUNCTION_ABS: subType = S_ABS; data = "abs"; break; case AST_FUNCTION_ARCCOS: subType = S_ARCCOS; data = "acos"; break; case AST_FUNCTION_ARCCOSH: subType = S_ARCCOSH; data = "arccosh"; break; case AST_FUNCTION_ARCCOT: subType = S_ARCCOT; data = "arccot"; break; case AST_FUNCTION_ARCCOTH: subType = S_ARCCOTH; data = "arccoth"; break; case AST_FUNCTION_ARCCSC: subType = S_ARCCSC; data = "arccsc"; break; case AST_FUNCTION_ARCCSCH: subType = S_ARCCSCH; data = "arccsch"; break; case AST_FUNCTION_ARCSEC: subType = S_ARCSEC; data = "arcsec"; break; case AST_FUNCTION_ARCSECH: subType = S_ARCSECH; data = "arcsech"; break; case AST_FUNCTION_ARCSIN: subType = S_ARCSIN; data = "asin"; break; case AST_FUNCTION_ARCSINH: subType = S_ARCSINH; data = "arcsinh"; break; case AST_FUNCTION_ARCTAN: subType = S_ARCTAN; data = "atan"; break; case AST_FUNCTION_ARCTANH: subType = S_ARCTANH; data = "arctanh"; break; case AST_FUNCTION_CEILING: subType = S_CEIL; data = "ceil"; break; case AST_FUNCTION_COS: subType = S_COS; data = "cos"; break; case AST_FUNCTION_COSH: subType = S_COSH; data = "cosh"; break; case AST_FUNCTION_COT: subType = S_COT; data = "cot"; break; case AST_FUNCTION_COTH: subType = S_COTH; data = "coth"; break; case AST_FUNCTION_CSC: subType = S_CSC; data = "csc"; break; case AST_FUNCTION_CSCH: subType = S_CSCH; data = "csch"; break; case AST_FUNCTION_EXP: subType = S_EXP; data = "exp"; break; case AST_FUNCTION_FACTORIAL: subType = S_FACTORIAL; data = "factorial"; break; case AST_FUNCTION_FLOOR: subType = S_FLOOR; data = "floor"; break; case AST_FUNCTION_LN: subType = S_LOG; data = "log"; break; case AST_FUNCTION_LOG: subType = S_LOG10; data = "log10"; break; case AST_FUNCTION_SEC: subType = S_SEC; data = "sec"; break; case AST_FUNCTION_SECH: subType = S_SECH; data = "sech"; break; case AST_FUNCTION_SIN: subType = S_SIN; data = "sin"; break; case AST_FUNCTION_SINH: subType = S_SINH; data = "sinh"; break; case AST_FUNCTION_TAN: subType = S_TAN; data = "tan"; break; case AST_FUNCTION_TANH: subType = S_TANH; data = "tanh"; break; case AST_LOGICAL_NOT: subType = S_NOT; data = "not"; break; default: subType = S_INVALID; fatalError(); break; } assert(iMax == 1); CEvaluationNode * pNode = new CEvaluationNodeFunction(subType, data); if (!children.empty()) pNode->addChild(children[0]); return pNode; }
// static CEvaluationNode * CEvaluationNodeNumber::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children) { assert(pASTNode->getNumChildren() == children.size()); std::stringstream ss; ss.imbue(std::locale::classic()); ss.precision(std::numeric_limits<double>::digits10 + 2); SubType subType; std::string data = ""; CEvaluationNode* pNode = NULL; switch (pASTNode->getType()) { case AST_INTEGER: subType = SubType::INTEGER; if (pASTNode->getInteger() < 0) { pNode = new CEvaluationNodeFunction(SubType::MINUS, "-"); ss << abs(pASTNode->getInteger()); data = ss.str(); pNode->addChild(new CEvaluationNodeNumber(subType, data)); } else { ss << pASTNode->getInteger(); data = ss.str(); pNode = new CEvaluationNodeNumber(subType, data); } break; case AST_REAL: subType = SubType::DOUBLE; if (pASTNode->getReal() == (std::numeric_limits<C_FLOAT64>::infinity())) { pNode = new CEvaluationNodeConstant(SubType::Infinity, "INFINITY"); } else if (pASTNode->getReal() == (-std::numeric_limits<C_FLOAT64>::infinity())) { pNode = new CEvaluationNodeFunction(SubType::MINUS, "-"); pNode->addChild(new CEvaluationNodeConstant(SubType::Infinity, "INFINITY")); } else if (isnan(pASTNode->getReal())) { pNode = new CEvaluationNodeConstant(SubType::NaN, "NAN"); } else if (pASTNode->getReal() < 0.0) { pNode = new CEvaluationNodeFunction(SubType::MINUS, "-"); ss << fabs(pASTNode->getReal()); data = ss.str(); pNode->addChild(new CEvaluationNodeNumber(subType, data)); } else { ss << pASTNode->getReal(); data = ss.str(); pNode = new CEvaluationNodeNumber(subType, data); } break; case AST_REAL_E: subType = SubType::ENOTATION; if (pASTNode->getReal() == (std::numeric_limits<C_FLOAT64>::infinity())) { pNode = new CEvaluationNodeConstant(SubType::Infinity, "INFINITY"); } else if (pASTNode->getReal() == (-std::numeric_limits<C_FLOAT64>::infinity())) { pNode = new CEvaluationNodeFunction(SubType::MINUS, "-"); pNode->addChild(new CEvaluationNodeConstant(SubType::Infinity, "INFINITY")); } else if (isnan(pASTNode->getReal())) { pNode = new CEvaluationNodeConstant(SubType::NaN, "NAN"); } else if (pASTNode->getReal() < 0.0) { pNode = new CEvaluationNodeFunction(SubType::MINUS, "-"); ss << fabs(pASTNode->getReal()); data = ss.str(); pNode->addChild(new CEvaluationNodeNumber(subType, data)); } else { ss << pASTNode->getReal(); data = ss.str(); pNode = new CEvaluationNodeNumber(subType, data); } break; case AST_RATIONAL: subType = SubType::RATIONALE; if (pASTNode->getReal() < 0.0) // getReal returns the value of the node { pNode = new CEvaluationNodeFunction(SubType::MINUS, "-"); ss << "(" << abs(pASTNode->getNumerator()) << "/" << abs(pASTNode->getDenominator()) << ")"; data = ss.str(); pNode->addChild(new CEvaluationNodeNumber(subType, data)); } else { ss << "(" << pASTNode->getNumerator() << "/" << pASTNode->getDenominator() << ")"; data = ss.str(); pNode = new CEvaluationNodeNumber(subType, data); } break; default: subType = SubType::INVALID; break; } return pNode; }
CEvaluationNode* CEvaluationNodeNormalizer::normalizeMinusNode(const CEvaluationNodeOperator* pNode) { CEvaluationNode* pResult = NULL; if (pNode != NULL) { CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pChild1 != NULL) { CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling())); if (pChild2 != NULL) { if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER) { // eliminate subtraction of 0 if (fabs(pChild2->getValue()) < ZERO) { pResult = pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } else if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER) { // if both children are numbers, do the calculation std::ostringstream os; os << pChild1->getValue() - pChild2->getValue(); pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str()); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } else { // TODO find out if a factor is involved if (*pChild1 == *pChild2) { pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "0.0"); delete pChild1; delete pChild2; pChild1 = NULL; pChild2 = NULL; } } if (pResult == NULL) { pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::MINUS, "-"); pResult->addChild(pChild1); pResult->addChild(pChild2); } } else { delete pChild1; pChild1 = NULL; } } if (pResult == NULL) pResult = pNode->copyBranch(); } return pResult; }
// static CEvaluationNode * CEvaluationNodeChoice::fromAST(const ASTNode * pASTNode, const std::vector< CEvaluationNode * > & children) { assert(pASTNode->getNumChildren() == children.size()); size_t i = 0, iMax = children.size(); // a piecewise function definition can have zero or more children. if (iMax == 0) { // create a NaN node return new CEvaluationNodeConstant(CEvaluationNodeConstant::_NaN, "NAN"); } if (iMax == 1) { // this must be the otherwise // It is not clearly specified what happens if there are no pieces, but // an otherwise. I would assume that in this case, the otherwise always // takes effect return children[0]; } SubType subType; std::string data = ""; switch (pASTNode->getType()) { case AST_FUNCTION_PIECEWISE: subType = IF; data = "if"; break; default: subType = INVALID; break; } CEvaluationNodeChoice * pNode = new CEvaluationNodeChoice(subType, data); CEvaluationNode * pCurrent = pNode; // We have at least 2 children while (i < iMax - 1) { // add the condition pCurrent->addChild(children[i + 1]); // the true value pCurrent->addChild(children[i]); i += 2; switch (iMax - i) { case 0: // We are missing the false value pCurrent->addChild(new CEvaluationNodeConstant(CEvaluationNodeConstant::_NaN, "NAN")); break; case 1: // the false value pCurrent->addChild(children[i++]); break; default: // We have at least 2 more children { // create a new piecewise as the false value CEvaluationNode * pTmp = new CEvaluationNodeChoice(subType, data); pCurrent->addChild(pTmp); pCurrent = pTmp; } break; } } return pNode; }
CEvaluationNode* CEvaluationNodeNormalizer::normalizeCEvaluationNodeFunction(const CEvaluationNodeFunction* pNode) { CEvaluationNode* pResult = NULL; if (pNode != NULL) { CEvaluationNode* pTmpResult; switch ((CEvaluationNodeFunction::SubType)CEvaluationNode::subType(pNode->getType())) { case CEvaluationNodeFunction::INVALID: break; case CEvaluationNodeFunction::LOG: case CEvaluationNodeFunction::LOG10: case CEvaluationNodeFunction::EXP: case CEvaluationNodeFunction::SIN: case CEvaluationNodeFunction::COS: case CEvaluationNodeFunction::TAN: case CEvaluationNodeFunction::SEC: case CEvaluationNodeFunction::CSC: case CEvaluationNodeFunction::COT: case CEvaluationNodeFunction::SINH: case CEvaluationNodeFunction::COSH: case CEvaluationNodeFunction::TANH: case CEvaluationNodeFunction::SECH: case CEvaluationNodeFunction::CSCH: case CEvaluationNodeFunction::COTH: case CEvaluationNodeFunction::ARCSIN: case CEvaluationNodeFunction::ARCCOS: case CEvaluationNodeFunction::ARCTAN: case CEvaluationNodeFunction::ARCSEC: case CEvaluationNodeFunction::ARCCSC: case CEvaluationNodeFunction::ARCCOT: case CEvaluationNodeFunction::ARCSINH: case CEvaluationNodeFunction::ARCCOSH: case CEvaluationNodeFunction::ARCTANH: case CEvaluationNodeFunction::ARCSECH: case CEvaluationNodeFunction::ARCCSCH: case CEvaluationNodeFunction::ARCCOTH: case CEvaluationNodeFunction::SQRT: case CEvaluationNodeFunction::ABS: case CEvaluationNodeFunction::FLOOR: case CEvaluationNodeFunction::CEIL: case CEvaluationNodeFunction::FACTORIAL: case CEvaluationNodeFunction::NOT: case CEvaluationNodeFunction::MINUS: pResult = new CEvaluationNodeFunction((CEvaluationNodeFunction::SubType)CEvaluationNode::subType(pNode->getType()), pNode->getData()); pTmpResult = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pTmpResult != NULL) { pResult->addChild(pTmpResult); } else { delete pResult; pResult = NULL; } break; case CEvaluationNodeFunction::RUNIFORM: case CEvaluationNodeFunction::RNORMAL: //case CEvaluationNodeFunction::DELAY: // normalize all children pResult = new CEvaluationNodeFunction((CEvaluationNodeFunction::SubType)CEvaluationNode::subType(pNode->getType()), pNode->getData()); pTmpResult = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); if (pTmpResult != NULL) { pResult->addChild(pTmpResult); pTmpResult = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling())); if (pTmpResult != NULL) { pResult->addChild(pTmpResult); } else { delete pResult; pResult = NULL; } } else { delete pResult; pResult = NULL; } break; /* case CEvaluationNodeFunction::MINUS: // relace the - by a multiplication with -1 // !!! Maybe this is not possible since CEvaluationNodeNumber // elements can not hold negative numbers. pResult=new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY,""); */ case CEvaluationNodeFunction::PLUS: // eliminate the plus pResult = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild())); break; } if (pResult == NULL) pResult = pNode->copyBranch(); } return pResult; }
CEvaluationNode* CDerive::deriveBranch(const CEvaluationNode* node, unsigned C_INT32 variableIndex, const CCopasiObject * pObject) { CEvaluationNode * newNode = NULL; const CEvaluationNodeOperator * pENO = dynamic_cast<const CEvaluationNodeOperator*>(node); if (pENO) { if (!pENO->getLeft() || !pENO->getRight()) return NULL; CEvaluationNode * pLeftDeriv = deriveBranch(pENO->getLeft(), variableIndex, pObject); if (!pLeftDeriv) return NULL; CEvaluationNode * pRightDeriv = deriveBranch(pENO->getRight(), variableIndex, pObject); if (!pRightDeriv) {delete pLeftDeriv; return NULL;} // we now know that derivations of the left and right branch exist switch ((CEvaluationNodeOperator::SubType) CEvaluationNode::subType(pENO->getType())) { case CEvaluationNodeOperator::MULTIPLY: { CEvaluationNode * pLeftCopy = pENO->getLeft()->copyBranch(); CEvaluationNode * pRightCopy = pENO->getRight()->copyBranch(); newNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::PLUS, "+"); CEvaluationNodeOperator * tmpNode; tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); tmpNode->addChild(pRightCopy); tmpNode->addChild(pLeftDeriv); //tmpNode->compile(NULL); newNode->addChild(tmpNode); tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); tmpNode->addChild(pRightDeriv); tmpNode->addChild(pLeftCopy); //tmpNode->compile(NULL); newNode->addChild(tmpNode); //if (newNode) newNode->compile(NULL); return newNode; } break; case CEvaluationNodeOperator::DIVIDE: { CEvaluationNode * pLeftCopy = pENO->getLeft()->copyBranch(); CEvaluationNode * pRightCopy = pENO->getRight()->copyBranch(); //numerator CEvaluationNodeOperator * minusNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MINUS, "+"); CEvaluationNodeOperator * tmpNode; tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); tmpNode->addChild(pRightCopy); tmpNode->addChild(pLeftDeriv); //tmpNode->compile(NULL); minusNode->addChild(tmpNode); tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); tmpNode->addChild(pRightDeriv); tmpNode->addChild(pLeftCopy); //tmpNode->compile(NULL); minusNode->addChild(tmpNode); minusNode->compile(NULL); //denominator CEvaluationNodeOperator * powerNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^"); pRightCopy = pENO->getRight()->copyBranch(); //new copy powerNode->addChild(pRightCopy); powerNode->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "2")); //powerNode->compile(NULL); newNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::DIVIDE, "/"); newNode->addChild(minusNode); newNode->addChild(powerNode); //if (newNode) newNode->compile(NULL); return newNode; } break; case CEvaluationNodeOperator::PLUS: newNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::PLUS, "+"); newNode->addChild(pLeftDeriv); newNode->addChild(pRightDeriv); //TODO check for zeros //if (newNode) newNode->compile(NULL); return newNode; break; case CEvaluationNodeOperator::MINUS: newNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MINUS, "-"); newNode->addChild(pLeftDeriv); newNode->addChild(pRightDeriv); //TODO check for zeros //if (newNode) newNode->compile(NULL); return newNode; break; case CEvaluationNodeOperator::POWER: { CEvaluationNode * pLeftCopy = pENO->getLeft()->copyBranch(); CEvaluationNode * pRightCopy = pENO->getRight()->copyBranch(); // a^(b-1) CEvaluationNodeOperator * powerNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^"); powerNode->addChild(pLeftCopy); // add a CEvaluationNodeOperator * tmpNode; tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MINUS, "-"); tmpNode->addChild(pRightCopy); // add b tmpNode->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1")); // 1 powerNode->addChild(tmpNode); // add b-1 // b*a´ + a*b´* ln a CEvaluationNodeOperator * plusNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::PLUS, "+"); tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); pRightCopy = pENO->getRight()->copyBranch(); //new copy of b tmpNode->addChild(pRightCopy); // add b tmpNode->addChild(pLeftDeriv); // add a´ plusNode->addChild(tmpNode); // add b*a´ tmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); pLeftCopy = pENO->getLeft()->copyBranch(); //new copy of a tmpNode->addChild(pLeftCopy); // add a CEvaluationNodeOperator * tmptmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); tmptmpNode->addChild(pRightDeriv); // add b´ CEvaluationNodeFunction * funcNode = new CEvaluationNodeFunction(CEvaluationNodeFunction::LOG, "ln"); // ln a pLeftCopy = pENO->getLeft()->copyBranch(); //new copy of a funcNode->addChild(pLeftCopy); // add a tmptmpNode->addChild(funcNode); // add ln a tmpNode->addChild(tmptmpNode); // add b´ * ln a plusNode->addChild(tmpNode); // add a * b´ * ln a // a^(b-1)*(b*a´ + a*b´ * ln a) newNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); newNode->addChild(powerNode); newNode->addChild(plusNode); return newNode; } break; default: break; } } const CEvaluationNodeVariable * pENV = dynamic_cast<const CEvaluationNodeVariable*>(node); if (pENV) { if (pObject) return NULL; // if a variable node occurs, we are differentiating a function if (variableIndex == pENV->getIndex()) newNode = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "1"); else newNode = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); return newNode; } const CEvaluationNodeNumber * pENN = dynamic_cast<const CEvaluationNodeNumber*>(node); if (pENN) { newNode = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0"); return newNode; } return newNode; }
CEvaluationNode* CEvaluationNodeFunction::simplifyNode(const std::vector<CEvaluationNode*>& children) const { assert(children.size() > 0); CEvaluationNode* child1 = children[0]; switch (mSubType) { case S_MINUS: { switch (child1->mainType()) { case CEvaluationNode::T_OPERATOR: { switch (child1->subType()) { case S_DIVIDE: { // -(a/b) -> (-a)/b // want to recognize a fraction in a sum easily CEvaluationNode *newnode = CEvaluationNode::create(T_OPERATOR, S_DIVIDE, "/"); CEvaluationNode *newchild1 = CEvaluationNode::create(T_FUNCTION, S_MINUS, "-"); CEvaluationNode *newchild2 = dynamic_cast<CEvaluationNode*>(child1->getChild()->getSibling())->copyBranch(); CEvaluationNode *grandchild = dynamic_cast<CEvaluationNode*>(child1->getChild())->copyBranch(); newnode->addChild(newchild1, NULL); newnode->addChild(newchild2, newchild1); newchild1->addChild(grandchild, NULL); delete child1; return newnode; } case S_PLUS: { // -(a+b) -> (-a)+(-b) // negativity should be property of product CEvaluationNode *newnode = CEvaluationNode::create(T_OPERATOR, S_PLUS, "+"); CEvaluationNode *newchild1 = CEvaluationNode::create(T_FUNCTION, S_MINUS, "-"); CEvaluationNode *newchild2 = CEvaluationNode::create(T_FUNCTION, S_MINUS, "-"); CEvaluationNode *grandchild1 = dynamic_cast<CEvaluationNode*>(child1->getChild())->copyBranch(); CEvaluationNode *grandchild2 = dynamic_cast<CEvaluationNode*>(child1->getChild()->getSibling())->copyBranch(); newnode->addChild(newchild1, NULL); newnode->addChild(newchild2, newchild1); newchild1->addChild(grandchild1, NULL); newchild2->addChild(grandchild2, NULL); delete child1; return newnode; } default: // cases POWER, MULTIPLY, MODULUS. don't expect MINUS to occur anymore { CEvaluationNode *newnode = copyNode(children); return newnode; } } } case CEvaluationNode::T_FUNCTION: { if (child1->getData() == "-") { // -(-a) -> a CEvaluationNode *newnode = dynamic_cast<CEvaluationNode*>(child1->getChild())->copyBranch(); delete child1; return newnode; } // default: copy CEvaluationNode *newnode = copyNode(children); return newnode; } case CEvaluationNode::T_NUMBER: { std::stringstream tmp; tmp << *child1->getValuePointer() *(-1.0); CEvaluationNode* newnode = CEvaluationNode::create(T_NUMBER, S_DOUBLE, tmp.str()); delete child1; return newnode; } default: //cases VARIABLE, CONSTANT.. { CEvaluationNode *newnode = copyNode(children); return newnode; } } break; } case S_SQRT: { // write as ^0.5 CEvaluationNode* newnode = CEvaluationNode::create(T_OPERATOR, S_POWER, "^"); CEvaluationNode* newchild2 = CEvaluationNode::create(T_NUMBER, S_DOUBLE, "0.5"); newnode->addChild(child1, NULL); newnode->addChild(newchild2, child1); return newnode; } default: { CEvaluationNode *newnode = copyNode(children); return newnode; } } }