COPASI API  4.16.103
Static Public Member Functions | Static Public Attributes | Static Protected Member Functions | Static Protected Attributes | List of all members
CNormalTranslation Class Reference

#include <CNormalTranslation.h>

Collaboration diagram for CNormalTranslation:
Collaboration graph
[legend]

Static Public Member Functions

static CEvaluationNodecreateChain (const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
 
static CEvaluationNodecreateChain (const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< CEvaluationNode * > &elements)
 
static CEvaluationNodecreateOperatorChain (CEvaluationNodeOperator::SubType type, const char *data, const std::vector< CEvaluationNode * > &nodes)
 
static CEvaluationNodecreateOperatorChain (CEvaluationNodeOperator::SubType type, const char *data, const std::vector< const CEvaluationNode * > &nodes)
 
static CEvaluationNodeexpandPowerBases (const CEvaluationNode *pRoot)
 
static CEvaluationNodeexpandPowerExponents (const CEvaluationNode *pRoot)
 
static CEvaluationNodeexpandProducts (const CEvaluationNode *pOrig)
 
static void findSummands (const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &summands)
 
static bool has_duplicate_nodes (const CEvaluationNode *pNode)
 
static CEvaluationNodenewEvaluateNumbers (const CEvaluationNode *pOrig)
 
static CNormalFractionnormAndSimplify (const CEvaluationNode *root0)
 
static CNormalFractionnormAndSimplifyReptdly (const CEvaluationTree *tree0, unsigned int depth=0)
 
static CNormalFractionnormAndSimplifyReptdly (const CEvaluationNode *tree0, unsigned int depth=0)
 
static CEvaluationNodesimplifyTree (const CEvaluationNode *node)
 
static CEvaluationNodesimplifyTreeReptdly (const CEvaluationNode *root0)
 
static void splitProduct (const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &multiplications, std::vector< const CEvaluationNode * > &divisions, bool division)
 
static void splitSum (const CEvaluationNode *pRoot, std::vector< CEvaluationNode * > &additions, std::vector< CEvaluationNode * > &substractions, bool minus)
 
static void splitSum (const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &additions, std::vector< const CEvaluationNode * > &substractions, bool minus)
 

Static Public Attributes

static const CEvaluationNode NEUTRAL_ELEMENT_ADD = CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "0.0")
 
static const CEvaluationNode NEUTRAL_ELEMENT_AND = CEvaluationNodeConstant(CEvaluationNodeConstant::TRUE, "TRUE")
 
static const CEvaluationNode NEUTRAL_ELEMENT_MULTIPLY = CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "1.0")
 
static const CEvaluationNode NEUTRAL_ELEMENT_OR = CEvaluationNodeConstant(CEvaluationNodeConstant::FALSE, "FALSE")
 
static const CEvaluationNode ONE_NODE = CNormalTranslation::NEUTRAL_ELEMENT_MULTIPLY
 
static const CEvaluationNode PLUS_NODE = CEvaluationNodeOperator(CEvaluationNodeOperator::PLUS, "+")
 
static const CEvaluationNode TIMES_NODE = CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*")
 
static const CEvaluationNode ZERO_NODE = CNormalTranslation::NEUTRAL_ELEMENT_ADD
 

Static Protected Member Functions

static CEvaluationNodeelementaryElimination (CEvaluationNode *pOrig)
 
static CEvaluationNodeelementaryEliminationDivide (const CEvaluationNode *pDivideNode)
 
static CEvaluationNodeelementaryEliminationFunction (const CEvaluationNode *pFunctionNode)
 
static CEvaluationNodeelementaryEliminationMinus (const CEvaluationNode *pMinusNode)
 
static CEvaluationNodeelementaryEliminationModulus (const CEvaluationNode *pModulusNode)
 
static CEvaluationNodeelementaryEliminationMultiply (const CEvaluationNode *pMultiplyNode)
 
static CEvaluationNodeelementaryEliminationPlus (const CEvaluationNode *pPlusNode)
 
static CEvaluationNodeelementaryEliminationPower (const CEvaluationNode *pPowerNode)
 
static CEvaluationNodeeliminate (const CEvaluationNode *pOrig)
 
static CEvaluationNodeeliminateDirectlyNestedFractions (const CEvaluationNode *pOrig)
 
static CEvaluationNodeeliminateNestedPowers (const CEvaluationNode *pOrig)
 
static CEvaluationNodeeliminatePowersOfFractions (const CEvaluationNode *pOrig)
 
static CEvaluationNodeexpandPowerNodes (const CEvaluationNode *pOrig)
 
static std::pair
< CEvaluationNode
*, CEvaluationNode * > 
factorize (const std::vector< CEvaluationNode * > &additions, const std::vector< CEvaluationNode * > &subtractions)
 
static void findNegativeNumbers (std::vector< const CEvaluationNode * > &v1, std::vector< CEvaluationNode * > &v2)
 
static std::vector< product_matchmatchPowerBases (const std::vector< const CEvaluationNode * > &multiplications, const std::vector< const CEvaluationNode * > &divisions)
 
static std::vector< std::pair
< CEvaluationNode
*, CEvaluationNode * > > 
matchSummands (const std::vector< CEvaluationNode * > &additions, const std::vector< CEvaluationNode * > &subtractions)
 
static std::vector< summ_matchmatchSummands (const std::vector< const CEvaluationNode * > &additions, const std::vector< const CEvaluationNode * > &subtractions)
 
static CEvaluationNodemultiply (const CEvaluationNode *pNode1, const CEvaluationNode *pNode2)
 
static CEvaluationNodenewCancel (const CEvaluationNode *pOrig)
 
static void order (const CEvaluationNode *pRoot, std::list< const CEvaluationNode * > &orderList)
 
static void printPointers (const CEvaluationNode *pNode, const char *indent="")
 
static CEvaluationNodeproduct2fraction (const CEvaluationNode *pOrig)
 
static CEvaluationNodesimplify (const CEvaluationNode *pOrig)
 
static void swapNegativeNumbers (std::vector< CEvaluationNode * > &v1, std::vector< CEvaluationNode * > &v2)
 

Static Protected Attributes

static const unsigned int RECURSION_LIMIT = 20
 
static const double ZERO = 1e-100
 

Detailed Description

The class for simplification and translation of trees into CNormal

Definition at line 84 of file CNormalTranslation.h.

Member Function Documentation

CEvaluationNode * CNormalTranslation::createChain ( const CEvaluationNode pLink,
const CEvaluationNode pNeutralElement,
const std::vector< const CEvaluationNode * > &  elements 
)
static

More general version of createOperatorChain. This method can also be used to combine logical item chains. Once I know this works, I will replace createOperatorChain with this method.

This version of create chain copies the given elements in the vector and then calls the createChain method which does not need copying.

Definition at line 5905 of file CNormalTranslation.cpp.

Referenced by convertToCEvaluationNode(), createFraction(), createProduct(), expandPowerBases(), expandPowerExponents(), expandPowerNodes(), factorize(), matchSummands(), multiply(), newCancel(), and newEvaluateNumbers().

5906 {
5907  std::vector<CEvaluationNode*> tmpVector;
5908  tmpVector.reserve(elements.size());
5909  std::vector<const CEvaluationNode*>::const_iterator it = elements.begin(), endit = elements.end();
5910 
5911  while (it != endit)
5912  {
5913  tmpVector.push_back((*it)->copyBranch());
5914  ++it;
5915  }
5916 
5917  return CNormalTranslation::createChain(pLink, pNeutralElement, tmpVector);
5918 }
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
CEvaluationNode * CNormalTranslation::createChain ( const CEvaluationNode pLink,
const CEvaluationNode pNeutralElement,
const std::vector< CEvaluationNode * > &  elements 
)
static

More general version of createOperatorChain. This version does not copy the nodes in the given vector, but uses them directly. This method can also be used to combine logical item chains. method.

This method creates a chain of operations. The individual elements are linked with copies of pLink. NULL is returned if elements is empty. So if this method is used to create a chanin of OR linked elements which will be embedded in another and linked chain, the neutral element should be a TRUE node since AND combining something with true does not change the result. The neutral element is the element that does not change the result of the operation represented be pLink. So if pLink represents a multiplication, the neutral element is the number node 1.0. This method does not copy the elements in the given vector, but uses them in the chain directly.

Definition at line 5933 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), and pResult.

5934 {
5935  CEvaluationNode* pResult = NULL;
5936 
5937  if (elements.size() == 1)
5938  {
5939  pResult = elements[0];
5940  }
5941  else if (elements.size() > 1)
5942  {
5943  std::vector<CEvaluationNode*>::const_reverse_iterator it = elements.rbegin(), endit = elements.rend();
5944  CEvaluationNode* pOperator = pLink->copyBranch();
5945  CEvaluationNode* pChild = *it;
5946  ++it;
5947  pOperator->addChild(*it);
5948  pOperator->addChild(pChild);
5949  ++it;
5950  pChild = pOperator;
5951 
5952  while (it != endit)
5953  {
5954  pOperator = pLink->copyBranch();
5955  pOperator->addChild(*it);
5956  pOperator->addChild(pChild);
5957  pChild = pOperator;
5958  ++it;
5959  }
5960 
5961  pResult = pOperator;
5962  }
5963 
5964  return pResult;
5965 }
CEvaluationNode * copyBranch() const
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
const CArrayAnnotation * pResult
CEvaluationNode * CNormalTranslation::createOperatorChain ( CEvaluationNodeOperator::SubType  type,
const char *  data,
const std::vector< CEvaluationNode * > &  nodes 
)
static

Given a vector of nodes, this method creates a multiplication chain of all the nodes. The chain contains copies of the nodes passed in.

Given a vector of nodes, this method creates a multiplication chain of all the nodes. The chain contains the original nodes and not copies.

Definition at line 5887 of file CNormalTranslation.cpp.

Referenced by factorize(), and matchSummands().

5888 {
5889  std::vector<const CEvaluationNode*> tmpV;
5890  std::vector<CEvaluationNode*>::const_iterator it = nodes.begin(), endit = nodes.end();
5891 
5892  while (it != endit)
5893  {
5894  tmpV.push_back(*it);
5895  ++it;
5896  }
5897 
5898  return CNormalTranslation::createOperatorChain(type, data, tmpV);
5899 }
static CEvaluationNode * createOperatorChain(CEvaluationNodeOperator::SubType type, const char *data, const std::vector< CEvaluationNode * > &nodes)
CEvaluationNode * CNormalTranslation::createOperatorChain ( CEvaluationNodeOperator::SubType  type,
const char *  data,
const std::vector< const CEvaluationNode * > &  nodes 
)
static

Given a vector of nodes, this method creates a multiplication chain of all the nodes. The chain contains copies of the nodes passed in.

Concatenates the goven nodes by the given operation. So if the nodes are node1, node2,node3 and the operation is multiplication, this will create node1 * node2 * node3 The node that is returned contains copies of the original nodes and the caller is responsible for freeing the memory.

Definition at line 298 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), CEvaluationNodeNumber::DOUBLE, and pResult.

299 {
300  CEvaluationNode* pResult = NULL;
301 
302  if (nodes.size() == 0)
303  {
305  }
306  else if (nodes.size() == 1)
307  {
308  pResult = nodes[0]->copyBranch();
309  }
310  else
311  {
312  // start from the back to create the deepest nodes first
313  std::vector<const CEvaluationNode*>::const_reverse_iterator it = nodes.rbegin(), endit = nodes.rend();
314  CEvaluationNode* pOperator = new CEvaluationNodeOperator(type, data);
315  CEvaluationNode* pChild2 = (*it)->copyBranch();
316  ++it;
317  CEvaluationNode* pChild1 = (*it)->copyBranch();
318  pOperator->addChild(pChild1);
319  pOperator->addChild(pChild2);
320  ++it;
321  pChild2 = pOperator;
322 
323  while (it != endit)
324  {
325  pOperator = new CEvaluationNodeOperator(type, data);
326  pOperator->addChild((*it)->copyBranch());
327  pOperator->addChild(pChild2);
328  pChild2 = pOperator;
329  ++it;
330  }
331 
332  pResult = pOperator;
333  }
334 
335  return pResult;
336 }
CEvaluationNode * copyBranch() const
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
const CArrayAnnotation * pResult
CEvaluationNode * CNormalTranslation::elementaryElimination ( CEvaluationNode pOrig)
staticprotected

This routine is responsible for all elementary eliminations, e.g. addition of 0. These steps can not lead to new simplifications in the children of the node being simplified, so it is not necessary to run this on the children again.

This routine is responsible for all elementary eliminations, e.g. addition of 0. These steps can not lead to new simplifications in the children of the node being simplified, so it is not necessary to run this on the children again.

Calls one of the following: elementaryEliminationPower elementaryEliminationModulus elementaryEliminationMultiply elementaryEliminationDivide elementaryEliminationPlus elementaryEliminationMinus elementaryEliminationFunction

Which method is called depends on the node passed to the method. The method is called recursively on the children of the passed in node.

Definition at line 622 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNodeOperator::DIVIDE, elementaryEliminationDivide(), elementaryEliminationFunction(), elementaryEliminationMinus(), elementaryEliminationModulus(), elementaryEliminationMultiply(), elementaryEliminationPlus(), elementaryEliminationPower(), fatalError, CEvaluationNode::FUNCTION, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MODULUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::PLUS, CEvaluationNodeOperator::POWER, pResult, CCopasiNode< _Data >::removeChild(), CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by eliminate().

623 {
624  // this is done depth first
625  CEvaluationNode* pResult = pOrig;
626  CEvaluationNode* pChild = dynamic_cast<CEvaluationNode*>(pOrig->getChild());
627  CEvaluationNode* pLastChild = pOrig;
628 
629  while (pChild != NULL)
630  {
631  CEvaluationNode* pNewChild = elementaryElimination(pChild);
632  assert(pNewChild != NULL);
633 
634  if (pNewChild != pChild)
635  {
636  // remove the old child and add the new one
637  pOrig->removeChild(pChild);
638  delete pChild;
639  pChild = pNewChild;
640  pOrig->addChild(pNewChild, pLastChild);
641  }
642 
643  pLastChild = pChild;
644  pChild = dynamic_cast<CEvaluationNode*>(pChild->getSibling());
645  }
646 
648  {
649  // check if we can eliminate anything
650  // check if one of the children is (-)0, (-)1, NaN or INFINITY
652  {
655  break;
658  break;
661  break;
664  break;
667  break;
670  break;
671  default:
672  // we should never end up here
673  fatalError();
674  break;
675  }
676  }
678  {
680  }
681 
682  if (pResult == NULL)
683  {
684  pResult = pOrig;
685  }
686 
687  return pResult;
688 }
static CEvaluationNode * elementaryEliminationModulus(const CEvaluationNode *pModulusNode)
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
#define fatalError()
const Type & getType() const
static CEvaluationNode * elementaryEliminationDivide(const CEvaluationNode *pDivideNode)
static Type type(const Type &type)
static CEvaluationNode * elementaryEliminationPlus(const CEvaluationNode *pPlusNode)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static CEvaluationNode * elementaryEliminationPower(const CEvaluationNode *pPowerNode)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
static CEvaluationNode * elementaryEliminationMinus(const CEvaluationNode *pMinusNode)
static CEvaluationNode * elementaryElimination(CEvaluationNode *pOrig)
virtual bool removeChild(CCopasiNode< Data > *pChild)
Definition: CCopasiNode.h:181
static CEvaluationNode * elementaryEliminationFunction(const CEvaluationNode *pFunctionNode)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static CEvaluationNode * elementaryEliminationMultiply(const CEvaluationNode *pMultiplyNode)
CEvaluationNode * CNormalTranslation::elementaryEliminationDivide ( const CEvaluationNode pDivideNode)
staticprotected

This method makes the elementary elimination on a divide node.

This method makes the elementary elimination on a divide node.

The following eliminations are made: a) Nan / x -> Nan b) x / NaN -> NaN c) x / 0 -> NaN d) 0 / x -> 0 e) x / x -> 1 f) x / 1 -> x

The caller is responsible for freeing the memory for the returned object.

Definition at line 1116 of file CNormalTranslation.cpp.

References CEvaluationNodeConstant::_NaN, CEvaluationNode::CONSTANT, CEvaluationNode::copyBranch(), createNormalRepresentation(), CEvaluationNodeOperator::DIVIDE, CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, pResult, CEvaluationNode::subType(), CNormalFraction::toString(), CEvaluationNode::type(), and ZERO.

Referenced by elementaryElimination().

1117 {
1118  CEvaluationNode* pResult = NULL;
1119  assert(CEvaluationNode::type(pDivideNode->getType()) == CEvaluationNode::OPERATOR);
1121  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pDivideNode->getChild());
1122  assert(pChild1 != NULL);
1123  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
1124  assert(pChild2 != NULL);
1125  assert(pChild2->getSibling() == NULL);
1126  // if one of the children is NaN, the result is NaN
1127  CNormalFraction* base1 = createNormalRepresentation(pChild1);
1128  CNormalFraction* base2 = createNormalRepresentation(pChild2);
1129 
1130  if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::CONSTANT &&
1134  {
1136  }
1137  // the second child is 0, the result is NaN
1138  else if ((CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER &&
1139  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild2)->getValue()) < ZERO))
1140  {
1142  }
1143  // if the first child is 0, the result is 0
1144  else if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER &&
1145  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild1)->getValue()) < ZERO))
1146  {
1148  }
1149  // if both children are the same, the result is 1
1150  else if (base1->toString() == base2->toString())
1151  {
1153  }
1154  // if the second child is 1, the result is the first child
1155  else if ((CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER &&
1156  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild2)->getValue() - 1.0) < ZERO))
1157  {
1158  pResult = pChild1->copyBranch();
1159  }
1160 
1161  delete base1;
1162  delete base2;
1163  base1 = NULL;
1164  base2 = NULL;
1165  return pResult;
1166 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static Type type(const Type &type)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
virtual std::string toString() const
CNormalFraction * createNormalRepresentation(const CEvaluationNode *node)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static const double ZERO
CEvaluationNode * CNormalTranslation::elementaryEliminationFunction ( const CEvaluationNode pFunctionNode)
staticprotected

This method makes elementary eliminations on function nodes

This method makes elementary eliminations on function nodes The elimiation made here are:

a) unary plus nodes are replaced by their child b) unary minus nodes of numbers are replaced by the corresponding number * -1 c) Function calls to NaN nodes are replaced by NaN

The node returned by this method is a new node and the caller is responsible for freeing the memory.

Definition at line 700 of file CNormalTranslation.cpp.

References CEvaluationNodeConstant::_NaN, CEvaluationNode::CONSTANT, CEvaluationNode::copyBranch(), CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeFunction::INVALID, CEvaluationNodeFunction::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, CEvaluationNodeFunction::PLUS, pResult, CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by elementaryElimination().

701 {
702  // PLUS(X) -> X
703  // X(NaN) -> NaN
704  // MINUX(X) where X is a number -> -X
705  CEvaluationNode* pResult = NULL;
706  const CEvaluationNode* pChild = NULL;
707 
709  {
711  break;
713  pChild = dynamic_cast<const CEvaluationNode*>(pFunctionNode->getChild());
714  assert(pChild != NULL);
715  assert(pChild->getSibling() == NULL);
716  pResult = pChild->copyBranch();
717  break;
719  pChild = dynamic_cast<const CEvaluationNode*>(pFunctionNode->getChild());
720  assert(pChild != NULL);
721  assert(pChild->getSibling() == NULL);
722 
724  {
725  std::ostringstream os;
726  os.precision(18);
727  os << -1.0*dynamic_cast<const CEvaluationNodeNumber*>(pChild)->getValue();
728  pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
729  }
732  {
734  }
735 
736  if (pResult == NULL)
737  {
738  // MINUS(X) -> -1.0 * X
740  pResult->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "-1.0"));
741  pResult->addChild(pChild->copyBranch());
742  }
743 
744  break;
745  default:
746  pChild = dynamic_cast<const CEvaluationNode*>(pFunctionNode->getChild());
747 
748  while (pChild != NULL)
749  {
751  {
753  break;
754  }
755 
756  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
757  }
758 
759  break;
760  }
761 
762  return pResult;
763 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static Type type(const Type &type)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * CNormalTranslation::elementaryEliminationMinus ( const CEvaluationNode pMinusNode)
staticprotected

