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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}