bool CEvaluationNodeNormalizer::collectIdenticalBranches(CEvaluationNodeOperator::SubType subType, std::vector<CEvaluationNode*>& chainNodes) { bool changed = false; if (chainNodes.size() > 1) { // what is done depends on the subtype // if it is an additon we replace identical nodes with a multiplication of // the node with the number of occurences // for a multiplication it's the same, but we use a power instead of a // multiplication if (subType == CEvaluationNodeOperator::MULTIPLY || subType == CEvaluationNodeOperator::PLUS) { CEvaluationNodeOperator* pOperation = (subType == CEvaluationNodeOperator::MULTIPLY) ? new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^") : new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); std::vector<CEvaluationNode*>::iterator it = chainNodes.begin(), endit = chainNodes.end(); std::map<CEvaluationNode, unsigned int> occurenceMap; while (it != endit) { std::map<CEvaluationNode, unsigned int>::iterator pos = occurenceMap.find(**it); if (pos == occurenceMap.end()) { occurenceMap[**it] = 1; } else { ++(pos->second); changed = true; } // delete the node delete(*it); ++it; } chainNodes.clear(); // convert the contents of the occurenceMap to new nodes std::map<CEvaluationNode, unsigned int>::const_iterator mapIt = occurenceMap.begin(), mapEndit = occurenceMap.end(); std::ostringstream os; while (mapIt != mapEndit) { os << mapIt->second; CEvaluationNodeNumber* pNumberNode = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, os.str()); CEvaluationNodeOperator* pNewOperator = dynamic_cast<CEvaluationNodeOperator*>(CEvaluationNode::create(pOperation->getType(), pOperation->getData())); pNewOperator->addChild(pNumberNode); pNewOperator->addChild(mapIt->first.copyBranch()); chainNodes.push_back(pNewOperator); os.str(""); ++mapIt; } delete pOperation; } } return changed; }
CEvaluationNodeOperator* CEvaluationNodeNormalizer::buildOperatorBranchFromChain(CEvaluationNodeOperator::SubType subType, const std::vector<CEvaluationNode*>& chainNodes) { CEvaluationNodeOperator* pResult = NULL; std::string data; switch (subType) { case CEvaluationNodeOperator::POWER: data = "^"; break; case CEvaluationNodeOperator::MULTIPLY: data = "*"; break; case CEvaluationNodeOperator::DIVIDE: data = "/"; break; case CEvaluationNodeOperator::MODULUS: data = "%"; break; case CEvaluationNodeOperator::PLUS: data = "+"; break; case CEvaluationNodeOperator::MINUS: data = "-"; break; default: fatalError(); break; } if (chainNodes.size() > 1) { std::vector<CEvaluationNode*>::const_reverse_iterator it = chainNodes.rbegin(), endit = chainNodes.rend(); CEvaluationNodeOperator* pTmpOperator = new CEvaluationNodeOperator(subType, data); // add the first child pTmpOperator->addChild(*it); ++it; --endit; while (it != endit) { pTmpOperator->addChild(*it); pResult = new CEvaluationNodeOperator(subType, data); pResult->addChild(pTmpOperator); pTmpOperator = pResult; ++it; } // add the last child pResult->addChild(*it); } 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; }
void test_depth_first_iterator::test_dfi() { std::string infix("7-(3+(4-6))+1*8"); CEvaluationTree* pTree = new CEvaluationTree(); pTree->setInfix(infix); std::string s = pTree->getInfix(); CPPUNIT_ASSERT(pTree->getRoot() != NULL); CEvaluationNodeDepthFirstIterator it(pTree->getRoot()); CPPUNIT_ASSERT(it.isValid()); CEvaluationNode* pNode = NULL; CEvaluationNodeNumber* pNumberNode = NULL; CEvaluationNodeOperator* pOperatorNode = NULL; // 7 pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::NUMBER); pNumberNode = dynamic_cast<CEvaluationNodeNumber*>(pNode); CPPUNIT_ASSERT(pNumberNode != NULL); CPPUNIT_ASSERT((fabs(pNumberNode->getValue() - 7) / 7.0) <= std::numeric_limits<double>::min()); // 3 ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::NUMBER); pNumberNode = dynamic_cast<CEvaluationNodeNumber*>(pNode); CPPUNIT_ASSERT(pNumberNode != NULL); CPPUNIT_ASSERT((fabs(pNumberNode->getValue() - 3) / 3.0) <= std::numeric_limits<double>::min()); // 4 ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::NUMBER); pNumberNode = dynamic_cast<CEvaluationNodeNumber*>(pNode); CPPUNIT_ASSERT(pNumberNode != NULL); CPPUNIT_ASSERT((fabs(pNumberNode->getValue() - 4) / 4.0) <= std::numeric_limits<double>::min()); // 6 ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::NUMBER); pNumberNode = dynamic_cast<CEvaluationNodeNumber*>(pNode); CPPUNIT_ASSERT(pNumberNode != NULL); CPPUNIT_ASSERT((fabs(pNumberNode->getValue() - 6) / 6.0) <= std::numeric_limits<double>::min()); // - ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::OPERATOR); pOperatorNode = dynamic_cast<CEvaluationNodeOperator*>(pNode); CPPUNIT_ASSERT(pOperatorNode != NULL); CPPUNIT_ASSERT((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOperatorNode->getType()) == CEvaluationNodeOperator::MINUS); // + ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::OPERATOR); pOperatorNode = dynamic_cast<CEvaluationNodeOperator*>(pNode); CPPUNIT_ASSERT(pOperatorNode != NULL); CPPUNIT_ASSERT((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOperatorNode->getType()) == CEvaluationNodeOperator::PLUS); // - ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::OPERATOR); pOperatorNode = dynamic_cast<CEvaluationNodeOperator*>(pNode); CPPUNIT_ASSERT(pOperatorNode != NULL); CPPUNIT_ASSERT((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOperatorNode->getType()) == CEvaluationNodeOperator::MINUS); // 1 ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::NUMBER); pNumberNode = dynamic_cast<CEvaluationNodeNumber*>(pNode); CPPUNIT_ASSERT(pNumberNode != NULL); CPPUNIT_ASSERT((fabs(pNumberNode->getValue() - 1) / 1.0) <= std::numeric_limits<double>::min()); // 8 ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::NUMBER); pNumberNode = dynamic_cast<CEvaluationNodeNumber*>(pNode); CPPUNIT_ASSERT(pNumberNode != NULL); CPPUNIT_ASSERT((fabs(pNumberNode->getValue() - 8) / 8.0) <= std::numeric_limits<double>::min()); // * ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::OPERATOR); pOperatorNode = dynamic_cast<CEvaluationNodeOperator*>(pNode); CPPUNIT_ASSERT(pOperatorNode != NULL); CPPUNIT_ASSERT((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOperatorNode->getType()) == CEvaluationNodeOperator::MULTIPLY); // + ++it; CPPUNIT_ASSERT(it.isValid() == true); pNode = *it; CPPUNIT_ASSERT(pNode != NULL); CPPUNIT_ASSERT(CEvaluationNode::type(pNode->getType()) == CEvaluationNode::OPERATOR); pOperatorNode = dynamic_cast<CEvaluationNodeOperator*>(pNode); CPPUNIT_ASSERT(pOperatorNode != NULL); CPPUNIT_ASSERT((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOperatorNode->getType()) == CEvaluationNodeOperator::PLUS); ++it; CPPUNIT_ASSERT(it.isValid() == false); CPPUNIT_ASSERT(*it == NULL); delete pTree; }