This method makes the elementary elimination on a minus node.

This method makes the elementary elimination on a minus node. The following eliminations are made: a) NaN - x -> NaN b) x - NaN -> NaN c) x - x -> 0 d) x - 0 -> x e) 0 - x -> -1 * x

The caller is responsible for freeing the memory of the returned object.

Definition at line 1222 of file CNormalTranslation.cpp.

References CEvaluationNodeConstant::_NaN, CCopasiNode< _Data >::addChild(), CEvaluationNode::CONSTANT, CEvaluationNode::copyBranch(), createNormalRepresentation(), CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, pResult, CEvaluationNode::subType(), CNormalFraction::toString(), CEvaluationNode::type(), and ZERO.

Referenced by elementaryElimination().

1223 {
1224  CEvaluationNode* pResult = NULL;
1225  assert(CEvaluationNode::type(pMinusNode->getType()) == CEvaluationNode::OPERATOR);
1227  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pMinusNode->getChild());
1228  assert(pChild1 != NULL);
1229  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
1230  assert(pChild2 != NULL);
1231  assert(pChild2->getSibling() == NULL);
1232  // if one child is NaN, the result is NaN (one could also consider to put
1233  // the second condition first so that to NaN would cancel each other out
1234  CNormalFraction* base1 = createNormalRepresentation(pChild1);
1235  CNormalFraction* base2 = createNormalRepresentation(pChild2);
1236 
1237  if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::CONSTANT &&
1241  {
1243  }
1244  // if both nodes are equal, the result is 0.0
1245  else if (base1->toString() == base2->toString())
1246  {
1248  }
1249  // the second child is 0, the result is the first child
1250  else if ((CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER &&
1251  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild2)->getValue()) < ZERO))
1252  {
1253  pResult = pChild1->copyBranch();
1254  }
1255  // if the first child is 0, the result is -1 times the second child
1256  else if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER &&
1257  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild1)->getValue()) < ZERO))
1258  {
1261  pResult->addChild(pChild2->copyBranch());
1262  }
1263 
1264  delete base1;
1265  delete base2;
1266  base1 = NULL;
1267  base2 = NULL;
1268  return pResult;
1269 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
const CArrayAnnotation * pResult
static Type subType(const Type &type)
virtual std::string toString() const
CNormalFraction * createNormalRepresentation(const CEvaluationNode *node)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static const double ZERO
CEvaluationNode * CNormalTranslation::elementaryEliminationModulus ( const CEvaluationNode pModulusNode)
staticprotected

This method makes the elementary elimination on a modulus node.

This method makes the elementary elimination on a modulus node. The following eliminations are made: a) NaNx -> NaN b) xNaN -> NaN c) xx -> 0 d) 0x -> 0 e) 1n -> 1 (n is a number, other than 1)

The caller is responsible for freeing the memory of the returned object.

Definition at line 987 of file CNormalTranslation.cpp.

References CEvaluationNodeConstant::_NaN, CEvaluationNode::CONSTANT, createNormalRepresentation(), CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::getValue(), CEvaluationNodeOperator::MODULUS, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, pResult, CEvaluationNode::subType(), CNormalFraction::toString(), CEvaluationNode::type(), and ZERO.

Referenced by elementaryElimination().

988 {
989  CEvaluationNode* pResult = NULL;
990  assert(CEvaluationNode::type(pModulusNode->getType()) == CEvaluationNode::OPERATOR);
992  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pModulusNode->getChild());
993  assert(pChild1 != NULL);
994  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
995  assert(pChild2 != NULL);
996  assert(pChild2->getSibling() == NULL);
997 
998  // if one child is NaN, the result is NaN
999  if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::CONSTANT &&
1003  {
1005  }
1006 
1007  // X%X -> 0
1008  CNormalFraction* base1 = createNormalRepresentation(pChild1);
1009  CNormalFraction* base2 = createNormalRepresentation(pChild2);
1010 
1011  if (base1->toString() == base2->toString())
1012  {
1014  }
1015  else if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER)
1016  {
1017  // 0 and 1
1018  const CEvaluationNodeNumber* pNumberNode = dynamic_cast<const CEvaluationNodeNumber*>(pChild1);
1019  assert(pNumberNode != NULL);
1020  double value = pNumberNode->getValue();
1021 
1022  if (fabs(value) < ZERO)
1023  {
1025  }
1026  else if (fabs(value - 1.0) < ZERO)
1027  {
1028  // 1%X where X is any number other than 1 will give 1.0
1029  // the case where X is 1 is already covered above
1031  {
1033  }
1034  }
1035 
1036  // ignore the rest
1037  }
1038  else if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
1039  {
1040  // 0 and 1
1041  }
1042 
1043  delete base1;
1044  delete base2;
1045  base1 = NULL;
1046  base2 = NULL;
1047  return pResult;
1048 }
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const C_FLOAT64 & getValue() const
const Type & getType() const
static Type type(const Type &type)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
virtual std::string toString() const
CNormalFraction * createNormalRepresentation(const CEvaluationNode *node)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static const double ZERO
CEvaluationNode * CNormalTranslation::elementaryEliminationMultiply ( const CEvaluationNode pMultiplyNode)
staticprotected

This method makes the elementary elimination on a multiply node.

This method makes the elementary elimination on a multiply node. The following eliminations are made: a) NaN * x -> NaN b) 0 * x -> 0 c) 1 * x -> x

The caller is responsible for freeing the memory of the returned object.

Definition at line 1060 of file CNormalTranslation.cpp.

References CEvaluationNodeConstant::_NaN, CEvaluationNode::CONSTANT, CEvaluationNode::copyBranch(), CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, pResult, CEvaluationNode::subType(), CEvaluationNode::type(), and ZERO.

Referenced by elementaryElimination().

1061 {
1062  CEvaluationNode* pResult = NULL;
1063  assert(CEvaluationNode::type(pMultiplyNode->getType()) == CEvaluationNode::OPERATOR);
1065  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pMultiplyNode->getChild());
1066  assert(pChild1 != NULL);
1067  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
1068  assert(pChild2 != NULL);
1069  assert(pChild2->getSibling() == NULL);
1070 
1071  // if one child is NaN, the result is NaN
1072  if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::CONSTANT &&
1076  {
1078  }
1079  // if one child is 0, the result is 0
1080  else if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER &&
1081  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild1)->getValue()) < ZERO) ||
1083  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild2)->getValue()) < ZERO))
1084  {
1086  }
1087  // if one child is 1, the result is the other child
1088  else if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER &&
1089  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild1)->getValue() - 1.0) < ZERO))
1090  {
1091  pResult = pChild2->copyBranch();
1092  }
1093  else if ((CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER &&
1094  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild2)->getValue() - 1.0) < ZERO))
1095  {
1096  pResult = pChild1->copyBranch();
1097  }
1098 
1099  return pResult;
1100 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static Type type(const Type &type)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static const double ZERO
CEvaluationNode * CNormalTranslation::elementaryEliminationPlus ( const CEvaluationNode pPlusNode)
staticprotected

This method makes the elementary elimination on a plus node.

This method makes the elementary elimination on a plus node. The following eliminations are made: a) NaN + x -> NaN b) 0 + x -> x (also x + 0)

The caller is responsible for freeing the memory for the returned object.

Definition at line 1176 of file CNormalTranslation.cpp.

References CEvaluationNodeConstant::_NaN, CEvaluationNode::CONSTANT, CEvaluationNode::copyBranch(), CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::PLUS, pResult, CEvaluationNode::subType(), CEvaluationNode::type(), and ZERO.

Referenced by elementaryElimination().

1177 {
1178  CEvaluationNode* pResult = NULL;
1179  assert(CEvaluationNode::type(pPlusNode->getType()) == CEvaluationNode::OPERATOR);
1181  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pPlusNode->getChild());
1182  assert(pChild1 != NULL);
1183  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
1184  assert(pChild2 != NULL);
1185  assert(pChild2->getSibling() == NULL);
1186 
1187  // if one child is NaN, the result is NaN
1188  if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::CONSTANT &&
1192  {
1194  }
1195  // the second child is 0, the result is the first child
1196  else if ((CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER &&
1197  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild2)->getValue()) < ZERO))
1198  {
1199  pResult = pChild1->copyBranch();
1200  }
1201  // if the first child is 0, the result is the second child
1202  else if ((CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER &&
1203  fabs(dynamic_cast<const CEvaluationNodeNumber*>(pChild1)->getValue()) < ZERO))
1204  {
1205  pResult = pChild2->copyBranch();
1206  }
1207 
1208  return pResult;
1209 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static Type type(const Type &type)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static const double ZERO
CEvaluationNode * CNormalTranslation::elementaryEliminationPower ( const CEvaluationNode pPowerNode)
staticprotected

This method makes the elementary elimination on a power node.

This method makes the elementary elimination on a power node. This method makes the following elimination a) x^NaN -> NaN b) 0^0 -> NaN c) 0^(-x) -> NaN d) 0^x -> 0 e) 1^x -> 1 f) NaN^x -> NaN g) NFINITY^(-NaN) -> NaN i) INFINITY^-x -> 0.0 // x being a positive number j) INFINITY^x -> INFINITY // x being a positive number k) INFINITY^0 -> 1 l) INFINITY^0 -> 1.0 m) INFINITY^(-x) -> 0.0 n) INFINITY^x -> INFINITY o) INFINITY ^ x -> INFINITY p) x^0 -> 1 q) x^1 -> x

The caller is responsible for releasing the memory for the returned object.

Definition at line 787 of file CNormalTranslation.cpp.

References CEvaluationNodeConstant::_INFINITY, CEvaluationNodeConstant::_NaN, CEvaluationNode::CONSTANT, CEvaluationNode::copyBranch(), CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::getValue(), CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::POWER, pResult, CEvaluationNode::subType(), CEvaluationNode::type(), and ZERO.

Referenced by elementaryElimination().

788 {
789  CEvaluationNode* pResult = NULL;
790  assert(CEvaluationNode::type(pPowerNode->getType()) == CEvaluationNode::OPERATOR);
792  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pPowerNode->getChild());
793  assert(pChild1 != NULL);
794  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
795  assert(pChild2 != NULL);
796  assert(pChild2->getSibling() == NULL);
797 
798  if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER)
799  {
800  // 0 and 1
801  const CEvaluationNodeNumber* pNumberNode = dynamic_cast<const CEvaluationNodeNumber*>(pChild1);
802  assert(pNumberNode != NULL);
803  double value = pNumberNode->getValue();
804 
805  if (fabs(value) < ZERO)
806  {
807  // 0^(NaN) -> NaN
809  {
811  }
812  else if (pChild2->getType() == CEvaluationNode::NUMBER)
813  {
814  const CEvaluationNodeNumber* pNumberNode2 = dynamic_cast<const CEvaluationNodeNumber*>(pChild2);
815  double value = pNumberNode2->getValue();
816 
817  // 0^0 -> NaN
818  // 0^(-x) -> NaN
819  if (fabs(value) < ZERO || value < 0.0)
820  {
822  }
823  }
824 
825  // 0^x -> 0
826  if (pResult == pPowerNode)
827  {
829  }
830  }
831  else if (fabs(value - 1.0) < ZERO)
832  {
833  // 1^NaN -> NaN
834  // 1^x -> 1
836  {
838  }
839 
840  if (pResult == NULL)
841  {
843  }
844  }
845 
846  /* ignore -1 for now
847  else if(fabs(value + 1.0) < ZERO)
848  {
849  }
850  */
851  }
852  else if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::CONSTANT)
853  {
854  // infinity and NaN
856  {
857  // NaN^x -> NaN
859  }
861  {
862  // INFINITY^(-NaN) -> NaN
863  // INFINITY^-x -> 0.0 // x being a positive number
864  // INFINITY^x -> INFINITY // x being a positive number
865  // INFINITY^0 -> 1
867  {
868  const CEvaluationNodeNumber* pNumberNode2 = dynamic_cast<const CEvaluationNodeNumber*>(pChild2);
869  assert(pNumberNode2 != NULL);
870  double value = pNumberNode2->getValue();
871 
872  // INFINITY^0 -> 1
873  if (fabs(value) < ZERO)
874  {
876  }
877  // INFINITY^x -> INFINITY // x being a positive number
878  else if (value > 0.0)
879  {
881  }
882  // INFINITY^-x -> 0.0 // x being a positive number
883  else
884  {
886  }
887  }
889  {
890  // INFINITY^NaN -> NaN
892  }
893  /* the minus function is eliminated
894  else if(CEvaluationNode::type(pChild2->getType())==CEvaluationNode::FUNCTION && ((CEvaluationNodeFunction::SubType)CEvaluationNode::subType(pChild2->getType()))==CEvaluationNodeFunction::MINUS)
895  {
896  CEvaluationNode* pChild=dynamic_cast<CEvaluationNode*>(pChild2->getChild());
897  // INFINITY^(-CONSTANT) -> 0.0 // where CONSTANT != NaN
898  if(CEvaluationNode::type(pChild->getType())==CEvaluationNode::CONSTANT)
899  {
900  pResult=new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE,"0.0");
901  }
902  }
903  */
904  else if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
905  {
906  const CEvaluationNodeNumber* pNumberNode2 = dynamic_cast<const CEvaluationNodeNumber*>(pChild2);
907  assert(pNumberNode2 != NULL);
908  double value = pNumberNode2->getValue();
909 
910  // INFINITY^0 -> 1.0
911  if (fabs(value) < ZERO)
912  {
914  }
915  // INFINITY^(-x) -> 0.0
916  else if (value > 0.0)
917  {
919  }
920  // INFINITY^x -> INFINITY
921  else
922  {
924  }
925  }
926 
927  // INFINITY ^ x -> INFINITY
928  if (pResult == NULL)
929  {
931  }
932  }
933  }
934  else if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
935  {
936  // 0 and 1
937  const CEvaluationNodeNumber* pNumberNode2 = dynamic_cast<const CEvaluationNodeNumber*>(pChild2);
938  assert(pNumberNode2 != NULL);
939  double value = pNumberNode2->getValue();
940 
941  // x^0 -> 1.0
942  if (fabs(value) < ZERO)
943  {
945  }
946  else if (fabs(value - 1.0) < ZERO)
947  {
948  // make a deep copy of the first child
949  pResult = pChild1->copyBranch();
950  }
951 
952  /* ignore -1 since this may interfere with other simplification
953  * mechanisms.
954  * Negative exponents will be eliminated in the end.
955  else if(fabs(value + 1.0) < ZERO)
956  {
957  }
958  */
959  }
961  {
962  // infinity and NaN
964  {
965  pResult = pChild2->copyBranch();
966  }
968  {
969  pResult = pChild2->copyBranch();
970  }
971  }
972 
973  return pResult;
974 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const C_FLOAT64 & getValue() const
const Type & getType() const
static Type type(const Type &type)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static const double ZERO
CEvaluationNode * CNormalTranslation::eliminate ( const CEvaluationNode pOrig)
staticprotected

This method elminates subexpressions from an expression

This method elminates subexpressions from an expression It calls: elementaryElimination eliminateNestedPowers eliminatePowersOfFractions eliminateDirectlyNestedFunctions cancel

These functions are called as long as the resulting tree contains changes

Definition at line 402 of file CNormalTranslation.cpp.

References CEvaluationNode::buildInfix(), CEvaluationNode::copyBranch(), elementaryElimination(), eliminateDirectlyNestedFractions(), eliminateNestedPowers(), eliminatePowersOfFractions(), newCancel(), and pResult.

Referenced by simplify().

403 {
404  CEvaluationNode* pResult = pOrig->copyBranch();
405  CEvaluationNode* pTmp = NULL;
406  std::string infix = pResult->buildInfix(); //base->toString();
407  //delete base;
408  bool changed = true;
409 
410  while (changed)
411  {
412  // first make elementary eliminations
414 
415  if (pTmp != pResult) delete pResult;
416 
417  // now get rid of nested powers a^b^c
419 
420  if (pResult != NULL)
421  {
422  delete pTmp;
423  pTmp = pResult;
424  }
425 
426  // eliminate fractions within powers
427  // (a/b)^3 -> a^3 / b^3
428  // now get rid of directly nested fractions
430 
431  if (pResult != NULL)
432  {
433  delete pTmp;
434  pTmp = pResult;
435  }
436 
438 
439  if (pResult != NULL)
440  {
441  delete pTmp;
442  }
443  else
444  {
445  pResult = pTmp;
446  }
447 
448  // now cancel since cancelation can lead to new nodes for which
449  // elementary elimination would be possible, we might have to run
450  // this loop again
451  pTmp = CNormalTranslation::newCancel(pResult);
452  //std::cout << "Before: " << pResult->buildInfix() << std::endl;
453 
454 
455  if (pTmp != NULL)
456  {
457  delete pResult;
458  }
459  else
460  {
461  pTmp = pResult;
462  }
463 
464  //std::cout << "Finished: " << pTmp->buildInfix() << std::endl;
465  //delete pResult;
466 
467  // check if we are done
468  // we are done if the infix has not changed over one loop run
469  if (/*base->toString()*/pTmp->buildInfix() == infix)
470  {
471  changed = false;
472  }
473  else
474  {
475  infix = pTmp->buildInfix(); //base->toString();
476  }
477 
478  pResult = pTmp;
479  //delete base;
480  //base = NULL;
481  }
482 
483  return pResult;
484 }
CEvaluationNode * copyBranch() const
std::string buildInfix() const
static CEvaluationNode * eliminateNestedPowers(const CEvaluationNode *pOrig)
const CArrayAnnotation * pResult
static CEvaluationNode * elementaryElimination(CEvaluationNode *pOrig)
static CEvaluationNode * eliminatePowersOfFractions(const CEvaluationNode *pOrig)
static CEvaluationNode * newCancel(const CEvaluationNode *pOrig)
static CEvaluationNode * eliminateDirectlyNestedFractions(const CEvaluationNode *pOrig)
CEvaluationNode * CNormalTranslation::eliminateDirectlyNestedFractions ( const CEvaluationNode pOrig)
staticprotected

This method eliminates directly nested fractions. ((a/b)/(c/d)) -> (a*d)/(b*c)

This method does all the canceling on a given node and its children. If no canceling was done, NULL is returned.

Obsolete recursive version This method does all the canceling on a given node and its children. CEvaluationNode* CNormalTranslation::cancel(const CEvaluationNode* pOrig) { TODO I think this method has much potential for improvement TODO since the comparison code seems to spend about 85% of the time TODO here, this is where I should start making optimizations

try to find multiplication chains where something is divided by itself or multiplied by -1 times itself also consider powers (it's the bases that have to match)

try to find addition changes where there is a subtraction of two identical nodes or an addition of one node and the same node times -1 CEvaluationNode* pResult = NULL; std::vector<CEvaluationNode*> children; std::cout << "Canceling: " << pOrig->buildInfix() << std::endl;

if (CEvaluationNode::type(pOrig->getType()) == CEvaluationNode::OPERATOR)
  {
    if (((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOrig->getType())) == CEvaluationNodeOperator::PLUS ||
        ((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOrig->getType())) == CEvaluationNodeOperator::MINUS)
      {

we are in a sum std::vector<CEvaluationNode*> additions, subtractions; CNormalTranslation::splitSum(pOrig, additions, subtractions, false); CNormalTranslation::swapNegativeNumbers(additions, subtractions); collect all nodes in additions and subtractions unsigned int i, iMax = additions.size();

for (i = 0; i < iMax; ++i) { CEvaluationNode* pChild = CNormalTranslation::cancel(additions[i]); delete additions[i]; additions[i] = pChild; }

iMax = subtractions.size();

for (i = 0; i < iMax; ++i) { CEvaluationNode* pChild = CNormalTranslation::cancel(subtractions[i]); delete subtractions[i]; subtractions[i] = pChild; }

find identical nodes in additions and subtractions The first entry in the pair is the collected factor the second entry is the original branch make sure the collected factor is again simplified std::vector<std::pair<CEvaluationNode*, CEvaluationNode*> > collected = CNormalTranslation::matchSummands(additions, subtractions); iMax = additions.size();

for (i = 0; i < iMax; ++i) { delete additions[i]; }

additions.clear(); iMax = subtractions.size();

for (i = 0; i < iMax; ++i) { delete subtractions[i]; }

subtractions.clear(); std::vector<CEvaluationNode*> chain; iMax = collected.size();

for (i = 0; i < iMax; ++i) { std::pair<CEvaluationNode*, CEvaluationNode*> pair = collected[i];

CEvaluationNode* pTmpNode = CNormalTranslation::eliminate(pair.first); delete pair.first; if simplified node is 0.0, we ignore this node if (CEvaluationNode::type(pair.first->getType()) == CEvaluationNode::NUMBER && fabs(dynamic_cast<CEvaluationNodeNumber*>(pair.first)->getValue()) < ZERO) { delete pair.first; delete pair.second; } else if (CEvaluationNode::type(pair.first->getType()) == CEvaluationNode::NUMBER && fabs(dynamic_cast<CEvaluationNodeNumber*>(pair.first)->getValue() - 1.0) < ZERO) { delete pair.first; chain.push_back(pair.second); } else { CEvaluationNode* pMult = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); pMult->addChild(pair.first); pMult->addChild(pair.second); chain.push_back(pMult); } }

pResult = CNormalTranslation::createChain(&CNormalTranslation::PLUS_NODE, &CNormalTranslation::ZERO_NODE, chain); assert(pResult != NULL); } else if (((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOrig->getType())) == CEvaluationNodeOperator::MULTIPLY || ((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pOrig->getType())) == CEvaluationNodeOperator::DIVIDE) { we are in a product std::vector<const CEvaluationNode*> multiplications, divisions; CNormalTranslation::splitProduct(pOrig, multiplications, divisions, false); collect all nodes in multiplications and divisions unsigned int i, iMax = multiplications.size();

for (i = 0; i < iMax; ++i) { multiplications[i] = CNormalTranslation::cancel(multiplications[i]); }

iMax = divisions.size();

for (i = 0; i < iMax; ++i) { divisions[i] = CNormalTranslation::cancel(divisions[i]); }

find identical nodes in multiplications and divisions The first entry in the pair is the collected power exponent the second entry is the original power base make sure the collected factor is again simplified std::vector<std::pair<CEvaluationNode*, CEvaluationNode*> > collected = CNormalTranslation::matchPowerBases(multiplications, divisions); iMax = multiplications.size();

for (i = 0; i < iMax; ++i) { delete multiplications[i]; }

multiplications.clear(); iMax = divisions.size();

for (i = 0; i < iMax; ++i) { delete divisions[i]; }

divisions.clear(); std::vector<CEvaluationNode*> numeratorChain; std::vector<CEvaluationNode*> denominatorChain; iMax = collected.size();

for (i = 0; i < iMax; ++i) { std::pair<CEvaluationNode*, CEvaluationNode*> pair = collected[i];

CEvaluationNode* pTmpNode = CNormalTranslation::eliminate(pair.first); delete pair.first; if simplified node is a 0.0, we ignore this node if (CEvaluationNode::type(pair.first->getType()) == CEvaluationNode::NUMBER) { if (fabs(dynamic_cast<CEvaluationNodeNumber*>(pair.first)->getValue()) < ZERO) { delete pair.first; delete pair.second; } else if (dynamic_cast<CEvaluationNodeNumber*>(pair.first)->getValue() > 0.0) { if (fabs(dynamic_cast<CEvaluationNodeNumber*>(pair.first)->getValue() - 1.0) < ZERO) { delete pair.first; numeratorChain.push_back(pair.second); } else { CEvaluationNode* pPower = new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^"); pPower->addChild(pair.second); pPower->addChild(pair.first); numeratorChain.push_back(pPower); } } else { if (fabs(dynamic_cast<CEvaluationNodeNumber*>(pair.first)->getValue() + 1.0) < ZERO) { delete pair.first; denominatorChain.push_back(pair.second); } else { CEvaluationNode* pPower = new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^"); pPower->addChild(pair.second); std::ostringstream os; os.precision(18); os << fabs(dynamic_cast<const CEvaluationNodeNumber*>(pair.first)->getValue()); pPower->addChild(new CEvaluationNodeNumber((CEvaluationNodeNumber::SubType)CEvaluationNode::subType(pair.first->getType()), os.str().c_str())); delete pair.first; denominatorChain.push_back(pPower); } } } else { CEvaluationNode* pPower = new CEvaluationNodeOperator(CEvaluationNodeOperator::POWER, "^");

check if the node is -1.0 * SOMETHING if (CEvaluationNode::type(pair.first->getType()) == CEvaluationNode::OPERATOR && (CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pair.first->getType()) == CEvaluationNodeOperator::MULTIPLY && CEvaluationNode::type(dynamic_cast<const CEvaluationNode*>(pair.first->getChild())->getType()) == CEvaluationNode::NUMBER) { if (fabs(static_cast<const CEvaluationNodeNumber*>(pair.first->getChild())->getValue() + 1.0) < ZERO) { pPower->addChild(pair.second); pPower->addChild(dynamic_cast<const CEvaluationNode*>(pair.first->getChild()->getSibling())->copyBranch()); delete pair.first; denominatorChain.push_back(pPower); } else if (fabs(static_cast<const CEvaluationNodeNumber*>(pair.first->getChild())->getValue()) < ZERO) { delete the power node and add delete pPower; delete pair.first; numeratorChain.push_back(pair.second); } else if (static_cast<const CEvaluationNodeNumber*>(pair.first->getChild())->getValue() < 0.0) { pPower->addChild(pair.second); pPower->addChild(pair.first); denominatorChain.push_back(pPower); } else { pPower->addChild(pair.second); pPower->addChild(pair.first); numeratorChain.push_back(pPower); } } else { pPower->addChild(pair.second); pPower->addChild(pair.first); numeratorChain.push_back(pPower); } } }

if there are only divisions, we have an empty numerator chain if (numeratorChain.empty()) { pResult = CNormalTranslation::ONE_NODE.copyBranch(); } else { pResult = CNormalTranslation::createChain(&CNormalTranslation::TIMES_NODE, &CNormalTranslation::ONE_NODE, numeratorChain); assert(pResult != NULL); }

if (!denominatorChain.empty()) { CEvaluationNode* pTmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::DIVIDE, "/"); pTmpNode->addChild(pResult); pResult = pTmpNode; pTmpNode = CNormalTranslation::createChain(&CNormalTranslation::TIMES_NODE, &CNormalTranslation::ONE_NODE, denominatorChain); assert(pTmpNode != NULL); pResult->addChild(pTmpNode); } } else { const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pOrig->getChild());

while (pChild != NULL) { children.push_back(CNormalTranslation::cancel(pChild)); pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling()); }

assert(children.size() == 2); } } else { const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pOrig->getChild());

while (pChild != NULL) { children.push_back(CNormalTranslation::cancel(pChild)); pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling()); } }

if (pResult == NULL) { pResult = pOrig->copyNode(children); }

if(pOrig->buildInfix() == pResult->buildInfix()) { std::cout << "Nothing Canceled." << std::endl; } else { std::cout << "Canceled: " << pResult->buildInfix() << std::endl; } return pResult; } This method eliminates directly nested fractions. A/B/C -> A/(B*C)

The caller is responsible for deleting the returned object.

Definition at line 5121 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), CEvaluationNode::copyNode(), CEvaluationNodeOperator::DIVIDE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::OPERATOR, pResult, CCopasiNode< _Data >::removeChild(), CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by eliminate().

5122 {
5123  if (pOrig == NULL) return NULL;
5124 
5125  CEvaluationNode* pResult = NULL;
5126  std::vector<CEvaluationNode*> children;
5127  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pOrig->getChild());
5128  CEvaluationNode* pNewChild = NULL;
5129  const CEvaluationNode* pTmpOrig = pOrig;
5130  bool childrenChanged = false;
5131 
5132  while (pChild != NULL)
5133  {
5135 
5136  if (pNewChild != NULL)
5137  {
5138  childrenChanged = true;
5139  }
5140 
5141  children.push_back(pNewChild);
5142  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
5143  }
5144 
5145  if (childrenChanged == true)
5146  {
5147  std::vector<CEvaluationNode*>::iterator it = children.begin(), endit = children.end();
5148  pChild = dynamic_cast<const CEvaluationNode*>(pTmpOrig->getChild());
5149 
5150  while (it != endit)
5151  {
5152  if ((*it) == NULL)
5153  {
5154  (*it) = pChild->copyBranch();
5155  }
5156 
5157  pChild = static_cast<const CEvaluationNode*>(pChild->getSibling());
5158  ++it;
5159  }
5160 
5161  assert(pChild == NULL);
5162  // make a copy of the original with the new children
5163  pResult = pTmpOrig->copyNode(children);
5164  pTmpOrig = pResult;
5165  }
5166 
5167 
5169  {
5170  // check if one of the children (or both) are a division
5171  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pTmpOrig->getChild());
5172  assert(pChild1 != NULL);
5173  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
5174  assert(pChild2 != NULL);
5175  assert(pChild2->getSibling() == NULL);
5176 
5178  {
5180  {
5181  // both children are division
5184  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild1->getChild())->copyBranch());
5185  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild2->getChild()->getSibling())->copyBranch());
5186  pTmpResult->addChild(pTmp);
5188  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild1->getChild()->getSibling())->copyBranch());
5189  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild2->getChild())->copyBranch());
5190  pTmpResult->addChild(pTmp);
5191 
5192  if (pResult != NULL)
5193  {
5194  delete pResult;
5195  }
5196 
5197  pResult = pTmpResult;
5198  }
5199  else
5200  {
5201  // only the first child is a division
5203  pTmpResult->addChild(dynamic_cast<const CEvaluationNode*>(pChild1->getChild())->copyBranch());
5205  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild1->getChild()->getSibling())->copyBranch());
5206 
5207  if (pResult == NULL)
5208  {
5209  pTmp->addChild(pChild2->copyBranch());
5210  }
5211  else
5212  {
5213  assert(pResult == pTmpOrig);
5214  pResult->removeChild(const_cast<CEvaluationNode*>(pChild2));
5215  pTmp->addChild(const_cast<CEvaluationNode*>(pChild2));
5216  delete pResult;
5217  }
5218 
5219  pTmpResult->addChild(pTmp);
5220  pResult = pTmpResult;
5221  }
5222  }
5224  {
5225  // only the second child is a division
5228 
5229  if (pResult != NULL)
5230  {
5231  assert(pTmpOrig == pResult);
5232  pResult->removeChild(const_cast<CEvaluationNode*>(pChild1));
5233  pTmp->addChild(const_cast<CEvaluationNode*>(pChild1));
5234  }
5235  else
5236  {
5237  pTmp->addChild(pChild1->copyBranch());
5238  }
5239 
5240  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild2->getChild()->getSibling())->copyBranch());
5241  pTmpResult->addChild(pTmp);
5242  pTmpResult->addChild(dynamic_cast<const CEvaluationNode*>(pChild2->getChild())->copyBranch());
5243 
5244  if (pResult != NULL)
5245  {
5246  delete pResult;
5247  }
5248 
5249  pResult = pTmpResult;
5250  }
5251  }
5252 
5253  return pResult;
5254 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
const Type & getType() const
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
const CArrayAnnotation * pResult
static Type subType(const Type &type)
virtual bool removeChild(CCopasiNode< Data > *pChild)
Definition: CCopasiNode.h:181
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static CEvaluationNode * eliminateDirectlyNestedFractions(const CEvaluationNode *pOrig)
CEvaluationNode * CNormalTranslation::eliminateNestedPowers ( const CEvaluationNode pOrig)
staticprotected

This method removes nested power nodes, e.g. (a^b)^c -> a^(b*c)

This method removes nested power nodes, e.g. (a^b)^c -> a^(b*c)

The caller is responsible for freeing the memory of the returned object.

Definition at line 2286 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), CEvaluationNode::copyNode(), CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::POWER, pResult, CCopasiNode< _Data >::removeChild(), CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by eliminate().

2287 {
2288  CEvaluationNode* pResult = NULL;
2289  std::vector<CEvaluationNode*> children;
2290  const CEvaluationNode* pTmpOrig = pOrig;
2291  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pTmpOrig->getChild());
2292  bool childrenChanged = false;
2293  CEvaluationNode* pNewChild = NULL;
2294 
2295  while (pChild != NULL)
2296  {
2297  pNewChild = CNormalTranslation::eliminateNestedPowers(pChild);
2298 
2299  if (pNewChild != NULL)
2300  {
2301  childrenChanged = true;
2302  }
2303 
2304  children.push_back(pNewChild);
2305  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
2306  }
2307 
2308  if (childrenChanged == true)
2309  {
2310  std::vector<CEvaluationNode*>::iterator it = children.begin(), endit = children.end();
2311  pChild = static_cast<const CEvaluationNode*>(pTmpOrig->getChild());
2312 
2313  while (it != endit)
2314  {
2315  if ((*it) == NULL)
2316  {
2317  (*it) = pChild->copyBranch();
2318  }
2319 
2320  pChild = static_cast<const CEvaluationNode*>(pChild->getSibling());
2321  ++it;
2322  }
2323 
2324  assert(pChild == NULL);
2325  pResult = pTmpOrig->copyNode(children);
2326  pTmpOrig = pResult;
2327  }
2328 
2331  {
2332  // check if the first child is also a power node
2333  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pTmpOrig->getChild());
2334  assert(pChild1 != NULL);
2335  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
2336  assert(pChild2 != NULL);
2337  assert(pChild2->getSibling() == NULL);
2338 
2341  {
2343  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pChild1->getChild());
2344  assert(pChild != NULL);
2345  pTmpNode->addChild(pChild->copyBranch());
2347  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
2348  assert(pChild != NULL);
2349  pMult->addChild(pChild->copyBranch());
2350 
2351  if (pResult == NULL)
2352  {
2353  pMult->addChild(pChild2->copyBranch());
2354  }
2355  else
2356  {
2357  assert(pResult == pTmpOrig);
2358  pResult->removeChild(const_cast<CEvaluationNode*>(pChild2));
2359  pMult->addChild(const_cast<CEvaluationNode*>(pChild2));
2360  delete pResult;
2361  }
2362 
2363  pTmpNode->addChild(pMult);
2364  pResult = pTmpNode;
2365  }
2366  }
2367 
2368  return pResult;
2369 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
const Type & getType() const
static CEvaluationNode * eliminateNestedPowers(const CEvaluationNode *pOrig)
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
const CArrayAnnotation * pResult
static Type subType(const Type &type)
virtual bool removeChild(CCopasiNode< Data > *pChild)
Definition: CCopasiNode.h:181
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * CNormalTranslation::eliminatePowersOfFractions ( const CEvaluationNode pOrig)
staticprotected

This method gets rid of fractions within a power construct. (a/b)^3 -> a^3 / b^3

This method replaces a power of a fraction by the fraction of two power nodes. (A/B)^x -> A^x / B^x

The caller is responsible for deleting the returned object.

Definition at line 5263 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), CEvaluationNode::copyNode(), CEvaluationNodeOperator::DIVIDE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::OPERATOR, CEvaluationNodeOperator::POWER, pResult, CCopasiNode< _Data >::removeChild(), CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by eliminate().

5264 {
5265  if (pOrig == NULL) return NULL;
5266 
5267  CEvaluationNode* pResult = NULL;
5268 
5269  std::vector<CEvaluationNode*> children;
5270  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pOrig->getChild());
5271  CEvaluationNode* pNewChild = NULL;
5272  const CEvaluationNode* pTmpOrig = pOrig;
5273  bool childrenChanged = false;
5274 
5275  while (pChild != NULL)
5276  {
5278 
5279  if (pNewChild != NULL)
5280  {
5281  childrenChanged = true;
5282  }
5283 
5284  children.push_back(pNewChild);
5285  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
5286  }
5287 
5288  if (childrenChanged == true)
5289  {
5290  pChild = dynamic_cast<const CEvaluationNode*>(pTmpOrig->getChild());
5291  std::vector<CEvaluationNode*>::iterator it = children.begin(), endit = children.end();
5292 
5293  while (it != endit)
5294  {
5295  if ((*it) == NULL)
5296  {
5297  (*it) = pChild->copyBranch();
5298  }
5299 
5300  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
5301  ++it;
5302  }
5303 
5304  assert(pChild == NULL);
5305  pResult = pTmpOrig->copyNode(children);
5306  pTmpOrig = pResult;
5307  }
5308 
5310  {
5311  const CEvaluationNode* pChild1 = static_cast<const CEvaluationNode*>(pTmpOrig->getChild());
5312  assert(pChild1 != NULL);
5313  const CEvaluationNode* pChild2 = static_cast<const CEvaluationNode*>(pChild1->getSibling());
5314  assert(pChild2 != NULL);
5315  assert(pChild2->getSibling() == NULL);
5316 
5318  {
5319  // the first child is a division
5320 
5323  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild1->getChild())->copyBranch());
5324  pTmp->addChild(pChild2->copyBranch());
5325  pTmpResult->addChild(pTmp);
5327  pTmp->addChild(dynamic_cast<const CEvaluationNode*>(pChild1->getChild()->getSibling())->copyBranch());
5328 
5329  if (pResult == NULL)
5330  {
5331  pTmp->addChild(pChild2->copyBranch());
5332  }
5333  else
5334  {
5335  // since pResult is a new object, we can safely modify it
5336  pResult->removeChild(const_cast<CEvaluationNode*>(pChild2));
5337  pTmp->addChild(const_cast<CEvaluationNode*>(pChild2));
5338  delete pResult;
5339  }
5340 
5341  pTmpResult->addChild(pTmp);
5342  pResult = pTmpResult;
5343  }
5344  }
5345 
5346  return pResult;
5347 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
const Type & getType() const
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
const CArrayAnnotation * pResult
static Type subType(const Type &type)
static CEvaluationNode * eliminatePowersOfFractions(const CEvaluationNode *pOrig)
virtual bool removeChild(CCopasiNode< Data > *pChild)
Definition: CCopasiNode.h:181
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * CNormalTranslation::expandPowerBases ( const CEvaluationNode pRoot)
static

Given a root node, this method traverses the tree and expands products in power bases to multiplications of power items. It is the responsibility of the caller to delete the returned node.

Given a root node, this method traverses the tree and expands produtcs in power bases to multiplications of power items.

(A*B)^x -> A^x * B^x

It is the responsibility of the caller to delete the returned node if it is not NULL.

Definition at line 5444 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), CEvaluationNode::copyNode(), createChain(), CEvaluationNodeOperator::DIVIDE, factorize(), CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::PLUS, CEvaluationNodeOperator::POWER, pResult, CCopasiNode< _Data >::removeChild(), splitProduct(), splitSum(), CEvaluationNode::subType(), swapNegativeNumbers(), and CEvaluationNode::type().

Referenced by simplify().

5445 {
5446  CEvaluationNode* pResult = NULL;
5447  std::vector<CEvaluationNode*> children;
5448 
5449  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pRoot->getChild());
5450  CEvaluationNode* pNewChild = NULL;
5451  bool childrenChanged = false;
5452 
5453  while (pChild != NULL)
5454  {
5455  pNewChild = CNormalTranslation::expandPowerBases(pChild);
5456 
5457  if (pNewChild != NULL)
5458  {
5459  childrenChanged = true;
5460  }
5461 
5462  children.push_back(pNewChild);
5463  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
5464  }
5465 
5466  if (childrenChanged == true)
5467  {
5468  std::vector<CEvaluationNode*>::iterator it = children.begin(), endit = children.end();
5469  pChild = dynamic_cast<const CEvaluationNode*>(pRoot->getChild());
5470 
5471  while (it != endit)
5472  {
5473  if ((*it) == NULL)
5474  {
5475  (*it) = pChild->copyBranch();
5476  }
5477 
5478  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
5479  ++it;
5480  }
5481 
5482  assert(pChild == NULL);
5483  }
5484 
5485  pResult = pRoot->copyNode(children);
5486  pRoot = pResult;
5487 
5488 
5489  CEvaluationNode::Type type = pRoot->getType();
5490 
5492  {
5493  const CEvaluationNode* pBase = dynamic_cast<const CEvaluationNode*>(pRoot->getChild());
5494  assert(pBase != NULL);
5495  const CEvaluationNode* pExp = dynamic_cast<const CEvaluationNode*>(pBase->getSibling());
5496  assert(pExp != NULL);
5497  type = pBase->getType();
5498 
5500  {
5501  std::vector<const CEvaluationNode*> multiplications, divisions;
5502  std::vector<CEvaluationNode*> numeratorNodes, denominatorNodes;
5503  CNormalTranslation::splitProduct(pBase, multiplications, divisions, false);
5504 
5505  std::vector<const CEvaluationNode*>::const_iterator it = multiplications.begin(), endit = multiplications.end();
5506  CEvaluationNode* pPower = NULL;
5507 
5508  while (it != endit)
5509  {
5511 
5512  if (pResult == NULL)
5513  {
5514  pPower->addChild((*it)->copyBranch());
5515  }
5516  else
5517  {
5518  // since pResult is a new node and not the original,
5519  // we can safely modify it instead of copying a whole branch
5520  if ((*it)->getParent() != NULL)
5521  {
5522  const_cast<CEvaluationNode*>((*it))->getParent()->removeChild(const_cast<CEvaluationNode*>(*it));
5523  }
5524 
5525  pPower->addChild(const_cast<CEvaluationNode*>(*it));
5526  }
5527 
5528  pPower->addChild(pExp->copyBranch());
5529  numeratorNodes.push_back(pPower);
5530  ++it;
5531  }
5532 
5534  assert(pTmp != NULL);
5535 
5536  if (!divisions.empty())
5537  {
5538  it = divisions.begin(), endit = divisions.end();
5539 
5540  while (it != endit)
5541  {
5543 
5544  if (pResult == NULL)
5545  {
5546  pPower->addChild((*it)->copyBranch());
5547  }
5548  else
5549  {
5550  // since pResult is a new node and not the original,
5551  // we can safely modify it instead of copying a whole branch
5552  if ((*it)->getParent() != NULL)
5553  {
5554  const_cast<CEvaluationNode*>((*it))->getParent()->removeChild(const_cast<CEvaluationNode*>(*it));
5555  }
5556 
5557  pPower->addChild(const_cast<CEvaluationNode*>(*it));
5558  }
5559 
5560  pPower->addChild(pExp->copyBranch());
5561  denominatorNodes.push_back(pPower);
5562  ++it;
5563  }
5564 
5566  pTmpResult->addChild(pTmp);
5568  assert(pTmp != NULL);
5569  pTmpResult->addChild(pTmp);
5570  pTmp = pTmpResult;
5571  }
5572 
5573  if (pResult != NULL)
5574  {
5575  delete pResult;
5576  }
5577 
5578  pResult = pTmp;
5579  }
5581  {
5582  std::vector<CEvaluationNode*> additions, subtractions;
5583  CNormalTranslation::splitSum(pBase, additions, subtractions, false);
5584  CNormalTranslation::swapNegativeNumbers(additions, subtractions);
5585  std::pair<CEvaluationNode*, CEvaluationNode*> resultPair = CNormalTranslation::factorize(additions, subtractions);
5586  unsigned int i, iMax = additions.size();
5587 
5588  for (i = 0; i < iMax; ++i)
5589  {
5590  delete additions[i];
5591  }
5592 
5593  additions.clear();
5594  iMax = subtractions.size();
5595 
5596  for (i = 0; i < iMax; ++i)
5597  {
5598  delete subtractions[i];
5599  }
5600 
5601  subtractions.clear();
5602 
5603  if (resultPair.first != NULL)
5604  {
5607  pTmpNode->addChild(resultPair.first);
5608  pTmpNode->addChild(pExp->copyBranch());
5609  pTmp->addChild(pTmpNode);
5611  pTmpNode->addChild(resultPair.second);
5612  pTmpNode->addChild(pExp->copyBranch());
5613  pTmp->addChild(pTmpNode);
5614 
5615  if (pResult != NULL)
5616  {
5617  delete pResult;
5618  }
5619 
5620  pResult = pTmp;
5621  }
5622  }
5623  }
5624 
5625  return pResult;
5626 }
static void splitSum(const CEvaluationNode *pRoot, std::vector< CEvaluationNode * > &additions, std::vector< CEvaluationNode * > &substractions, bool minus)
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
static std::pair< CEvaluationNode *, CEvaluationNode * > factorize(const std::vector< CEvaluationNode * > &additions, const std::vector< CEvaluationNode * > &subtractions)
static void swapNegativeNumbers(std::vector< CEvaluationNode * > &v1, std::vector< CEvaluationNode * > &v2)
const Type & getType() const
static CEvaluationNode * expandPowerBases(const CEvaluationNode *pRoot)
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static const CEvaluationNode ONE_NODE
static void splitProduct(const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &multiplications, std::vector< const CEvaluationNode * > &divisions, bool division)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
static const CEvaluationNode TIMES_NODE
virtual bool removeChild(CCopasiNode< Data > *pChild)
Definition: CCopasiNode.h:181
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * CNormalTranslation::expandPowerExponents ( const CEvaluationNode pRoot)
static

Given a root node, this method traverses the tree and expands sums in power exponents to multiplications of power items. It is the responsibility of the caller to delete the returned node.

Takes a node and expands expressions like x^(n+m) to x^n * x^m If some of the exponent summands are negative numbers, the expression is divided by the positive exponent expression (x^(n-5) -> x^n / x^5

Definition at line 197 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::create(), createChain(), CEvaluationNodeOperator::DIVIDE, CEvaluationNodeNumber::DOUBLE, findSummands(), CEvaluationNode::FUNCTION, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getData(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeFunction::MINUS, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::POWER, pResult, CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by normAndSimplify().

198 {
199  CEvaluationNode* pResult = NULL;
200  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pRoot->getChild());
201  std::vector<CEvaluationNode*> children;
202 
203  // go through this depth first and expand the power exponents in children
204  while (pChild != NULL)
205  {
207  children.push_back(pNewChild);
208  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
209  }
210 
212  {
213  assert(children.size() == 2);
214  std::vector<const CEvaluationNode*> summands;
215  CNormalTranslation::findSummands(children[1], summands);
216  // for each summand create a power node with a copy of the first child
217  // in children as child 1 and a copy of the summand as child 2
218  std::vector<CEvaluationNode*> numeratorNodes;
219  std::vector<CEvaluationNode*> denominatorNodes;
220  std::vector<const CEvaluationNode*>::iterator it = summands.begin(), endit = summands.end();
221 
222  while (it != endit)
223  {
225  pPowerNode->addChild(children[0]->copyBranch());
226 
228  {
229  pPowerNode->addChild(dynamic_cast<const CEvaluationNode*>((*it)->getChild())->copyBranch());
230  denominatorNodes.push_back(pPowerNode);
231  }
232  else if ((CEvaluationNode::type((*it)->getType()) == CEvaluationNode::NUMBER && dynamic_cast<const CEvaluationNodeNumber*>((*it))->getValue() < 0.0))
233  {
234  std::ostringstream os;
235  os.precision(18);
236  os << fabs(dynamic_cast<const CEvaluationNodeNumber*>(*it)->getValue());
237  pPowerNode->addChild(new CEvaluationNodeNumber((CEvaluationNodeNumber::SubType)CEvaluationNode::subType((*it)->getType()), os.str().c_str()));
238  denominatorNodes.push_back(pPowerNode);
239  }
240  else
241  {
242  pPowerNode->addChild((*it)->copyBranch());
243  numeratorNodes.push_back(pPowerNode);
244  }
245 
246  ++it;
247  }
248 
249  delete children[0];
250  delete children[1];
251 
252  // create the numerator chain
253  if (numeratorNodes.empty())
254  {
256  }
257  else
258  {
260  }
261 
262  assert(pResult != NULL);
263 
264  // if there are items in the denominator vector create the denominator
265  // chain and divide the numerator chain by the denominator chain
266  if (!denominatorNodes.empty())
267  {
269  pDivision->addChild(pResult);
271  pResult = pDivision;
272  }
273  }
274  else
275  {
276  // copy the node and add the children
277  pResult = CEvaluationNode::create(pRoot->getType(), pRoot->getData());
278  std::vector<CEvaluationNode*>::iterator it = children.begin(), endit = children.end();
279 
280  while (it != endit)
281  {
282  pResult->addChild(*it);
283  ++it;
284  }
285  }
286 
287  return pResult;
288 }
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static CEvaluationNode * create(const Type &type, const Data &data)
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static const CEvaluationNode ONE_NODE
const CArrayAnnotation * pResult
static Type subType(const Type &type)
static const CEvaluationNode TIMES_NODE
virtual const Data & getData() const
Definition: CCopasiNode.h:118
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static void findSummands(const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &summands)
static CEvaluationNode * expandPowerExponents(const CEvaluationNode *pRoot)
CEvaluationNode * CNormalTranslation::expandPowerNodes ( const CEvaluationNode pOrig)
staticprotected

This method expands the exponents of power nodes, e.g. A^(x+y) -> A^x * A^y

This method expands the exponents of power nodes, e.g. A^(x+y) -> A^x * A^y

The caller is responsible for freeing the memory of the returned object if it is not NULL.

Definition at line 2766 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), CEvaluationNode::copyNode(), createChain(), CEvaluationNodeOperator::DIVIDE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::POWER, pResult, splitSum(), CEvaluationNode::subType(), swapNegativeNumbers(), and CEvaluationNode::type().

Referenced by simplify().

2767 {
2768  CEvaluationNode* pResult = NULL;
2769  std::vector<CEvaluationNode*> children;
2770  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pOrig->getChild());
2771  CEvaluationNode* pNewChild = NULL;
2772  const CEvaluationNode* pTmpOrig = pOrig;
2773  bool childrenChanged = false;
2774 
2775  while (pChild != NULL)
2776  {
2777  pNewChild = CNormalTranslation::expandPowerNodes(pChild);
2778 
2779  if (pNewChild != NULL)
2780  {
2781  childrenChanged = true;
2782  }
2783 
2784  children.push_back(pNewChild);
2785  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
2786  }
2787 
2788  if (childrenChanged == true)
2789  {
2790  pChild = dynamic_cast<const CEvaluationNode*>(pTmpOrig->getChild());
2791  std::vector<CEvaluationNode*>::iterator it = children.begin(), endit = children.end();
2792 
2793  while (it != endit)
2794  {
2795  if ((*it) == NULL)
2796  {
2797  (*it) = pChild->copyBranch();
2798  }
2799 
2800  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
2801  ++it;
2802  }
2803 
2804  pResult = pTmpOrig->copyNode(children);
2805  pTmpOrig = pResult;
2806  }
2807 
2808 
2811  {
2812  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pTmpOrig->getChild());
2813  assert(pChild1 != NULL);
2814  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
2815  assert(pChild2 != NULL);
2816  assert(pChild2->getSibling() == NULL);
2817 
2818  std::vector<CEvaluationNode*> additions, subtractions;
2819  CNormalTranslation::splitSum(pChild2, additions, subtractions, false);
2820  CNormalTranslation::swapNegativeNumbers(additions, subtractions);
2821 
2822  // the root node is a fraction
2823  // the denominator is a product of all subtraction nodes
2824  // the numerator is a product of all addition nodes
2825  if (!additions.empty() || !subtractions.empty())
2826  {
2827  // replace all nodes in additions and subtractions by
2828  // pChild1^node so we can use the generic method to create the
2829  // multiplication chain
2830  unsigned int i, iMax = additions.size();
2831 
2832  for (i = 0; i < iMax; ++i)
2833  {
2834  CEvaluationNode* pTmpNode = NULL;
2835 
2836  if (CEvaluationNode::type(additions[i]->getType()) == CEvaluationNode::NUMBER && fabs(static_cast<const CEvaluationNodeNumber*>(additions[i])->getValue() - 1.0) < 1e-12)
2837  {
2838  delete additions[i];
2839  pTmpNode = pChild1->copyBranch();
2840  }
2841  else
2842  {
2844  pTmpNode->addChild(pChild1->copyBranch());
2845  // don't copy additions element since this has been created in
2846  // splitSum
2847  pTmpNode->addChild(additions[i]);
2848  additions[i] = pTmpNode;
2849  }
2850 
2851  additions[i] = pTmpNode;
2852  }
2853 
2854  iMax = subtractions.size();
2855 
2856  for (i = 0; i < iMax; ++i)
2857  {
2858  CEvaluationNode* pTmpNode = NULL;
2859 
2860  if (CEvaluationNode::type(subtractions[i]->getType()) == CEvaluationNode::NUMBER && fabs(static_cast<const CEvaluationNodeNumber*>(subtractions[i])->getValue() - 1.0) < 1e-12)
2861  {
2862  pTmpNode = pChild1->copyBranch();
2863  delete subtractions[i];
2864  }
2865  else
2866  {
2868  pTmpNode->addChild(pChild1->copyBranch());
2869  // don't copy subtractions element since this has been created in
2870  // splitSum
2871  pTmpNode->addChild(subtractions[i]);
2872  }
2873 
2874  subtractions[i] = pTmpNode;
2875  }
2876 
2877  // if we have only subtractions, the numerator of the resulting
2878  // exponent has to be 1
2879  CEvaluationNode* pTmpResult = NULL;
2880 
2881  if (additions.empty())
2882  {
2884  }
2885  else
2886  {
2888  additions.clear();
2889  }
2890 
2891  assert(pTmpResult != NULL);
2892 
2893  if (!subtractions.empty())
2894  {
2896  pTmpNode->addChild(pTmpResult);
2897  pTmpResult = pTmpNode;
2899  assert(pTmpNode != NULL);
2900  pTmpResult->addChild(pTmpNode);
2901  subtractions.clear();
2902  }
2903 
2904  if (pResult != NULL)
2905  {
2906  delete pResult;
2907  }
2908 
2909  pResult = pTmpResult;
2910  }
2911  }
2912 
2913  return pResult;
2914 }
static void splitSum(const CEvaluationNode *pRoot, std::vector< CEvaluationNode * > &additions, std::vector< CEvaluationNode * > &substractions, bool minus)
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
static void swapNegativeNumbers(std::vector< CEvaluationNode * > &v1, std::vector< CEvaluationNode * > &v2)
const Type & getType() const
static CEvaluationNode * expandPowerNodes(const CEvaluationNode *pOrig)
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static const CEvaluationNode ONE_NODE
const CArrayAnnotation * pResult
static Type subType(const Type &type)
static const CEvaluationNode TIMES_NODE
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * CNormalTranslation::expandProducts ( const CEvaluationNode pOrig)
static

This method expands products. (A+B)*(C+D) -> (A*C)+(A*D)+(B*C)+(B*D) This method should be replaced by the one below pretty soon.

This method expands products. (A+B)*(C+D) -> (A*C)+(A*D)+(B*C)+(B*D)

Definition at line 3835 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyNode(), CEvaluationNodeOperator::DIVIDE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MULTIPLY, multiply(), CEvaluationNode::OPERATOR, pResult, splitProduct(), CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by createNormalRepresentation(), and simplify().

3836 {
3837  CEvaluationNode* pResult = NULL;
3838 
3839  // we have to create operation chains and do the multiplication
3840  // on the numerator and the denominator chain if the node is a multiplication
3841  // or a division
3843  {
3844  std::vector<const CEvaluationNode*> multiplications, divisions;
3845  CNormalTranslation::splitProduct(pOrig, multiplications, divisions, false);
3846  unsigned int i, iMax = multiplications.size();
3847  CEvaluationNode* pTmpResult;
3848 
3849  for (i = 0; i < iMax; ++i)
3850  {
3851  if (pResult == NULL)
3852  {
3853  pResult = CNormalTranslation::expandProducts(multiplications[i]);
3854  }
3855  else
3856  {
3857  CEvaluationNode* pTmpNode = CNormalTranslation::expandProducts(multiplications[i]);
3858  pTmpResult = CNormalTranslation::multiply(pResult, pTmpNode);
3859  delete pResult;
3860  delete pTmpNode;
3861  pResult = pTmpResult;
3862  }
3863  }
3864 
3865  if (!divisions.empty())
3866  {
3867  CEvaluationNode* pDenominator = NULL;
3868  iMax = divisions.size();
3869 
3870  for (i = 0; i < iMax; ++i)
3871  {
3872  if (pDenominator == NULL)
3873  {
3874  pDenominator = CNormalTranslation::expandProducts(divisions[i]);
3875  }
3876  else
3877  {
3878  CEvaluationNode* pTmpNode = CNormalTranslation::expandProducts(divisions[i]);
3879  pTmpResult = CNormalTranslation::multiply(pDenominator, pTmpNode);
3880  delete pDenominator;
3881  delete pTmpNode;
3882  pDenominator = pTmpResult;
3883  }
3884 
3885  //delete divisions[i];
3886  }
3887 
3889  pTmpResult->addChild(pResult);
3890  pTmpResult->addChild(pDenominator);
3891  pResult = pTmpResult;
3892  }
3893  }
3894  else
3895  {
3896  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pOrig->getChild());
3897  std::vector<CEvaluationNode*> children;
3898 
3899  while (pChild != NULL)
3900  {
3901  children.push_back(CNormalTranslation::expandProducts(pChild));
3902  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
3903  }
3904 
3907  {
3908  assert(children.size() == 2);
3909  pResult = CNormalTranslation::multiply(children[0], children[1]);
3910  // delete the children
3911  delete children[0];
3912  delete children[1];
3913  }
3914 
3915  if (pResult == NULL)
3916  {
3917  pResult = pOrig->copyNode(children);
3918  }
3919  }
3920 
3921  return pResult;
3922 }
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
const Type & getType() const
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static void splitProduct(const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &multiplications, std::vector< const CEvaluationNode * > &divisions, bool division)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
static CEvaluationNode * multiply(const CEvaluationNode *pNode1, const CEvaluationNode *pNode2)
static CEvaluationNode * expandProducts(const CEvaluationNode *pOrig)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
std::pair< CEvaluationNode *, CEvaluationNode * > CNormalTranslation::factorize ( const std::vector< CEvaluationNode * > &  additions,
const std::vector< CEvaluationNode * > &  subtractions 
)
staticprotected

This method takes two vectors. One with a list of nodes that are added and one with nodes that are subtracted. It tries to find common factors and divisors in those nodes and returns two result nodes. The first is the multiplication of all common factors and divisors, the other is the sum of the remaining additions and subtractions after removing the common factors and divisors. e.g. (A*B*D+A*C*D) -> returns (A*D) and (B+C)

This method takes two vectors and checks if the elements in the two vectors can be split into multiplications and divisions and if there a common factors in all resulting subgroups.

Definition at line 5632 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), createChain(), createOperatorChain(), CEvaluationNodeOperator::DIVIDE, CEvaluationNode::getType(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::OPERATOR, splitProduct(), CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by expandPowerBases().

5633 {
5634  std::vector<const CEvaluationNode*> commonMultiplications;
5635  std::vector<const CEvaluationNode*> commonDivisions;
5636  // additions must have at least one entry
5637  assert(additions.size() > 0);
5638  // get all multipllications and divisions from the first entry in additions
5639  std::vector<const CEvaluationNode*> multiplications, divisions;
5640  unsigned int i, iMax = additions.size();
5641  unsigned int iiMax = iMax + subtractions.size();
5642  std::vector<std::vector<const CEvaluationNode*> > multiplicationVectors, divisionVectors;
5643 
5644  for (i = 0; i < iiMax; ++i)
5645  {
5646  const CEvaluationNode* pTmpNode = (i < iMax) ? additions[i] : subtractions[i - iMax];
5647  CEvaluationNode::Type type = pTmpNode->getType();
5648 
5650  {
5652 
5654  {
5655  CNormalTranslation::splitProduct(pTmpNode, multiplications, divisions, false);
5656  }
5657  else
5658  {
5659  multiplications.push_back(pTmpNode);
5660  }
5661  }
5662  else
5663  {
5664  multiplications.push_back(pTmpNode);
5665  }
5666 
5667  multiplicationVectors.push_back(multiplications);
5668  divisionVectors.push_back(divisions);
5669  multiplications.clear();
5670  divisions.clear();
5671  }
5672 
5673  // now we first search for common multiplications
5674  multiplications = multiplicationVectors[0];
5675  std::vector<const CEvaluationNode*>::const_iterator it = multiplications.begin(), endit = multiplications.end();
5676 
5677  while (it != endit)
5678  {
5679  bool everywhere = true;
5680  std::vector<std::vector<const CEvaluationNode*> >::iterator innerIt = multiplicationVectors.begin(), innerEndit = multiplicationVectors.end();
5681  // we can leave out the first one since the item comes from there anyway,
5682  // so we know it is in that vector
5683  std::string infix = (*it)->buildInfix();
5684  ++innerIt;
5685 
5686  while (innerIt != innerEndit)
5687  {
5688  bool found = false;
5689  std::vector<const CEvaluationNode*>::iterator innerIt2 = (*innerIt).begin(), innerEndit2 = (*innerIt).end();
5690 
5691  while (innerIt2 != innerEndit2)
5692  {
5693  if ((*innerIt2)->buildInfix() == infix)
5694  {
5695  found = true;
5696  break;
5697  }
5698 
5699  ++innerIt2;
5700  }
5701 
5702  if (!found)
5703  {
5704  everywhere = false;
5705  break;
5706  }
5707 
5708  ++innerIt;
5709  }
5710 
5711  // if the item was found as a factor in all other additions and
5712  // subtractions, we know it is a common factor, we add it to the
5713  // commonFactors and update the additions and subtractions
5714  if (everywhere)
5715  {
5716  commonMultiplications.push_back(*it);
5717  std::vector<std::vector<const CEvaluationNode*> >::iterator innerIt = multiplicationVectors.begin();
5718  std::vector<std::vector<const CEvaluationNode*> >::iterator innerEndit = multiplicationVectors.end();
5719 
5720  while (innerIt != innerEndit)
5721  {
5722  std::vector<const CEvaluationNode*>::iterator innerIt2 = (*innerIt).begin();
5723  std::vector<const CEvaluationNode*>::iterator innerEndit2 = (*innerIt).end();
5724 
5725  while (innerIt2 != innerEndit2)
5726  {
5727  if ((*innerIt2)->buildInfix() == infix)
5728  {
5729  innerIt->erase(innerIt2);
5730  break;
5731  }
5732 
5733  ++innerIt2;
5734  }
5735 
5736  ++innerIt;
5737  }
5738  }
5739 
5740  ++it;
5741  }
5742 
5743  // now we search for common divisions
5744  divisions = divisionVectors[0];
5745 
5746  if (!divisions.empty())
5747  {
5748  it = divisions.begin(), endit = divisions.end();
5749 
5750  while (it != endit)
5751  {
5752  bool everywhere = true;
5753  std::vector<std::vector<const CEvaluationNode*> >::iterator innerIt = divisionVectors.begin(), innerEndit = divisionVectors.end();
5754  // we can leav out the first one since the item comes from there anyway,
5755  // so we know it is in that vector
5756  std::string infix = (*it)->buildInfix();
5757  ++innerIt;
5758 
5759  while (innerIt != innerEndit)
5760  {
5761  bool found = false;
5762  std::vector<const CEvaluationNode*>::iterator innerIt2 = (*innerIt).begin(), innerEndit2 = (*innerIt).end();
5763 
5764  while (innerIt2 != innerEndit2)
5765  {
5766  if ((*innerIt2)->buildInfix() == infix)
5767  {
5768  found = true;
5769  break;
5770  }
5771 
5772  ++innerIt2;
5773  }
5774 
5775  if (!found)
5776  {
5777  everywhere = false;
5778  break;
5779  }
5780 
5781  ++innerIt;
5782  }
5783 
5784  // if the item was found as a factor in all other additions and
5785  // subtractions, we know it is a common factor, we add it to the
5786  // commonFactors and update the additions and subtractions
5787  if (everywhere)
5788  {
5789  commonDivisions.push_back(*it);
5790  innerIt = divisionVectors.begin();
5791  innerEndit = divisionVectors.end();
5792 
5793  while (innerIt != innerEndit)
5794  {
5795  std::vector<const CEvaluationNode*>::iterator innerIt2 = (*innerIt).begin();
5796  std::vector<const CEvaluationNode*>::iterator innerEndit2 = (*innerIt).end();
5797 
5798  while (innerIt2 != innerEndit2)
5799  {
5800  if ((*innerIt2)->buildInfix() == infix)
5801  {
5802  innerIt->erase(innerIt2);
5803  break;
5804  }
5805 
5806  ++innerIt2;
5807  }
5808 
5809  ++innerIt;
5810  }
5811  }
5812 
5813  ++it;
5814  }
5815  }
5816 
5817  // create the two resulting nodes
5818  // first we have to create new additions and subtraction vectors which we
5819  // then combine into a subtraction
5820  // then we combine all commonMultiplications and commonDivisions into a
5821  // division
5822  // those two nodes are then returned in a pair
5823  CEvaluationNode* pFirstNode = NULL;
5824  CEvaluationNode* pSecondNode = NULL;
5825 
5826  if (!(commonMultiplications.empty() && commonDivisions.empty()))
5827  {
5828  unsigned int i, iMax = additions.size();
5829  unsigned int iiMax = iMax + subtractions.size();
5830  std::vector<CEvaluationNode*> newAdditions, newSubtractions;
5831 
5832  for (i = 0; i < iiMax; ++i)
5833  {
5834  // since the createOperatorChain automatically returns 1 as the result
5835  // if an empty vector is given, we don't have to worry about havinf
5836  // removed all items from the vectors above.
5838 
5839  if (!divisionVectors[i].empty())
5840  {
5842  pTmpNode2->addChild(pTmpNode);
5844  pTmpNode = pTmpNode2;
5845  }
5846 
5847  if (i < iMax)
5848  {
5849  newAdditions.push_back(pTmpNode);
5850  }
5851  else
5852  {
5853  newSubtractions.push_back(pTmpNode);
5854  }
5855  }
5856 
5858  assert(pSecondNode != NULL);
5859 
5860  if (!newSubtractions.empty())
5861  {
5863  pTmpNode->addChild(pSecondNode);
5865  assert(pTmpNode != NULL);
5866  pSecondNode = pTmpNode;
5867  }
5868 
5869  pFirstNode = CNormalTranslation::createOperatorChain(CEvaluationNodeOperator::MULTIPLY, "*", commonMultiplications);
5870 
5871  if (!commonDivisions.empty())
5872  {
5874  pTmpNode->addChild(pFirstNode);
5876  pFirstNode = pTmpNode;
5877  }
5878  }
5879 
5880  return std::pair<CEvaluationNode*, CEvaluationNode*>(pFirstNode, pSecondNode);
5881 }
const Type & getType() const
static Type type(const Type &type)
static CEvaluationNode * createOperatorChain(CEvaluationNodeOperator::SubType type, const char *data, const std::vector< CEvaluationNode * > &nodes)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static const CEvaluationNode ZERO_NODE
static void splitProduct(const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &multiplications, std::vector< const CEvaluationNode * > &divisions, bool division)
static Type subType(const Type &type)
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
static const CEvaluationNode PLUS_NODE
void CNormalTranslation::findNegativeNumbers ( std::vector< const CEvaluationNode * > &  v1,
std::vector< CEvaluationNode * > &  v2 
)
staticprotected

This routine finds all negative numbers in vector v1 and adds a copy with a positive number to v2

Definition at line 6216 of file CNormalTranslation.cpp.

References CEvaluationNode::copyBranch(), CEvaluationNode::copyNode(), CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::getValue(), CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by newCancel().

6217 {
6218  const CEvaluationNode* pNode;
6219  CEvaluationNode::Type type, type1, type2;
6220  std::vector<const CEvaluationNode*>::iterator it = v1.begin(), endit = v1.end();
6221  std::ostringstream os;
6222 
6223  while (it != endit)
6224  {
6225  pNode = *it;
6226  type = pNode->getType();
6227 
6228  if (CEvaluationNode::type(type) == CEvaluationNode::NUMBER && pNode->getValue() < 0.0)
6229  {
6230  it = v1.erase(it);
6231  endit = v1.end();
6232  os.str("");
6233  os.precision(18);
6234  os << pNode->getValue() * -1.0;
6235  v2.push_back(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str()));
6236  continue;
6237  }
6239  {
6240  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pNode->getChild());
6241  assert(pChild1 != NULL);
6242  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
6243  assert(pChild2 != NULL);
6244  type1 = CEvaluationNode::type(pChild1->getType());
6245  type2 = CEvaluationNode::type(pChild2->getType());
6246 
6247  if (type1 == CEvaluationNode::NUMBER || type2 == CEvaluationNode::NUMBER)
6248  {
6249  if (type1 == CEvaluationNode::NUMBER && type2 == CEvaluationNode::NUMBER)
6250  {
6251  if (pChild1->getValue() < 0.0 && pChild2->getValue() < 0.0)
6252  {
6253  // we should never end up here because
6254  // elementaryElimination should take care of this case
6255  assert(false);
6256  continue;
6257  }
6258  else if (pChild1->getValue() < 0.0)
6259  {
6260  os.str("");
6261  os.precision(18);
6262  os << pChild1->getValue() * -1.0;
6264  std::vector<CEvaluationNode*> children;
6265  children.push_back(pTmpNode);
6266  children.push_back(pChild2->copyBranch());
6267  CEvaluationNode* pNewNode = pNode->copyNode(children);
6268  v2.push_back(pNewNode);
6269  it = v1.erase(it);
6270  endit = v1.end();
6271  continue;
6272  }
6273  else if (pChild2->getValue() < 0.0)
6274  {
6275  os.str("");
6276  os.precision(18);
6277  os << pChild2->getValue() * -1.0;
6279  std::vector<CEvaluationNode*> children;
6280  children.push_back(pChild1->copyBranch());
6281  children.push_back(pTmpNode);
6282  CEvaluationNode* pNewNode = pNode->copyNode(children);
6283  v2.push_back(pNewNode);
6284  it = v1.erase(it);
6285  endit = v1.end();
6286  continue;
6287  }
6288  }
6289  else if (type1 == CEvaluationNode::NUMBER)
6290  {
6291  if (pChild1->getValue() < 0.0)
6292  {
6293  os.str("");
6294  os.precision(18);
6295  os << pChild1->getValue() * -1.0;
6297  std::vector<CEvaluationNode*> children;
6298  children.push_back(pTmpNode);
6299  children.push_back(pChild2->copyBranch());
6300  CEvaluationNode* pNewNode = pNode->copyNode(children);
6301  v2.push_back(pNewNode);
6302  it = v1.erase(it);
6303  endit = v1.end();
6304  continue;
6305  }
6306  }
6307  else
6308  {
6309  if (pChild2->getValue() < 0.0)
6310  {
6311  os.str("");
6312  os.precision(18);
6313  os << pChild2->getValue() * -1.0;
6315  std::vector<CEvaluationNode*> children;
6316  children.push_back(pChild1->copyBranch());
6317  children.push_back(pTmpNode);
6318  CEvaluationNode* pNewNode = pNode->copyNode(children);
6319  v2.push_back(pNewNode);
6320  it = v1.erase(it);
6321  endit = v1.end();
6322  continue;
6323  }
6324  }
6325  }
6326  }
6327 
6328  ++it;
6329  }
6330 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
const C_FLOAT64 & getValue() const
const Type & getType() const
static Type type(const Type &type)
static Type subType(const Type &type)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
void CNormalTranslation::findSummands ( const CEvaluationNode pRoot,
std::vector< const CEvaluationNode * > &  summands 
)
static

Given a node, the method check if the node is a PLUS node, if so, it calls itself recursively on the children. This way all summands of a summation chain are gathered. All items in the vector are children of pRoot.

This method takes a node and if the node is the node is an addition operator, the method goes through the children of the node and check for more addition operators. All children of addition operators are added to the given summands vector. If the given node is not an addition operator, the methods adds the node itself to the vector of summands. The nodes that are added to the vector are the original nodes and not copies.

Definition at line 347 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::OPERATOR, CEvaluationNodeOperator::PLUS, CEvaluationNode::subType(), and CEvaluationNode::type().

Referenced by expandPowerExponents().

348 {
350  {
351  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pRoot->getChild());
352  assert(pChild1 != NULL);
353 
354  if (pChild1 != NULL)
355  {
356  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
357  assert(pChild2 != NULL);
358 
359  if (pChild2 != NULL)
360  {
361  assert(pChild2->getSibling() == NULL);
362 
364  {
365  CNormalTranslation::findSummands(pChild1, summands);
366  }
367  else
368  {
369  summands.push_back(pChild1);
370  }
371 
373  {
374  CNormalTranslation::findSummands(pChild2, summands);
375  }
376  else
377  {
378  summands.push_back(pChild2);
379  }
380  }
381  }
382  }
383  else
384  {
385  summands.push_back(pRoot);
386  }
387 }
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
static Type type(const Type &type)
static Type subType(const Type &type)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
static void findSummands(const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &summands)
bool CNormalTranslation::has_duplicate_nodes ( const CEvaluationNode pNode)
static

Definition at line 6407 of file CNormalTranslation.cpp.

References CEvaluationNodeDepthFirstIterator::isValid().

6408 {
6409  bool result = false;
6410  CEvaluationNodeDepthFirstIterator it(const_cast<CEvaluationNode*>(pNode));
6411  std::set<const CEvaluationNode*> s;
6412 
6413  while (it.isValid())
6414  {
6415  if (s.find(*it) == s.end())
6416  {
6417  s.insert(*it);
6418  }
6419  else
6420  {
6421  result = true;
6422  break;
6423  }
6424 
6425  ++it;
6426  }
6427 
6428  return result;
6429 }
std::vector< product_match > CNormalTranslation::matchPowerBases ( const std::vector< const CEvaluationNode * > &  multiplications,
const std::vector< const CEvaluationNode * > &  divisions 
)
staticprotected

The methods get a vector of multiplication elements and a vector of division elements and tries to find elements with the same power base in those two vectors.

The methods get a vector of multiplication elements and a vector of division elements and tries to find elements with the same power base in those two vectors. e.g. A^3 and A^x would have the same power base A.

The nodes in the match are copies of the original nodes

Definition at line 2923 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), summ_match::addition_indices, CEvaluationNode::buildInfix(), CEvaluationNode::copyBranch(), createNormalRepresentation(), CEvaluationNodeNumber::DOUBLE, summ_match::factor, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::getValue(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, newEvaluateNumbers(), CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, product_match::pExponentNode, CEvaluationNodeOperator::PLUS, summ_match::pNode, CEvaluationNodeOperator::POWER, summ_match::subtraction_indices, CEvaluationNode::subType(), CNormalFraction::toString(), and CEvaluationNode::type().

Referenced by newCancel().

2924 {
2925  std::map<const CEvaluationNode*, product_match> matchMap;
2926  std::map<std::string, const CEvaluationNode*> infixMap;
2927  std::map<const CEvaluationNode*, product_match>::iterator matchPos;
2928  std::map<std::string, const CEvaluationNode*>::iterator infixPos;
2929 
2930  std::vector<const CEvaluationNode*>::const_iterator vit = multiplications.begin(), vendit = multiplications.end();
2931  const CEvaluationNode* pBase = NULL;
2932  const CNormalFraction* pBase2 = NULL;
2933  std::string base2String;
2934  CEvaluationNode *pExponent = NULL, *pAddNode = NULL;
2935  unsigned int index = 0;
2936  product_match match;
2937  // we store the order in which the base strings occur
2938  // so that we can return the result in approximately the same order
2939  // this should help in eliminating loops of chains with alternating order
2940  std::list<const CEvaluationNode*> orderList;
2941 
2942  while (vit != vendit)
2943  {
2944  pBase = (*vit);
2945  pExponent = NULL;
2946 
2948  {
2949  pBase = dynamic_cast<const CEvaluationNode*>(pBase->getChild());
2950  pExponent = dynamic_cast<const CEvaluationNode*>(pBase->getSibling())->copyBranch();
2951  }
2952 
2953  // check if a base with the same infix is already in the map.
2954  // if not, add the base
2955  // if yes, add the exponent to the vector associated with the base
2956  //
2957  // we only need to create the infix through a normal base if the
2958  // object is complex
2959  if (pBase->getChild() != NULL)
2960  {
2961  pBase2 = createNormalRepresentation(pBase);
2962  base2String = pBase2->toString();
2963  delete pBase2;
2964  pBase2 = NULL;
2965  }
2966  else
2967  {
2968  base2String = pBase->buildInfix();
2969  }
2970 
2971  infixPos = infixMap.find(base2String);
2972 
2973  if (infixPos != infixMap.end())
2974  {
2975  matchPos = matchMap.find(infixPos->second);
2976  assert(matchPos != matchMap.end());
2977 
2978  if (matchPos != matchMap.end())
2979  {
2980  if (pExponent != NULL)
2981  {
2982  if (matchPos->second.pExponentNode != NULL)
2983  {
2985  pAddNode->addChild(matchPos->second.pExponentNode);
2986  pAddNode->addChild(pExponent);
2987  matchPos->second.pExponentNode = pAddNode;
2988  matchPos->second.addition_indices.insert(index);
2989  }
2990  else
2991  {
2992  matchPos->second.pExponentNode = pExponent;
2993  }
2994  }
2995  else
2996  {
2997  matchPos->second.factor += 1.0;
2998  }
2999  }
3000  }
3001  else
3002  {
3003  match.pNode = pBase->copyBranch();
3004 
3005  if (pExponent == NULL)
3006  {
3007  match.factor = 1.0;
3008  }
3009  else
3010  {
3011  match.factor = 0.0;
3012  }
3013 
3014  match.pExponentNode = pExponent;
3015  match.addition_indices.clear();
3016  match.addition_indices.insert(index);
3017  match.subtraction_indices.clear();
3018  infixMap.insert(std::pair<std::string, const CEvaluationNode*>(base2String, pBase));
3019  matchMap.insert(std::pair<const CEvaluationNode*, product_match>(pBase, match));
3020  orderList.push_back(pBase);
3021  }
3022 
3023  ++index;
3024  ++vit;
3025  }
3026 
3027  vit = divisions.begin(), vendit = divisions.end();
3028 
3029  index = 0;
3030 
3031  while (vit != vendit)
3032  {
3033  pBase = (*vit);
3034  pExponent = NULL;
3035 
3037  {
3038  pBase = dynamic_cast<const CEvaluationNode*>(pBase->getChild());
3039  pExponent = dynamic_cast<const CEvaluationNode*>(pBase->getSibling())->copyBranch();
3040  }
3041  else
3042  {
3043  pExponent = NULL;
3044  }
3045 
3046  // check if a base with the same infix is already in the map.
3047  // if not, add the base
3048  // if yes, add the exponent to the vector associated with the base
3049  if (pBase->getChild() != NULL)
3050  {
3051  pBase2 = createNormalRepresentation(pBase);
3052  base2String = pBase2->toString();
3053  delete pBase2;
3054  pBase2 = NULL;
3055  }
3056  else
3057  {
3058  base2String = pBase->buildInfix();
3059  }
3060 
3061  infixPos = infixMap.find(base2String);
3062 
3063  if (infixPos != infixMap.end())
3064  {
3065  matchPos = matchMap.find(infixPos->second);
3066  assert(matchPos != matchMap.end());
3067 
3068  if (matchPos != matchMap.end())
3069  {
3070  if (pExponent != NULL)
3071  {
3072  if (matchPos->second.pExponentNode != NULL)
3073  {
3075  pAddNode->addChild(matchPos->second.pExponentNode);
3076  pAddNode->addChild(pExponent);
3077  matchPos->second.pExponentNode = pAddNode;
3078  matchPos->second.subtraction_indices.insert(index);
3079  }
3080  else
3081  {
3082  // we have to add -1 * pExponent
3084  pAddNode->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "-1.0"));
3085  pAddNode->addChild(pExponent);
3086  matchPos->second.pExponentNode = pAddNode;
3087  }
3088  }
3089  else
3090  {
3091  // subtract one from the factor
3092  matchPos->second.factor -= 1.0;
3093  }
3094  }
3095  }
3096  else
3097  {
3098  match.pNode = pBase->copyBranch();
3099 
3100  if (pExponent == NULL)
3101  {
3102  match.factor = -1.0;
3103  match.pExponentNode = NULL;
3104  }
3105  else
3106  {
3107  // we have to add -1 * pExponent
3108  match.factor = 0.0;
3110  pAddNode->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "-1.0"));
3111  pAddNode->addChild(pExponent);
3112  match.pExponentNode = pAddNode;
3113  }
3114 
3115  match.addition_indices.clear();
3116  match.subtraction_indices.clear();
3117  match.subtraction_indices.insert(index);
3118  infixMap.insert(std::pair<std::string, const CEvaluationNode*>(base2String, pBase));
3119  matchMap.insert(std::pair<const CEvaluationNode*, product_match>(pBase, match));
3120  orderList.push_back(pBase);
3121  }
3122 
3123  ++index;
3124  ++vit;
3125  }
3126 
3127  // create the result vector
3128  std::vector<product_match> result;
3129  CEvaluationNode* pTmpNode = NULL;
3130  std::ostringstream os;
3131 
3132  std::list<const CEvaluationNode*>::const_iterator orderIt = orderList.begin(), orderEndit = orderList.end();
3133 
3134  while (orderIt != orderEndit)
3135  {
3136  matchPos = matchMap.find(*orderIt);
3137  assert(matchPos != matchMap.end());
3138 
3139  if (matchPos != matchMap.end())
3140  {
3141 
3142  // call newEvaluateNumbers on pExponentNode of each match
3143  if (matchPos->second.pExponentNode != NULL)
3144  {
3145  if (CEvaluationNode::type(matchPos->second.pExponentNode->getType()) == CEvaluationNode::NUMBER)
3146  {
3147  // add the numerical value to factor
3148  matchPos->second.factor += matchPos->second.pExponentNode->getValue();
3149  // and delete the exponent node
3150  delete matchPos->second.pExponentNode;
3151  matchPos->second.pExponentNode = NULL;
3152  }
3153  else
3154  {
3155  pTmpNode = CNormalTranslation::newEvaluateNumbers(matchPos->second.pExponentNode);
3156 
3157  if (pTmpNode != NULL)
3158  {
3160  {
3161  // add the numerical value to factor
3162  matchPos->second.factor += pTmpNode->getValue();
3163  // and delete the exponent node
3164  delete matchPos->second.pExponentNode;
3165  matchPos->second.pExponentNode = NULL;
3166  }
3167  else
3168  {
3169  // replace the exponent node
3170  delete matchPos->second.pExponentNode;
3171  matchPos->second.pExponentNode = pTmpNode;
3172  }
3173  }
3174  else
3175  {
3176  // add the factor to the exponent node
3177  // and set the factor to 0.0
3178  if (matchPos->second.factor != 0.0)
3179  {
3180  os.str("");
3181  os.precision(18);
3182  os << matchPos->second.factor;
3183  pExponent = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
3185  pAddNode->addChild(pExponent);
3186  pAddNode->addChild(matchPos->second.pExponentNode);
3187  matchPos->second.pExponentNode = pAddNode;
3188  matchPos->second.factor = 0.0;
3189  }
3190 
3191  }
3192  }
3193  }
3194 
3195  result.push_back(matchPos->second);
3196  }
3197 
3198  ++orderIt;
3199  }
3200 
3201  return result;
3202 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const C_FLOAT64 & getValue() const
const Type & getType() const
std::string buildInfix() const
CEvaluationNode * pNode
std::set< unsigned int > subtraction_indices
static Type type(const Type &type)
std::set< unsigned int > addition_indices
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static CEvaluationNode * newEvaluateNumbers(const CEvaluationNode *pOrig)
static Type subType(const Type &type)
virtual std::string toString() const
CNormalFraction * createNormalRepresentation(const CEvaluationNode *node)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * pExponentNode
std::vector< std::pair< CEvaluationNode *, CEvaluationNode * > > CNormalTranslation::matchSummands ( const std::vector< CEvaluationNode * > &  additions,
const std::vector< CEvaluationNode * > &  subtractions 
)
staticprotected

The methods get a vector of addition elements and a vector of subtractions elements and tries to find equal elements in those two vectors.

The methods get a vector of multiplication elements and a vector of division elements and tries to find elements with the same power base in those two vectors.

std::vector<std::pair<CEvaluationNode*, CEvaluationNode*> > CNormalTranslation::matchPowerBases(const std::vector<const CEvaluationNode*>& multiplications, const std::vector<const CEvaluationNode*>& divisions) { std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > > matchMap; std::vector<const CEvaluationNode*>::const_iterator vit = multiplications.begin(), vendit = multiplications.end();

while (vit != vendit) { const CEvaluationNode* pBase = (vit); CEvaluationNode pExponent = NULL;

if (CEvaluationNode::type(pBase->getType()) == CEvaluationNode::OPERATOR && ((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pBase->getType())) == CEvaluationNodeOperator::POWER) { pBase = dynamic_cast<const CEvaluationNode*>(pBase->getChild()); pExponent = dynamic_cast<const CEvaluationNode*>(pBase->getSibling())->copyBranch(); } else { pExponent = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "1.0"); }

check if a base with the same infix is already in the map. if not, add the base if yes, add the exponent to the vector associated with the base std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > >::iterator mapIt = matchMap.begin(), mapEndit = matchMap.end(); CNormalFraction* pBase2 = createNormalRepresentation(pBase); std::string base2String = pBase2->toString(); delete pBase2;

while (mapIt != mapEndit) { if (mapIt->first.second == base2String) { mapIt->second.push_back(pExponent); break; }

++mapIt; }

if (mapIt == mapEndit) { std::vector<CEvaluationNode*> v; v.push_back(pExponent); matchMap.push_back(std::make_pair(std::pair<const CEvaluationNode*, std::string>(pBase, base2String), v)); }

++vit; }

std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > > matchMap2; vit = divisions.begin(), vendit = divisions.end();

while (vit != vendit) { const CEvaluationNode* pBase = (vit); CEvaluationNode pExponent = NULL;

if (CEvaluationNode::type(pBase->getType()) == CEvaluationNode::OPERATOR && ((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pBase->getType())) == CEvaluationNodeOperator::POWER) { pBase = dynamic_cast<const CEvaluationNode*>(pBase->getChild()); pExponent = dynamic_cast<const CEvaluationNode*>(pBase->getSibling())->copyBranch(); } else { pExponent = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "1.0"); }

check if a base with the same infix is already in the map. if not, add the base if yes, add the exponent to the vector associated with the base std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > >::iterator mapIt = matchMap2.begin(), mapEndit = matchMap2.end(); CNormalFraction* pBase2 = createNormalRepresentation(pBase); std::string base2String = pBase2->toString(); delete pBase2;

while (mapIt != mapEndit) { if (mapIt->first.second == base2String) { mapIt->second.push_back(pExponent); break; }

++mapIt; }

if (mapIt == mapEndit) { std::vector<CEvaluationNode*> v; v.push_back(pExponent); matchMap2.push_back(std::make_pair(std::pair<const CEvaluationNode*, std::string>(pBase, base2String), v)); }

++vit; }

now combine the two maps std::vector<std::pair<CEvaluationNode*, std::pair<CEvaluationNode*, std::string> > > result; std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > >::iterator mapIt = matchMap.begin(), mapEndit = matchMap.end();

while (mapIt != mapEndit) { CEvaluationNode* pNode = CNormalTranslation::createChain(&CNormalTranslation::PLUS_NODE, &CNormalTranslation::ZERO_NODE, mapIt->second); assert(pNode != NULL); result.push_back(std::make_pair(pNode, std::pair<CEvaluationNode*, std::string>(mapIt->first.first->copyBranch(), mapIt->first.second))); ++mapIt; }

mapIt = matchMap2.begin(), mapEndit = matchMap2.end();

while (mapIt != mapEndit) { std::vector<CEvaluationNode*> constVect; constVect.insert(constVect.begin(), mapIt->second.begin(), mapIt->second.end()); CEvaluationNode* pNode = CNormalTranslation::createOperatorChain(CEvaluationNodeOperator::PLUS, "+", constVect); now check if we already have a base with the same infix in the results unsigned int i, iMax = result.size();

for (i = 0; i < iMax; ++i) { if (result[i].second.second == mapIt->first.second) { CEvaluationNode* pTmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MINUS, "-"); pTmpNode->addChild(result[i].first); pTmpNode->addChild(pNode); result[i] = std::make_pair(pTmpNode, result[i].second); break; } }

if (i == iMax) { if (CEvaluationNode::type(pNode->getType()) == CEvaluationNode::NUMBER) { std::ostringstream os; os.precision(18); os << static_cast<CEvaluationNodeNumber*>(pNode)->getValue() * -1.0; CEvaluationNode* pTmpNumber = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str()); delete pNode; result.push_back(std::make_pair(pTmpNumber, std::pair<CEvaluationNode*, std::string>(mapIt->first.first->copyBranch(), mapIt->first.second))); } else { CEvaluationNode* pTmpNode = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*"); pTmpNode->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "-1.0")); pTmpNode->addChild(pNode); result.push_back(std::make_pair(pTmpNode, std::pair<CEvaluationNode*, std::string>(mapIt->first.first->copyBranch(), mapIt->first.second))); } }

delete the obsolete nodes iMax = mapIt->second.size();

for (i = 0; i < iMax; ++i) { delete mapIt->second[i]; }

++mapIt; }

copy the result vector into the return data structure std::vector<std::pair<CEvaluationNode*, CEvaluationNode*> > tmp; unsigned int i, iMax = result.size(); since we know how many elements will end up in tmp, we can already reserve the space tmp.reserve(iMax);

for (i = 0; i < iMax; ++i) { tmp.push_back(std::pair<CEvaluationNode*, CEvaluationNode*>(result[i].first, result[i].second.first)); }

return tmp; } The methods get a vector of addition elements and a vector of subtractions elements and tries to find equal elements in those two vectors.

Definition at line 3587 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::buildInfix(), CEvaluationNode::copyBranch(), createChain(), createNormalRepresentation(), createOperatorChain(), CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::PLUS, CEvaluationNode::subType(), CNormalFraction::toString(), and CEvaluationNode::type().

Referenced by newCancel().

3588 {
3589  // the individual elements could be multiplication chains and there could
3590  // be a common factor somewhere in the chain
3591  // Since I only want to get rid of numbers, it might be enough to
3592  // consider only those multiplication chains the contain a number node and
3593  // something else, everything else is ambiguous anyway and depends on
3594  // the order of the nodes in the chain
3595  std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > > matchMap;
3596 
3597  std::vector<CEvaluationNode*>::const_iterator vit = additions.begin(), vendit = additions.end();
3598 
3599  while (vit != vendit)
3600  {
3601  const CEvaluationNode* pNode = (*vit);
3602  CEvaluationNode* pFactor = NULL;
3603 
3605  {
3606  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pNode->getChild());
3607  assert(pChild1 != NULL);
3608  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
3609  assert(pChild2 != NULL);
3610  assert(pChild2->getSibling() == NULL);
3611 
3613  {
3614  pNode = pChild2;
3615  pFactor = pChild1->copyBranch();
3616  }
3617  else if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
3618  {
3619  pNode = pChild1;
3620  pFactor = pChild2->copyBranch();
3621  }
3622  else
3623  {
3625  }
3626  }
3627  else
3628  {
3630  }
3631 
3632  // check if a node with the same infix is already in the map.
3633  // if not, add the base
3634  // if yes, add the exponent to the vector associated with the base
3635  std::string base2String;
3636 
3637  if (pNode->getChild() != NULL)
3638  {
3640  base2String = pBase2->toString();
3641  delete pBase2;
3642  pBase2 = NULL;
3643  }
3644  else
3645  {
3646  base2String = pNode->buildInfix();
3647  }
3648 
3649  std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > >::iterator mapIt = matchMap.begin(), mapEndit = matchMap.end();
3650 
3651  while (mapIt != mapEndit)
3652  {
3653  if (mapIt->first.second == base2String)
3654  {
3655  mapIt->second.push_back(pFactor);
3656  break;
3657  }
3658 
3659  ++mapIt;
3660  }
3661 
3662 
3663  if (mapIt == mapEndit)
3664  {
3665  std::vector<CEvaluationNode*> v;
3666  v.push_back(pFactor);
3667  matchMap.push_back(std::make_pair(std::pair<const CEvaluationNode*, std::string>(pNode, base2String), v));
3668  }
3669 
3670  ++vit;
3671  }
3672 
3673  std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > > matchMap2;
3674  vit = subtractions.begin(), vendit = subtractions.end();
3675 
3676  while (vit != vendit)
3677  {
3678  const CEvaluationNode* pNode = (*vit);
3679  CEvaluationNode* pFactor = NULL;
3680 
3682  {
3683  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(pNode->getChild());
3684  assert(pChild1 != NULL);
3685  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
3686  assert(pChild2 != NULL);
3687  assert(pChild2->getSibling() == NULL);
3688 
3690  {
3691  pNode = pChild2;
3692  pFactor = pChild1->copyBranch();
3693  }
3694  else if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
3695  {
3696  pNode = pChild1;
3697  pFactor = pChild2->copyBranch();
3698  }
3699  else
3700  {
3702  }
3703  }
3704  else
3705  {
3707  }
3708 
3709  // check if a node with the same infix is already in the map.
3710  // if not, add the node
3711  // if yes, add the 1 to the vector associated with the base
3712  std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > >::iterator mapIt = matchMap2.begin(), mapEndit = matchMap2.end();
3713  std::string base2String;
3714 
3715  if (pNode->getChild() != NULL)
3716  {
3718  base2String = pBase2->toString();
3719  delete pBase2;
3720  }
3721  else
3722  {
3723  base2String = pNode->buildInfix();
3724  }
3725 
3726  while (mapIt != mapEndit)
3727  {
3728  if (mapIt->first.second == base2String)
3729  {
3730  mapIt->second.push_back(pFactor);
3731  break;
3732  }
3733 
3734  ++mapIt;
3735  }
3736 
3737 
3738  if (mapIt == mapEndit)
3739  {
3740  std::vector<CEvaluationNode*> v;
3741  v.push_back(pFactor);
3742  matchMap2.push_back(std::make_pair(std::pair<const CEvaluationNode*, std::string>(pNode, base2String), v));
3743  }
3744 
3745  ++vit;
3746  }
3747 
3748  // now combine the two maps
3749  std::vector<std::pair<CEvaluationNode*, std::pair<CEvaluationNode*, std::string> > > result;
3750  std::vector<std::pair<std::pair<const CEvaluationNode*, std::string>, std::vector<CEvaluationNode*> > >::iterator mapIt = matchMap.begin(), mapEndit = matchMap.end();
3751 
3752  while (mapIt != mapEndit)
3753  {
3755  assert(pNode != NULL);
3756  result.push_back(std::make_pair(pNode, std::pair<CEvaluationNode*, std::string>(mapIt->first.first->copyBranch(), mapIt->first.second)));
3757  ++mapIt;
3758  }
3759 
3760  mapIt = matchMap2.begin(), mapEndit = matchMap2.end();
3761 
3762  while (mapIt != mapEndit)
3763  {
3764  std::vector<CEvaluationNode*> constVect;
3765  constVect.insert(constVect.begin(), mapIt->second.begin(), mapIt->second.end());
3767  // now check if we already have a base with the same infix in the
3768  // results
3769  unsigned int i, iMax = result.size();
3770 
3771  for (i = 0; i < iMax; ++i)
3772  {
3773  if (result[i].second.second == mapIt->first.second)
3774  {
3776  pTmpNode->addChild(result[i].first);
3777  pTmpNode->addChild(pNode);
3778  result[i] = std::make_pair(pTmpNode, result[i].second);
3779  break;
3780  }
3781  }
3782 
3783  if (i == iMax)
3784  {
3785  CEvaluationNode* pTmpNode = NULL;
3786 
3788  {
3789  std::ostringstream os;
3790  os.precision(18);
3791  os << dynamic_cast<const CEvaluationNodeNumber*>(pNode)->getValue() * -1.0;
3792  pTmpNode = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
3793  delete pNode;
3794  }
3795  else
3796  {
3799  pTmpNode->addChild(pNode);
3800  }
3801 
3802  result.push_back(std::make_pair(pTmpNode, std::pair<CEvaluationNode*, std::string>(mapIt->first.first->copyBranch(), mapIt->first.second)));
3803  }
3804 
3805  // delete the obsolete nodes
3806  iMax = mapIt->second.size();
3807 
3808  for (i = 0; i < iMax; ++i)
3809  {
3810  delete mapIt->second[i];
3811  }
3812 
3813  ++mapIt;
3814  }
3815 
3816  std::vector<std::pair<CEvaluationNode*, CEvaluationNode*> > tmp;
3817  // copy the result vector into the expected return data type
3818  unsigned int i, iMax = result.size();
3819  // since we know how many item will end up in the vector we can already
3820  // reserve the space
3821  tmp.reserve(iMax);
3822 
3823  for (i = 0; i < iMax; ++i)
3824  {
3825  tmp.push_back(std::pair<CEvaluationNode*, CEvaluationNode*>(result[i].first, result[i].second.first));
3826  }
3827 
3828  return tmp;
3829 }
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
std::string buildInfix() const
static Type type(const Type &type)
static CEvaluationNode * createOperatorChain(CEvaluationNodeOperator::SubType type, const char *data, const std::vector< CEvaluationNode * > &nodes)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static const CEvaluationNode ZERO_NODE
static Type subType(const Type &type)
virtual std::string toString() const
CNormalFraction * createNormalRepresentation(const CEvaluationNode *node)
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
static const CEvaluationNode PLUS_NODE
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
std::vector< summ_match > CNormalTranslation::matchSummands ( const std::vector< const CEvaluationNode * > &  additions,
const std::vector< const CEvaluationNode * > &  subtractions 
)
staticprotected

The methods get a vector of addition elements and a vector of subtractions elements and tries to find equal elements in those two vectors.

Definition at line 3210 of file CNormalTranslation.cpp.

References summ_match::addition_indices, CEvaluationNode::buildInfix(), CEvaluationNode::copyBranch(), createNormalRepresentation(), summ_match::factor, CCopasiNode< _Data >::getChild(), CEvaluationNode::getType(), CEvaluationNode::getValue(), CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, summ_match::pNode, summ_match::subtraction_indices, CEvaluationNode::subType(), CNormalFraction::toString(), and CEvaluationNode::type().

3211 {
3212  // the individual elements could be multiplication chains and there could
3213  // be a common factor somewhere in the chain
3214  // Since I only want to get rid of numbers, it might be enough to
3215  // consider only those multiplication chains that contain a number node and
3216  // something else, everything else is ambiguous anyway and depends on
3217  // the order of the nodes in the chain
3218  std::map<const CEvaluationNode*, summ_match> matchMap;
3219  std::map<const CEvaluationNode*, summ_match>::iterator matchPos;
3220  std::map<std::string, const CEvaluationNode*> infixMap;
3221  std::map<std::string, const CEvaluationNode*>::iterator infixPos;
3222 
3223  summ_match match;
3224  std::vector<const CEvaluationNode*>::const_iterator vit = additions.begin(), vendit = additions.end();
3225  const CEvaluationNode *pNode = NULL, *pChild1 = NULL, *pChild2 = NULL;
3226  double factor = 0.0;
3227  CNormalFraction* pBase2 = NULL;
3228  std::string base2String;
3229  unsigned int index = 0;
3230  // we store the order in which the base string occur so that we can
3231  // return the result in approxiumately the same order, the will help in
3232  // reducing the problem of loops with changing element order
3233  std::list<const CEvaluationNode*> orderList;
3234 
3235  while (vit != vendit)
3236  {
3237  pNode = (*vit);
3238  factor = 1.0;
3239 
3241  {
3242  pChild1 = dynamic_cast<const CEvaluationNode*>(pNode->getChild());
3243  assert(pChild1 != NULL);
3244  pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
3245  assert(pChild2 != NULL);
3246  assert(pChild2->getSibling() == NULL);
3247 
3248  if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER)
3249  {
3250  pNode = pChild2;
3251  factor = pChild1->getValue();
3252  }
3253  else if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
3254  {
3255  pNode = pChild1;
3256  factor = pChild2->getValue();
3257  }
3258  }
3259 
3260  // check if a node with the same infix is already in the map.
3261  // if not, add the base
3262  // if yes, add the exponent to the vector associated with the base
3263  if (pNode->getChild() != NULL)
3264  {
3265  pBase2 = createNormalRepresentation(pNode);
3266  base2String = pBase2->toString();
3267  delete pBase2;
3268  pBase2 = NULL;
3269  }
3270  else
3271  {
3272  base2String = pNode->buildInfix();
3273  }
3274 
3275  infixPos = infixMap.find(base2String);
3276 
3277  if (infixPos != infixMap.end())
3278  {
3279  matchPos = matchMap.find(infixPos->second);
3280  assert(matchPos != matchMap.end());
3281 
3282  if (matchPos != matchMap.end())
3283  {
3284  matchPos->second.factor += factor;
3285  matchPos->second.addition_indices.insert(index);
3286  }
3287  }
3288  else
3289  {
3290  match.pNode = pNode->copyBranch();
3291  match.factor = factor;
3292  match.addition_indices.clear();
3293  match.addition_indices.insert(index);
3294  match.subtraction_indices.clear();
3295  infixMap.insert(std::pair<std::string, const CEvaluationNode*>(base2String, pNode));
3296  matchMap.insert(std::pair<const CEvaluationNode*, summ_match>(pNode, match));
3297  orderList.push_back(pNode);
3298  }
3299 
3300  ++index;
3301  ++vit;
3302  }
3303 
3304  index = 0;
3305 
3306  vit = subtractions.begin(), vendit = subtractions.end();
3307 
3308  while (vit != vendit)
3309  {
3310  pNode = (*vit);
3311  factor = -1.0;
3312 
3314  {
3315  pChild1 = dynamic_cast<const CEvaluationNode*>(pNode->getChild());
3316  assert(pChild1 != NULL);
3317  pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
3318  assert(pChild2 != NULL);
3319  assert(pChild2->getSibling() == NULL);
3320 
3321  if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER)
3322  {
3323  pNode = pChild2;
3324  factor = pChild1->getValue();
3325  }
3326  else if (CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
3327  {
3328  pNode = pChild1;
3329  factor = pChild2->getValue();
3330  }
3331  }
3332 
3333  // check if a node with the same infix is already in the map.
3334  // if not, add the node
3335  // if yes, add the 1 to the vector associated with the base
3336  if (pNode->getChild() != NULL)
3337  {
3338  pBase2 = createNormalRepresentation(pNode);
3339  base2String = pBase2->toString();
3340  delete pBase2;
3341  pBase2 = NULL;
3342  }
3343  else
3344  {
3345  base2String = pNode->buildInfix();
3346  }
3347 
3348  infixPos = infixMap.find(base2String);
3349 
3350  if (infixPos != infixMap.end())
3351  {
3352  matchPos = matchMap.find(infixPos->second);
3353  assert(matchPos != matchMap.end());
3354 
3355  if (matchPos != matchMap.end())
3356  {
3357  matchPos->second.factor -= factor;
3358  matchPos->second.subtraction_indices.insert(index);
3359  }
3360  }
3361  else
3362  {
3363  match.pNode = pNode->copyBranch();
3364  match.factor = factor;
3365  match.addition_indices.clear();
3366  match.subtraction_indices.clear();
3367  match.subtraction_indices.insert(index);
3368  infixMap.insert(std::pair<std::string, const CEvaluationNode*>(base2String, pNode));
3369  matchMap.insert(std::pair<const CEvaluationNode*, summ_match>(pNode, match));
3370  orderList.push_back(pNode);
3371  }
3372 
3373  ++index;
3374  ++vit;
3375  }
3376 
3377  // now combine the two maps
3378  std::vector<summ_match> result;
3379 
3380  std::list<const CEvaluationNode*>::const_iterator orderIt = orderList.begin(), orderEndit = orderList.end();
3381 
3382  while (orderIt != orderEndit)
3383  {
3384  matchPos = matchMap.find(*orderIt);
3385  assert(matchPos != matchMap.end());
3386 
3387  if (matchPos != matchMap.end())
3388  {
3389  result.push_back(matchPos->second);
3390  }
3391 
3392  ++orderIt;
3393  }
3394 
3395  return result;
3396 }
CEvaluationNode * copyBranch() const
const C_FLOAT64 & getValue() const
const Type & getType() const
std::string buildInfix() const
CEvaluationNode * pNode
std::set< unsigned int > subtraction_indices
static Type type(const Type &type)
std::set< unsigned int > addition_indices
static Type subType(const Type &type)
virtual std::string toString() const
CNormalFraction * createNormalRepresentation(const CEvaluationNode *node)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * CNormalTranslation::multiply ( const CEvaluationNode pNode1,
const CEvaluationNode pNode2 
)
staticprotected

Multiplies the two given nodes and returns the result.

Definition at line 3928 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), createChain(), CEvaluationNodeNumber::DOUBLE, CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, pResult, splitSum(), and CEvaluationNode::type().

Referenced by expandProducts().

3929 {
3930  CEvaluationNode* pResult = NULL;
3931  std::vector<const CEvaluationNode*> additions1, subtractions1;
3932  CNormalTranslation::splitSum(pNode1, additions1, subtractions1, false);
3933  std::vector<const CEvaluationNode*> additions2, subtractions2;
3934  CNormalTranslation::splitSum(pNode2, additions2, subtractions2, false);
3935  // multiply every element in additions1 with every element in additions2
3936  // and subtractions2 the results for the multiplication with the elements
3937  // of subtractions2 must be multiplied by -1
3938  // multiply every element in subtraction1 with every element in additions2
3939  // and subtractions2 the results for the multiplication with the elements
3940  // of additions2 must be multiplied by -1
3941  std::vector<CEvaluationNode*> tmp;
3942  unsigned int i, iMax = additions1.size();
3943 
3944  for (i = 0; i < iMax; ++i)
3945  {
3946  unsigned int j, jMax = additions2.size();
3947 
3948  for (j = 0; j < jMax; ++j)
3949  {
3951  pMult->addChild(additions1[i]->copyBranch());
3952  pMult->addChild(additions2[j]->copyBranch());
3953  tmp.push_back(pMult);
3954  }
3955  }
3956 
3957  iMax = subtractions1.size();
3958 
3959  for (i = 0; i < iMax; ++i)
3960  {
3961  unsigned int j, jMax = subtractions2.size();
3962 
3963  for (j = 0; j < jMax; ++j)
3964  {
3966  pMult->addChild(subtractions1[i]->copyBranch());
3967  pMult->addChild(subtractions2[j]->copyBranch());
3968  tmp.push_back(pMult);
3969  }
3970  }
3971 
3972  if (!tmp.empty())
3973  {
3975  assert(pResult != NULL);
3976  tmp.clear();
3977  }
3978 
3979  iMax = additions1.size();
3980 
3981  for (i = 0; i < iMax; ++i)
3982  {
3983  unsigned int j, jMax = subtractions2.size();
3984 
3985  for (j = 0; j < jMax; ++j)
3986  {
3988  pMult->addChild(additions1[i]->copyBranch());
3989  pMult->addChild(subtractions2[j]->copyBranch());
3990  tmp.push_back(pMult);
3991  }
3992  }
3993 
3994  iMax = subtractions1.size();
3995 
3996  for (i = 0; i < iMax; ++i)
3997  {
3998  unsigned int j, jMax = additions2.size();
3999 
4000  for (j = 0; j < jMax; ++j)
4001  {
4003  pMult->addChild(subtractions1[i]->copyBranch());
4004  pMult->addChild(additions2[j]->copyBranch());
4005  tmp.push_back(pMult);
4006  }
4007  }
4008 
4009  if (!tmp.empty())
4010  {
4011  if (pResult != NULL)
4012  {
4014  pTmpNode->addChild(pResult);
4015  pResult = pTmpNode;
4017  assert(pTmpNode != NULL);
4018  pResult->addChild(pTmpNode);
4019  }
4020  else
4021  {
4022  if (tmp.size() == 1 && CEvaluationNode::type(tmp[0]->getType()) == CEvaluationNode::NUMBER)
4023  {
4024  std::ostringstream os;
4025  os.precision(18);
4026  os << tmp[0]->getValue() * -1.0;
4027  pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
4028  delete tmp[0];
4029  }
4030  else
4031  {
4034  pResult = pTmpNode;
4036  assert(pTmpNode != NULL);
4037  pResult->addChild(pTmpNode);
4038  }
4039  }
4040  }
4041 
4042  return pResult;
4043 }
static void splitSum(const CEvaluationNode *pRoot, std::vector< CEvaluationNode * > &additions, std::vector< CEvaluationNode * > &substractions, bool minus)
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static const CEvaluationNode ZERO_NODE
const CArrayAnnotation * pResult
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
static const CEvaluationNode PLUS_NODE
CEvaluationNode * CNormalTranslation::newCancel ( const CEvaluationNode pOrig)
staticprotected

This method does all the canceling on a given node and its children. New non-recursive cancel method. This method does all the canceling on a given node and its children. If no canceling was done, NULL is returned.

New non-recursive cancel method. This method does all the canceling on a given node and its children. If no canceling was done, NULL is returned.

Definition at line 4050 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), createChain(), CEvaluationNodeOperator::DIVIDE, CEvaluationNodeNumber::DOUBLE, summ_match::factor, findNegativeNumbers(), CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getParent(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNodeDepthFirstIterator::isValid(), matchPowerBases(), matchSummands(), CEvaluationNodeOperator::MINUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::OPERATOR, product_match::pExponentNode, CEvaluationNodeOperator::PLUS, summ_match::pNode, CEvaluationNodeOperator::POWER, pResult, splitProduct(), splitSum(), CEvaluationNode::subType(), CEvaluationNode::type(), and ZERO.

Referenced by eliminate(), and simplify().

4051 {
4052  //
4053  // try to find multiplication chains where something is divided by itself
4054  // or multiplied by -1 times itself
4055  // also consider powers (it's the bases that have to match)
4056  //
4057  // try to find addition changes where there is a subtraction of two
4058  // identical nodes or an addition of one node and the same node times -1
4059  bool modified = false;
4060  // make a copy of the node
4061  CEvaluationNode* pResult = pOrig->copyBranch();
4062  assert(pResult != NULL);
4063  CEvaluationNodeDepthFirstIterator dfi(pResult);
4064  CEvaluationNode::Type type;
4065  CEvaluationNode* pTmpOrig = NULL;
4066  std::ostringstream os;
4067 
4068  while (dfi.isValid())
4069  {
4070  type = CEvaluationNode::type(dfi->getType());
4071 
4072  if (type == CEvaluationNode::OPERATOR)
4073  {
4074  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(dfi->getChild());
4075  assert(pChild1 != NULL);
4076  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
4077  assert(pChild2 != NULL);
4079 
4080  switch (subType)
4081  {
4084  {
4085  pTmpOrig = dynamic_cast<CEvaluationNode*>(dfi->getParent());
4086 
4087  // if there is no parent or if the parent is not a multiplication or division, we try to evaluate numbers
4089  {
4090  // do the canceling
4091  std::vector<const CEvaluationNode*> multiplications, divisions;
4092  CNormalTranslation::splitProduct(*dfi, multiplications, divisions, false);
4093  // collect all nodes in multiplications and divisions
4094 
4095  // find identical nodes in multiplications and divisions
4096  // The first entry in the pair is the collected power exponent
4097  // the second entry is the original power base
4098  // make sure the collected factor is again simplified
4099  std::vector<product_match> collected = CNormalTranslation::matchPowerBases(multiplications, divisions);
4100 
4101  // decide if matches were found
4102  // if we are working on a copy, we can go and delete those elements, that are no longer needed (e.g. all but the first entry for each match element)
4103  // remember to delete the entries in negAdditions and negSubtractions
4104  if (collected.size() != (multiplications.size() + divisions.size()))
4105  {
4106  std::vector<CEvaluationNode*> numeratorChain;
4107  std::vector<CEvaluationNode*> denominatorChain;
4108  unsigned int iMax = collected.size();
4109 
4110  for (unsigned int i = 0; i < iMax; ++i)
4111  {
4112  product_match& match = collected[i];
4113 
4114  // the matches we get back either have the factor set if it is a pure number,
4115  // or they have the pExponentNode set if it can't be represented as a pure number
4116  // if simplified node is a 0.0, we ignore this node
4117  if (match.pExponentNode == NULL)
4118  {
4119  if (fabs(match.factor) < ZERO)
4120  {
4121  delete match.pNode;
4122  match.pNode = NULL;
4123  }
4124  else if (match.factor > 0.0)
4125  {
4126  if (fabs(match.factor - 1.0) < ZERO)
4127  {
4128  numeratorChain.push_back(match.pNode);
4129  }
4130  else
4131  {
4132  os.str("");
4133  os.precision(18);
4134  os << match.factor;
4136  pPower->addChild(match.pNode);
4137  pPower->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str()));
4138  numeratorChain.push_back(pPower);
4139  }
4140  }
4141  else
4142  {
4143  if (fabs(match.factor + 1.0) < ZERO)
4144  {
4145  denominatorChain.push_back(match.pNode);
4146  }
4147  else
4148  {
4150  pPower->addChild(match.pNode);
4151  os.str("");
4152  os.precision(18);
4153  os << fabs(match.factor);
4154  pPower->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str()));
4155  denominatorChain.push_back(pPower);
4156  }
4157  }
4158  }
4159  else
4160  {
4161  // since the pExponentNode is not NULL, we can ignore the factor attribute
4162  // because it has already been added to the pExponentNode
4163  //
4164  // since the exponent can't be represented as a number, we probably don't now if the
4165  // exponent should be added to divisions or multiplications, so we just add all of them
4166  // to the numerator
4168  pPower->addChild(match.pNode);
4169  pPower->addChild(match.pExponentNode);
4170  numeratorChain.push_back(pPower);
4171  }
4172  }
4173 
4174  // if there are only divisions, we have an empty numerator chain
4175  if (numeratorChain.empty())
4176  {
4178  }
4179  else
4180  {
4182  }
4183 
4184  assert(pTmpOrig != NULL);
4185 
4186  if (!denominatorChain.empty())
4187  {
4189  pTmpNode->addChild(pTmpOrig);
4190  pTmpOrig = pTmpNode;
4192  assert(pTmpNode != NULL);
4193  pTmpOrig->addChild(pTmpNode);
4194  }
4195 
4196  assert(pTmpOrig != NULL);
4197 
4198  // now we need to replace dfi in it's parent by pTmpOrig and
4199  // delete dfi
4200  if (dfi->getParent() != NULL)
4201  {
4202  dfi->getParent()->addChild(pTmpOrig, *dfi);
4203  dfi->getParent()->removeChild(*dfi);
4204  delete *dfi;
4205  dfi = pTmpOrig;
4206  }
4207  else
4208  {
4209  // it must be the root node
4210  assert(*dfi == pResult);
4211  delete pResult;
4212  pResult = pTmpOrig;
4213  // we are done
4214  dfi = NULL;
4215  }
4216 
4217  modified = true;
4218  }
4219  else
4220  {
4221  // clean up
4222  std::vector<product_match>::iterator it2 = collected.begin(), endit2 = collected.end();
4223 
4224  while (it2 != endit2)
4225  {
4226  if ((*it2).pNode != NULL)
4227  {
4228  delete(*it2).pNode;
4229 
4230  if ((*it2).pExponentNode != NULL)
4231  {
4232  delete(*it2).pExponentNode;
4233  }
4234  }
4235 
4236  ++it2;
4237  }
4238  }
4239  }
4240  }
4241  break;
4244  {
4245  pTmpOrig = dynamic_cast<CEvaluationNode*>(dfi->getParent());
4246 
4247  // if there is no parent or if the parent is not an addition or subtraction, we try to evaluate numbers
4249  {
4250  // do the canceling
4251  // we are in a sum
4252  std::vector<const CEvaluationNode*> additions, subtractions;
4253  CNormalTranslation::splitSum(*dfi, additions, subtractions, false);
4254  std::vector<CEvaluationNode*> negAdditions, negSubtractions;
4255  CNormalTranslation::findNegativeNumbers(additions, negAdditions);
4256  CNormalTranslation::findNegativeNumbers(subtractions, negSubtractions);
4257  additions.insert(additions.end(), negSubtractions.begin(), negSubtractions.end());
4258  subtractions.insert(subtractions.end(), negAdditions.begin(), negAdditions.end());
4259 
4260  // find identical nodes in additions and subtractions
4261  // The first entry in the pair is the collected factor
4262  // the second entry is the original branch
4263  // make sure the collected factor is again simplified
4264  std::vector<summ_match> collected = CNormalTranslation::matchSummands(additions, subtractions);
4265  // cleanup the generated objects negXXX vector
4266  std::vector<CEvaluationNode*>::iterator it = negAdditions.begin(), endit = negAdditions.end();
4267 
4268  while (it != endit)
4269  {
4270  delete *it;
4271  ++it;
4272  }
4273 
4274  it = negSubtractions.begin(), endit = negSubtractions.end();
4275 
4276  while (it != endit)
4277  {
4278  delete *it;
4279  ++it;
4280  }
4281 
4282  // decide if matches were found
4283  // if we are working on a copy, we can go and delete those elements, that are no longer needed (e.g. all but the first entry for each match element)
4284  if (collected.size() != (additions.size() + subtractions.size()))
4285  {
4286  std::vector<CEvaluationNode*> chain;
4287  unsigned int iMax = collected.size();
4288 
4289 
4290  // now we have to create the result chain
4291  // all elements with a negative factor are subtracted and all indices with a
4292  // positive factor are added
4293  // all nodes with a 0.0 factor are dropped
4294  for (unsigned int i = 0; i < iMax; ++i)
4295  {
4296  summ_match& match = collected[i];
4297 
4298  // if simplified node is 0.0, we ignore this node
4299  if (fabs(match.factor) < ZERO)
4300  {
4301  delete match.pNode;
4302  }
4303  else if (fabs(match.factor - 1.0) < ZERO)
4304  {
4305  chain.push_back(match.pNode);
4306  }
4307  else
4308  {
4310  os.str("");
4311  os.precision(18);
4312  os << match.factor;
4313  pMult->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str()));
4314  assert(pMult != NULL);
4315  assert(match.pNode != NULL);
4316  pMult->addChild(match.pNode);
4317  chain.push_back(pMult);
4318  }
4319  }
4320 
4321  if (!chain.empty())
4322  {
4323  // we replace the current node with the result created here
4325  }
4326  else
4327  {
4328  // we replace the current node with the result created here
4329  // the result is 0.0
4331  }
4332 
4333  assert(pTmpOrig != NULL);
4334 
4335  // now we need to replace dfi in it's parent by pTmpOrig and
4336  // delete dfi
4337  if (dfi->getParent() != NULL)
4338  {
4339  dfi->getParent()->addChild(pTmpOrig, *dfi);
4340  dfi->getParent()->removeChild(*dfi);
4341  delete *dfi;
4342  dfi = pTmpOrig;
4343  }
4344  else
4345  {
4346  // it must be the root node
4347  assert(*dfi == pResult);
4348  delete pResult;
4349  pResult = pTmpOrig;
4350  // we are done
4351  dfi = NULL;
4352  }
4353 
4354  modified = true;
4355  }
4356  else
4357  {
4358  // delete the nodes in collected
4359  std::vector<summ_match>::iterator it2 = collected.begin(), endit2 = collected.end();
4360 
4361  while (it2 != endit2)
4362  {
4363  if ((*it2).pNode != NULL)
4364  {
4365  delete(*it2).pNode;
4366  }
4367 
4368  ++it2;
4369  }
4370  }
4371 
4372  // the entries in these two vectors can be cleared
4373  additions.clear();
4374  subtractions.clear();
4375  }
4376  }
4377  break;
4378  default:
4379  break;
4380  }
4381  }
4382 
4383  if (dfi.isValid())
4384  {
4385  ++dfi;
4386  }
4387  }
4388 
4389  if (modified == false)
4390  {
4391  delete pResult;
4392  pResult = NULL;
4393  }
4394 
4395  return pResult;
4396 }
static void splitSum(const CEvaluationNode *pRoot, std::vector< CEvaluationNode * > &additions, std::vector< CEvaluationNode * > &substractions, bool minus)
CEvaluationNode * copyBranch() const
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
const Type & getType() const
CEvaluationNode * pNode
static std::vector< product_match > matchPowerBases(const std::vector< const CEvaluationNode * > &multiplications, const std::vector< const CEvaluationNode * > &divisions)
static void findNegativeNumbers(std::vector< const CEvaluationNode * > &v1, std::vector< CEvaluationNode * > &v2)
static Type type(const Type &type)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
static const CEvaluationNode ONE_NODE
static const CEvaluationNode ZERO_NODE
static void splitProduct(const CEvaluationNode *pRoot, std::vector< const CEvaluationNode * > &multiplications, std::vector< const CEvaluationNode * > &divisions, bool division)
const CArrayAnnotation * pResult
static Type subType(const Type &type)
static std::vector< std::pair< CEvaluationNode *, CEvaluationNode * > > matchSummands(const std::vector< CEvaluationNode * > &additions, const std::vector< CEvaluationNode * > &subtractions)
static const CEvaluationNode TIMES_NODE
static CEvaluationNode * createChain(const CEvaluationNode *pLink, const CEvaluationNode *pNeutralElement, const std::vector< const CEvaluationNode * > &elements)
static const CEvaluationNode PLUS_NODE
CEvaluationNode * pExponentNode
static const double ZERO
CEvaluationNode * CNormalTranslation::newEvaluateNumbers ( const CEvaluationNode pOrig)
static

This method evaluates operators acting on two numbers This method evaluates operators acting on two numbers

This method replaces operations on two (or more) number nodes by the resulting number node. The returned node is either NULL, or a new node. If the returned node is not NULL, the caller is responsible for freeing the memory of the object.

Obsolete recursive version This method replaces operations on two (or more) number nodes by the resulting number node. The returned node is either NULL, or a new node. If the returned node is not NULL, the caller is responsible for freeing the memory of the object.

Definition at line 1755 of file CNormalTranslation.cpp.

References CCopasiNode< _Data >::addChild(), CEvaluationNode::copyBranch(), createChain(), CEvaluationNodeOperator::DIVIDE, CEvaluationNodeNumber::DOUBLE, CCopasiNode< _Data >::getChild(), CCopasiNode< _Data >::getParent(), CCopasiNode< _Data >::getSibling(), CEvaluationNode::getType(), CEvaluationNode::getValue(), CEvaluationNodeOperator::INVALID, CEvaluationNodeDepthFirstIterator::isValid(), CEvaluationNodeOperator::MINUS, CEvaluationNodeFunction::MINUS, CEvaluationNodeOperator::MODULUS, CEvaluationNodeOperator::MULTIPLY, CEvaluationNode::NUMBER, CEvaluationNode::OPERATOR, CEvaluationNodeOperator::PLUS, CEvaluationNodeOperator::POWER, pResult, splitProduct(), splitSum(), CEvaluationNode::subType(), swapNegativeNumbers(), CEvaluationNode::type(), and ZERO.

Referenced by createNormalRepresentation(), matchPowerBases(), and simplify().

1756 {
1757  // if the node is unmodified, return NULL
1758  // else try to make the modifications in place instead of copying the whole
1759  // subtree
1760  CEvaluationNode* pResult = NULL;
1761  // remember if we modified anything
1762  bool modified = false;
1763  // make a copy of the node
1764  pResult = pOrig->copyBranch();
1765  assert(pResult != NULL);
1766  CEvaluationNodeDepthFirstIterator dfi(pResult);
1767  CEvaluationNode::Type type;
1768  CEvaluationNode* pTmpOrig = NULL;
1769 
1770  while (dfi.isValid())
1771  {
1772  // check if the current node is an operator
1773  type = CEvaluationNode::type(dfi->getType());
1774 
1775  if (type == CEvaluationNode::OPERATOR)
1776  {
1777  const CEvaluationNode* pChild1 = dynamic_cast<const CEvaluationNode*>(dfi->getChild());
1778  assert(pChild1 != NULL);
1779  const CEvaluationNode* pChild2 = dynamic_cast<const CEvaluationNode*>(pChild1->getSibling());
1780  assert(pChild2 != NULL);
1782 
1783  switch (subType)
1784  {
1786 
1788  {
1789  std::ostringstream os;
1790  const CEvaluationNodeNumber* pNumberNode1 = dynamic_cast<const CEvaluationNodeNumber*>(pChild1);
1791  assert(pNumberNode1 != NULL);
1792  const CEvaluationNodeNumber* pNumberNode2 = dynamic_cast<const CEvaluationNodeNumber*>(pChild2);
1793  assert(pNumberNode1 != NULL);
1794  os << pow(pNumberNode1->getValue(), pNumberNode2->getValue());
1795  pTmpOrig = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
1796 
1797  // now we need to replace dfi in it's parent by pTmpOrig and
1798  // delete dfi
1799  if (dfi->getParent() != NULL)
1800  {
1801  dfi->getParent()->addChild(pTmpOrig, *dfi);
1802  dfi->getParent()->removeChild(*dfi);
1803  delete *dfi;
1804  dfi = pTmpOrig;
1805  }
1806  else
1807  {
1808  // it must be the root node
1809  assert(*dfi == pResult);
1810  delete pResult;
1811  pResult = pTmpOrig;
1812  // we are done
1813  dfi = NULL;
1814  }
1815 
1816  modified = true;
1817  }
1818 
1819  break;
1821 
1823  {
1824  std::ostringstream os;
1825  const CEvaluationNodeNumber* pNumberNode1 = dynamic_cast<const CEvaluationNodeNumber*>(pChild1);
1826  assert(pNumberNode1 != NULL);
1827  const CEvaluationNodeNumber* pNumberNode2 = dynamic_cast<const CEvaluationNodeNumber*>(pChild2);
1828  assert(pNumberNode2 != NULL);
1829  os << ((int)pNumberNode1->getValue()) % ((int)pNumberNode2->getValue());
1830  pTmpOrig = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
1831 
1832  // now we need to replace dfi in it's parent by pTmpOrig and
1833  // delete dfi
1834  if (dfi->getParent() != NULL)
1835  {
1836  dfi->getParent()->addChild(pTmpOrig, *dfi);
1837  dfi->getParent()->removeChild(*dfi);
1838  delete *dfi;
1839  dfi = pTmpOrig;
1840  }
1841  else
1842  {
1843  // it must be the root node
1844  assert(*dfi == pResult);
1845  delete pResult;
1846  pResult = pTmpOrig;
1847  // we are done
1848  dfi = NULL;
1849 
1850  }
1851 
1852  modified = true;
1853  }
1854 
1855  break;
1858  {
1859  pTmpOrig = dynamic_cast<CEvaluationNode*>(dfi->getParent());
1860 
1861  // if there is no parent or if the parent is not a multiplication or division, we try to evaluate numbers
1863  {
1864 
1865  std::vector<const CEvaluationNode*> multiplications, divisions;
1866  // multiplications and divisions contain the original nodes,
1867  // splitProduct doesn't copy nodes
1868  CNormalTranslation::splitProduct(*dfi, multiplications, divisions, false);
1869  std::set<CEvaluationNode*> multiplicationNumberNodes;
1870  unsigned int i, iMax = multiplications.size();
1871  CEvaluationNode* pNode = NULL;
1872 
1873  for (i = 0; i < iMax; ++i)
1874  {
1875  pNode = const_cast<CEvaluationNode*>(multiplications[i]);
1876 
1878  {
1879  multiplicationNumberNodes.insert(pNode);
1880  }
1881  }
1882 
1883  std::set<CEvaluationNode*> divisionNumberNodes;
1884  iMax = divisions.size();
1885 
1886  for (i = 0; i < iMax; ++i)
1887  {
1888  pNode = const_cast<CEvaluationNode*>(divisions[i]);
1889 
1891  {
1892  divisionNumberNodes.insert(pNode);
1893  }
1894  }
1895 
1896  if ((multiplicationNumberNodes.size() + divisionNumberNodes.size()) > 1)
1897  {
1898  // there are at least two number nodes, so we have to evaluate
1899  // the numbers
1900  double value = 1.0;
1901  std::set<CEvaluationNode*>::iterator it = multiplicationNumberNodes.begin(), endit = multiplicationNumberNodes.end();
1902 
1903  while (it != endit)
1904  {
1905  value *= (*it)->getValue();
1906  ++it;
1907  }
1908 
1909  it = divisionNumberNodes.begin();
1910  endit = divisionNumberNodes.end();
1911 
1912  while (it != endit)
1913  {
1914  value /= (*it)->getValue();
1915  ++it;
1916  }
1917 
1918  std::vector<CEvaluationNode*> newMultiplications, newDivisions;
1919 
1920  if (fabs((value - 1.0)) >= ZERO)
1921  {
1922  std::ostringstream os;
1923  os.precision(18);
1924 
1925  if (fabs(value) < 1.0)
1926  {
1927  os << 1.0 / value;
1928  CEvaluationNodeNumber* pEvaluated = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
1929  newDivisions.push_back(pEvaluated);
1930  }
1931  else
1932  {
1933  os << value;
1934  CEvaluationNodeNumber* pEvaluated = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
1935  newMultiplications.push_back(pEvaluated);
1936  }
1937  }
1938 
1939  std::vector<const CEvaluationNode*>::iterator it2 = multiplications.begin(), endit2 = multiplications.end();
1940 
1941  while (it2 != endit2)
1942  {
1943  // if the node is not in multiplicationNumberNodes, we add
1944  // it
1945  it = multiplicationNumberNodes.find(const_cast<CEvaluationNode*>(*it2));
1946 
1947  if (it == multiplicationNumberNodes.end())
1948  {
1949 
1950  CEvaluationNode* pTmpNode = const_cast<CEvaluationNode*>(*it2);
1951 
1952  // to reuse the nodes, we have to remove them from their original parent
1953  if (pTmpNode->getParent() != NULL)
1954  {
1955  pTmpNode->getParent()->removeChild(pTmpNode);
1956  }
1957 
1958  newMultiplications.push_back(pTmpNode);
1959  }
1960  else
1961  {
1962  // delete the old number node
1963  delete *it2;
1964  }
1965 
1966  ++it2;
1967  }
1968 
1969  it2 = divisions.begin();
1970  endit2 = divisions.end();
1971 
1972  while (it2 != endit2)
1973  {
1974  // if the node is not in multiplicationNumberNodes, we add
1975  // it
1976  it = divisionNumberNodes.find(const_cast<CEvaluationNode*>(*it2));
1977 
1978  if (it == divisionNumberNodes.end())
1979  {
1980  CEvaluationNode* pTmpNode = const_cast<CEvaluationNode*>(*it2);
1981 
1982  // to reuse the nodes, we have to remove them from their original parent
1983  if (pTmpNode->getParent() != NULL)
1984  {
1985  pTmpNode->getParent()->removeChild(pTmpNode);
1986  }
1987 
1988  newDivisions.push_back(const_cast<CEvaluationNode*>(pTmpNode));
1989  }
1990  else
1991  {
1992  // delete the old number node
1993  delete *it2;
1994  }
1995 
1996  ++it2;
1997  }
1998 
1999  // now we create a new result node from the newMultiplications
2000  // and newDivisions
2001  if (newMultiplications.empty())
2002  {
2004  }
2005  else
2006  {
2008  }
2009 
2010  if (!newDivisions.empty())
2011  {
2013  pTmpNode->addChild(pTmpOrig);
2014  pTmpOrig = pTmpNode;
2016  pTmpOrig->addChild(pTmpNode);
2017  }
2018 
2019  // now we need to replace dfi in it's parent by pTmpOrig and
2020  // delete dfi
2021  if (dfi->getParent() != NULL)
2022  {
2023  dfi->getParent()->addChild(pTmpOrig, *dfi);
2024  dfi->getParent()->removeChild(*dfi);
2025  delete *dfi;
2026  dfi = pTmpOrig;
2027  }
2028  else
2029  {
2030  // it must be the root node
2031  assert(*dfi == pResult);
2032  delete pResult;
2033  pResult = pTmpOrig;
2034  // we are done
2035  dfi = NULL;
2036  }
2037 
2038  modified = true;
2039 
2040  }
2041  }
2042  }
2043  break;
2046  {
2047  pTmpOrig = dynamic_cast<CEvaluationNode*>(dfi->getParent());
2048 
2049  // if there is no parent or if the parent is not a multiplication or division, we try to evaluate numbers
2051  {
2052  std::vector<CEvaluationNode*> additions, subtractions;
2053  // splitSum copies the nodes that are returned
2054  CNormalTranslation::splitSum(*dfi, additions, subtractions, false);
2055  CNormalTranslation::swapNegativeNumbers(additions, subtractions);
2056  std::set<CEvaluationNode*> additionNumberNodes;
2057  unsigned int i, iMax = additions.size();
2058  CEvaluationNode* pNode = NULL;
2059 
2060  for (i = 0; i < iMax; ++i)
2061  {
2062  pNode = const_cast<CEvaluationNode*>(additions[i]);
2063 
2065  {
2066  additionNumberNodes.insert(pNode);
2067  }
2068  }
2069 
2070  std::set<CEvaluationNode*> subtractionNumberNodes;
2071  iMax = subtractions.size();
2072 
2073  for (i = 0; i < iMax; ++i)
2074  {
2075  pNode = const_cast<CEvaluationNode*>(subtractions[i]);
2076 
2078  {
2079  subtractionNumberNodes.insert(pNode);
2080  }
2081  }
2082 
2083  if ((additionNumberNodes.size() + subtractionNumberNodes.size()) > 1)
2084  {
2085  // there are at least two number nodes, so we have to evaluate
2086  // the numbers
2087  double value = 0.0;
2088  std::set<CEvaluationNode*>::const_iterator it = additionNumberNodes.begin(), endit = additionNumberNodes.end();
2089 
2090  while (it != endit)
2091  {
2092  value += (*it)->getValue();
2093  ++it;
2094  }
2095 
2096  it = subtractionNumberNodes.begin();
2097  endit = subtractionNumberNodes.end();
2098 
2099  while (it != endit)
2100  {
2101  value -= (*it)->getValue();
2102  ++it;
2103  }
2104 
2105  std::vector<CEvaluationNode*> newAdditions, newSubtractions;
2106 
2107  if (fabs(value) >= ZERO)
2108  {
2109  std::ostringstream os;
2110  os.precision(18);
2111 
2112  if (value < 0.0)
2113  {
2114  os << -1.0 * value;
2115  CEvaluationNodeNumber* pEvaluated = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
2116  newSubtractions.push_back(pEvaluated);
2117  }
2118  else
2119  {
2120  os << value;
2121  CEvaluationNodeNumber* pEvaluated = new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, os.str().c_str());
2122  newAdditions.push_back(pEvaluated);
2123  }
2124  }
2125 
2126  // now we have to copy all nonnumber nodes
2127  std::vector<CEvaluationNode*>::const_iterator it2 = additions.begin(), endit2 = additions.end();
2128 
2129  while (it2 != endit2)
2130  {
2131  // if the node is not in additionNumberNodes, we copy
2132  // it
2133  it = additionNumberNodes.find(*it2);
2134 
2135  if (it == additionNumberNodes.end())
2136  {
2137  newAdditions.push_back(*it2);
2138  }
2139  else
2140  {
2141  // delete the original node that was created by splitSum
2142  delete *it2;
2143  }
2144 
2145  ++it2;
2146  }
2147 
2148  it2 = subtractions.begin();
2149  endit2 = subtractions.end();
2150 
2151  while (it2 != endit2)
2152  {
2153  // if the node is not in subtractionNumberNodes, we copy
2154  // it
2155  it = subtractionNumberNodes.find(*it2);
2156 
2157  if (it == subtractionNumberNodes.end())
2158  {
2159  newSubtractions.push_back(*it2);
2160  }
2161  else
2162  {
2163  // delete the original node that was created by splitSum
2164  delete *it2;
2165  }
2166 
2167