COPASI API  4.16.103
compare_utilities.cpp
Go to the documentation of this file.
1 // Begin CVS Header
2 // $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/compareExpressions/compare_utilities.cpp,v $
3 // $Revision: 1.15 $
4 // $Name: $
5 // $Author: shoops $
6 // $Date: 2012/05/15 15:56:21 $
7 // End CVS Header
8 
9 // Copyright (C) 2012 - 2010 by Pedro Mendes, Virginia Tech Intellectual
10 // Properties, Inc., University of Heidelberg, and The University
11 // of Manchester.
12 // All rights reserved.
13 
14 // Copyright (C) 2008 by Pedro Mendes, Virginia Tech Intellectual
15 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
16 // and The University of Manchester.
17 // All rights reserved.
18 
19 // Copyright (C) 2001 - 2007 by Pedro Mendes, Virginia Tech Intellectual
20 // Properties, Inc. and EML Research, gGmbH.
21 // All rights reserved.
22 
23 #ifdef WIN32
24 # pragma warning (disable: 4786)
25 # pragma warning (disable: 4243)
26 // warning C4355: 'this' : used in base member initializer list
27 # pragma warning (disable: 4355)
28 #endif // WIN32
29 
30 #include <sstream>
31 
32 #include "compare_utilities.h"
33 
34 #include "sbml/math/ASTNode.h"
35 #include "sbml/Model.h"
36 #include "CNormalBase.h"
37 #include "CNormalFraction.h"
38 #include "CNormalFunction.h"
39 #include "CNormalSum.h"
40 #include "CNormalProduct.h"
41 #include "CNormalLogical.h"
42 #include "CNormalLogicalItem.h"
43 #include "CNormalChoice.h"
44 #include "CNormalChoiceLogical.h"
45 #include "CNormalGeneralPower.h"
46 #include "CNormalItemPower.h"
47 #include "CNormalItem.h"
48 #include "CNormalTranslation.h"
59 #include "sbml/FunctionDefinition.h"
60 #include "copasi/model/CChemEq.h"
62 #include "copasi/model/CModel.h"
65 
66 /**
67  * Creates an expanded expression from the given expression.
68  * This method expands all function calls.
69  * On failure NULL is returned, otherwise an expanded copy of the original node
70  * is returned.
71  */
72 ASTNode* create_expression(const ASTNode* pSource, const ListOfFunctionDefinitions* pFunctions)
73 {
74  // expand all function calls
75  ASTNode* pResult = expand_function_calls(pSource, pFunctions);
76  return pResult;
77 }
78 
79 /**
80  * This method expands the function calls in the given expression.
81  * On failure NULL is returned, otherwise a copy of the original node
82  * is returned where all function calls have been expanded.
83  */
84 ASTNode* expand_function_calls(const ASTNode* pNode, const ListOfFunctionDefinitions* pFunctions)
85 {
86  ASTNode* pResult = NULL;
87 
88  if (pNode->getType() == AST_FUNCTION)
89  {
90  pResult = expand_function_call(pNode, pFunctions);
91 
92  if (pResult == NULL)
93  {
94  return NULL;
95  }
96 
97  ASTNode* pTmp = expand_function_calls(pResult, pFunctions);
98 
99  if (pTmp == NULL)
100  {
101  delete pResult;
102  return NULL;
103  }
104 
105  delete pResult;
106  pResult = pTmp;
107  }
108  else
109  {
110  // only make a shallow copy
111  pResult = ConverterASTNode::shallowCopy(pNode);
112  unsigned int i = 0;
113  unsigned int iMax = pNode->getNumChildren();
114  ASTNode* pChild = NULL;
115  ASTNode* pNewChild = NULL;
116 
117  while (i < iMax)
118  {
119  pChild = pNode->getChild(i);
120  assert(pChild != NULL);
121  pNewChild = expand_function_calls(pChild, pFunctions);
122 
123  if (pNewChild == NULL)
124  {
125  delete pResult;
126  pResult = NULL;
127  break;
128  }
129 
130  pResult->addChild(pNewChild);
131  ++i;
132  }
133  }
134 
135  return pResult;
136 }
137 
138 /**
139  * This method expands the given function call.
140  * On failure NULL is returned, otherwise on expression of the expanded
141  * function call is returned.
142  */
143 ASTNode* expand_function_call(const ASTNode* pCall, const ListOfFunctionDefinitions* pFunctions)
144 {
145  // find the function that belongs to the call
146  const FunctionDefinition * pFunctionDefinition = pFunctions->get(pCall->getName());
147  ASTNode* pResult = NULL;
148 
149  if (pFunctionDefinition == NULL) return NULL;
150 
151  // create the mapping
152  unsigned int iMax = pFunctionDefinition->getNumArguments();
153 
154  if (pFunctionDefinition != NULL && iMax == pCall->getNumChildren())
155  {
156  // map the first function argument to the first child in the call etc.
157  std::map<std::string, const ASTNode*> argumentMap;
158  unsigned int i = 0;
159 
160  while (i < iMax)
161  {
162  argumentMap[pFunctionDefinition->getArgument(i)->getName()] = pCall->getChild(i);
163  ++i;
164  }
165 
166  // create the resulting tree
167  pResult = pFunctionDefinition->getBody()->deepCopy();
168  ASTNode* pTmpNode = replace_variable_names(pResult, argumentMap);
169  assert(pTmpNode != NULL);
170  delete pResult;
171  pResult = pTmpNode;
172  }
173 
174  return pResult;
175 }
176 
177 ASTNode* replace_variable_names(const ASTNode* pNode, const std::map<std::string, const ASTNode*>& argumentMap)
178 {
179  ASTNode* pResult = NULL;
180 
181  if (pNode->getType() == AST_NAME)
182  {
183  std::map<std::string, const ASTNode*>::const_iterator pos = argumentMap.find(pNode->getName());
184 
185  if (pos == argumentMap.end())
186  {
187  pResult = NULL;
188  }
189  else
190  {
191  pResult = pos->second->deepCopy();
192  }
193  }
194  else
195  {
196  // only make a shallow copy
197  pResult = ConverterASTNode::shallowCopy(pNode);
198  unsigned int i = 0;
199  unsigned int iMax = pNode->getNumChildren();
200  ASTNode* pChild = NULL;
201  ASTNode* pNewChild = NULL;
202 
203  while (i < iMax)
204  {
205  pChild = pNode->getChild(i);
206  assert(pChild != NULL);
207  pNewChild = replace_variable_names(pChild, argumentMap);
208  assert(pNewChild != NULL);
209  pResult->addChild(pNewChild);
210  ++i;
211  }
212  }
213 
214  return pResult;
215 }
216 
217 /**
218  * This method takes two normalforms and normalizes the variable names in both
219  * expressions.
220  * Afterwards the two expressions are compared. If they are equal true is
221  * returned.
222  */
223 bool are_equal(const CNormalFraction* pLHS, const CNormalFraction* pRHS)
224 {
225  bool result = true;
226  // replace all variable names in the normalform so that the naming scheme
227  // is consistent
228  std::map<std::string, std::string> variableMap;
229  CNormalFraction* pTmpLHS = new CNormalFraction(*pLHS);
230  normalize_variable_names(pTmpLHS, variableMap);
231  variableMap.clear();
232  CNormalFraction* pTmpRHS = new CNormalFraction(*pRHS);
233  normalize_variable_names(pTmpRHS, variableMap);
234  result = ((*pTmpLHS) == (*pTmpRHS));
235  delete pTmpLHS;
236  delete pTmpRHS;
237  return result;
238 }
239 
240 /**
241  * This method normalizes the variable names in a given normalform expression.
242  * The first variable found in the expression is named "variable1", the second
243  * "variable2" and so on.
244  */
245 void normalize_variable_names(CNormalBase* pBase, std::map<std::string, std::string>& variableMap)
246 {
247  CNormalChoice* pChoice = NULL;
248  CNormalChoiceLogical* pLogicalChoice = NULL;
249  CNormalFraction* pFraction = NULL;
250  CNormalFunction* pFunction = NULL;
251  CNormalGeneralPower* pGeneralPower = NULL;
252  CNormalItem* pItem = NULL;
253  CNormalItemPower* pItemPower = NULL;
254  CNormalLogical* pLogical = NULL;
255  CNormalLogicalItem* pLogicalItem = NULL;
256  CNormalProduct* pProduct = NULL;
257  CNormalSum* pSum = NULL;
258 
259  if ((pChoice = dynamic_cast<CNormalChoice*>(pBase)) != NULL)
260  {
261  normalize_variable_names(&pChoice->getCondition(), variableMap);
262  normalize_variable_names(&pChoice->getTrueExpression(), variableMap);
263  normalize_variable_names(&pChoice->getFalseExpression(), variableMap);
264  }
265  else if ((pLogicalChoice = dynamic_cast<CNormalChoiceLogical*>(pBase)) != NULL)
266  {
267  normalize_variable_names(&pChoice->getCondition(), variableMap);
268  normalize_variable_names(&pChoice->getTrueExpression(), variableMap);
269  normalize_variable_names(&pChoice->getFalseExpression(), variableMap);
270  }
271  else if ((pFraction = dynamic_cast<CNormalFraction*>(pBase)) != NULL)
272  {
273  normalize_variable_names(&pFraction->getNumerator(), variableMap);
274 
275  if (!pFraction->checkDenominatorOne())
276  {
277  normalize_variable_names(&pFraction->getDenominator(), variableMap);
278  }
279  }
280  else if ((pFunction = dynamic_cast<CNormalFunction*>(pBase)) != NULL)
281  {
282  normalize_variable_names(&pFunction->getFraction(), variableMap);
283  }
284  else if ((pGeneralPower = dynamic_cast<CNormalGeneralPower*>(pBase)) != NULL)
285  {
286  normalize_variable_names(&pGeneralPower->getLeft(), variableMap);
287  normalize_variable_names(&pGeneralPower->getRight(), variableMap);
288  }
289  else if ((pItem = dynamic_cast<CNormalItem*>(pBase)) != NULL)
290  {
291  std::map<std::string, std::string>::iterator pos;
292 
293  switch (pItem->getType())
294  {
296  pos = variableMap.find(pItem->getName());
297 
298  if (pos != variableMap.end())
299  {
300  pItem->setName(pos->second);
301  }
302  else
303  {
304  std::ostringstream ostrstr;
305  ostrstr << "variable";
306  ostrstr.width(7);
307  ostrstr.fill('0');
308  ostrstr << variableMap.size() + 1;
309  variableMap[pItem->getName()] = ostrstr.str();
310  pItem->setName(ostrstr.str());
311  }
312 
313  break;
314  default:
315  break;
316  }
317  }
318  else if ((pItemPower = dynamic_cast<CNormalItemPower*>(pBase)) != NULL)
319  {
320  normalize_variable_names(&pItemPower->getItem(), variableMap);
321  }
322  else if ((pLogical = dynamic_cast<CNormalLogical*>(pBase)) != NULL)
323  {
325  CNormalLogical::ChoiceSetOfSets::const_iterator it = pLogical->getChoices().begin(), endit = pLogical->getChoices().end();
326 
327  while (it != endit)
328  {
329  CNormalLogical::ChoiceSet tmpChoiceSet;
330  CNormalLogical::ChoiceSet::const_iterator innerit = (*it).first.begin(), innerendit = (*it).first.end();
331 
332  while (innerit != innerendit)
333  {
334  pLogicalChoice = new CNormalChoiceLogical(*(*innerit).first);
335  normalize_variable_names(pLogicalChoice, variableMap);
336  tmpChoiceSet.insert(std::make_pair(pLogicalChoice, (*innerit).second));
337  ++innerit;
338  }
339 
340  tmpSet.insert(std::make_pair(tmpChoiceSet, (*it).second));
341  ++it;
342  }
343 
344  pLogical->setChoices(tmpSet);
347  CNormalLogical::ItemSetOfSets::const_iterator it2 = pLogical->getAndSets().begin(), endit2 = pLogical->getAndSets().end();
348 
349  while (it2 != endit2)
350  {
351  CNormalLogical::ItemSet tmpItemSet;
352  CNormalLogical::ItemSet::const_iterator innerit = (*it2).first.begin(), innerendit = (*it2).first.end();
353 
354  while (innerit != innerendit)
355  {
356  pLogicalItem = new CNormalLogicalItem(*(*innerit).first);
357  normalize_variable_names(pLogicalItem, variableMap);
358  tmpItemSet.insert(std::make_pair(pLogicalItem, (*innerit).second));
359  ++innerit;
360  }
361 
362  tmpSet2.insert(std::make_pair(tmpItemSet, (*it2).second));
363  ++it2;
364  }
365 
366  pLogical->setAndSets(tmpSet2);
368  }
369  else if ((pLogicalItem = dynamic_cast<CNormalLogicalItem*>(pBase)) != NULL)
370  {
371  normalize_variable_names(&pLogicalItem->getLeft(), variableMap);
372  normalize_variable_names(&pLogicalItem->getRight(), variableMap);
373  }
374  else if ((pProduct = dynamic_cast<CNormalProduct*>(pBase)) != NULL)
375  {
376  std::set<CNormalItemPower*, compareItemPowers> tmpSet;
377  std::set<CNormalItemPower*, compareItemPowers>::const_iterator it = pProduct->getItemPowers().begin(), endit = pProduct->getItemPowers().end();
378 
379  while (it != endit)
380  {
381  CNormalItemPower* pItemPower = new CNormalItemPower(**it);
382  normalize_variable_names(pItemPower, variableMap);
383  tmpSet.insert(pItemPower);
384  ++it;
385  }
386 
387  pProduct->setItemPowers(tmpSet);
388  it = tmpSet.begin(), endit = tmpSet.end();
389 
390  while (it != endit)
391  {
392  delete *it;
393  ++it;
394  }
395  }
396  else if ((pSum = dynamic_cast<CNormalSum*>(pBase)) != NULL)
397  {
398  std::set<CNormalFraction*> tmpSet;
399  std::set<CNormalFraction*>::const_iterator it = pSum->getFractions().begin(), endit = pSum->getFractions().end();
400 
401  while (it != endit)
402  {
403  pFraction = new CNormalFraction(**it);
404  normalize_variable_names(pFraction, variableMap);
405  tmpSet.insert(pFraction);
406  ++it;
407  }
408 
409  pSum->setFractions(tmpSet);
410  it = tmpSet.begin(), endit = tmpSet.end();
411 
412  while (it != endit)
413  {
414  delete *it;
415  ++it;
416  }
417 
418  std::set<CNormalProduct*, compareProducts> tmpSet2;
419  std::set<CNormalProduct*, compareProducts>::const_iterator it2 = pSum->getProducts().begin(), endit2 = pSum->getProducts().end();
420 
421  while (it2 != endit2)
422  {
423  pProduct = new CNormalProduct(**it2);
424  normalize_variable_names(pProduct, variableMap);
425  tmpSet2.insert(pProduct);
426  ++it2;
427  }
428 
429  pSum->setProducts(tmpSet2);
430  it2 = tmpSet2.begin(), endit2 = tmpSet2.end();
431 
432  while (it2 != endit2)
433  {
434  delete(*it2);
435  ++it2;
436  }
437  }
438 }
439 
440 /**
441  * This method converts a given ASTNode into a CNormalFraction.
442  * The expression is simplified in the process to create the "final"
443  * normalform.
444  */
446 {
447  CNormalFraction* pFraction = NULL;
448  // translate the ASTNode based tree into an CEvaluationNode based tree and
449  CEvaluationNode* pEvaluationNode = CEvaluationTree::fromAST(pSource);
450  // all variable nodes in this tree are objects nodes so we have to convert
451  // them
452  CCopasiTree<CEvaluationNode>::iterator treeIt = pEvaluationNode;
453 
454  // if the root node already is an object node, this has to be dealt with separately
455  if (dynamic_cast<CEvaluationNodeObject*>(&(*treeIt)))
456  {
457  CEvaluationNodeVariable* pVariableNode = new CEvaluationNodeVariable(CEvaluationNodeVariable::ANY, (*treeIt).getData().substr(1, (*treeIt).getData().length() - 2));
458  delete pEvaluationNode;
459  pEvaluationNode = pVariableNode;
460  }
461  else
462  {
463  while (treeIt != NULL)
464  {
465  if (dynamic_cast<CEvaluationNodeObject*>(&(*treeIt)))
466  {
467  CEvaluationNodeVariable* pVariableNode = new CEvaluationNodeVariable(CEvaluationNodeVariable::ANY, (*treeIt).getData().substr(1, (*treeIt).getData().length() - 2));
468 
469  if ((*treeIt).getParent())
470  {
471  (*treeIt).getParent()->addChild(pVariableNode, &(*treeIt));
472  (*treeIt).getParent()->removeChild(&(*treeIt));
473  }
474 
475  delete &(*treeIt);
476  treeIt = pVariableNode;
477  }
478 
479  ++treeIt;
480  }
481  }
482 
483  if (pEvaluationNode != NULL)
484  {
485  // create the normalform from that
486  pFraction = dynamic_cast<CNormalFraction*>(CNormalTranslation::normAndSimplifyReptdly(pEvaluationNode));
487  delete pEvaluationNode;
488  }
489 
490  return pFraction;
491 }
492 
493 /**
494  * This method converts a given ASTNode into a CNormalFraction.
495  * The resulting normalform is not necessarily simplified.
496  */
497 CNormalFraction* create_normalform(const ASTNode* pSource)
498 {
499  CNormalFraction* pFraction = NULL;
500  // translate the ASTNode based tree into an CEvaluationNode based tree and
501  CEvaluationNode* pEvaluationNode = CEvaluationTree::fromAST(pSource);
502  // all variable nodes in this tree are objects nodes so we have to convert
503  // them
504  CCopasiTree<CEvaluationNode>::iterator treeIt = pEvaluationNode;
505 
506  // if the root node already is an object node, this has to be dealt with separately
507  if (dynamic_cast<CEvaluationNodeObject*>(&(*treeIt)))
508  {
509  CEvaluationNodeVariable* pVariableNode = new CEvaluationNodeVariable(CEvaluationNodeVariable::ANY, (*treeIt).getData().substr(1, (*treeIt).getData().length() - 2));
510  delete pEvaluationNode;
511  pEvaluationNode = pVariableNode;
512  }
513  else
514  {
515  while (treeIt != NULL)
516  {
517  if (dynamic_cast<CEvaluationNodeObject*>(&(*treeIt)))
518  {
519  CEvaluationNodeVariable* pVariableNode = new CEvaluationNodeVariable(CEvaluationNodeVariable::ANY, (*treeIt).getData().substr(1, (*treeIt).getData().length() - 2));
520 
521  if ((*treeIt).getParent())
522  {
523  (*treeIt).getParent()->addChild(pVariableNode, &(*treeIt));
524  (*treeIt).getParent()->removeChild(&(*treeIt));
525  }
526 
527  delete &(*treeIt);
528  treeIt = pVariableNode;
529  }
530 
531  ++treeIt;
532  }
533  }
534 
535  if (pEvaluationNode != NULL)
536  {
537  // create the normalform from that
538  pFraction = createNormalRepresentation(pEvaluationNode);
539  delete pEvaluationNode;
540  }
541 
542  return pFraction;
543 }
544 
545 /**
546  * This function replaces a call to SEC by 1/COS.
547  */
548 ASTNode* replace_SEC(const ASTNode* pChild)
549 {
550  ASTNode* pResult = NULL;
551 
552  if (pChild != NULL)
553  {
554  pResult = new ASTNode(AST_DIVIDE);
555  ASTNode* pTmpNode = new ASTNode(AST_INTEGER);
556  pTmpNode->setValue(1);
557  pResult->addChild(pTmpNode);
558  pTmpNode = new ASTNode(AST_FUNCTION_COS);
559  pTmpNode->addChild(pChild->deepCopy());
560  pResult->addChild(pTmpNode);
561  }
562 
563  return pResult;
564 }
565 
566 /**
567  * This function replaces a call to CSC by 1/SIN.
568  */
569 ASTNode* replace_CSC(const ASTNode* pChild)
570 {
571  ASTNode* pResult = NULL;
572 
573  if (pChild != NULL)
574  {
575  pResult = new ASTNode(AST_DIVIDE);
576  ASTNode* pTmpNode = new ASTNode(AST_INTEGER);
577  pTmpNode->setValue(1);
578  pResult->addChild(pTmpNode);
579  pTmpNode = new ASTNode(AST_FUNCTION_SIN);
580  pTmpNode->addChild(pChild->deepCopy());
581  pResult->addChild(pTmpNode);
582  }
583 
584  return pResult;
585 }
586 
587 /**
588  * This function replaces a call to COT by COS/SIN.
589  */
590 ASTNode* replace_COT(const ASTNode* pChild)
591 {
592  ASTNode* pResult = NULL;
593 
594  if (pChild != NULL)
595  {
596  pResult = new ASTNode(AST_DIVIDE);
597  ASTNode* pTmpNode = new ASTNode(AST_FUNCTION_COS);
598  pTmpNode->addChild(pChild->deepCopy());
599  pResult->addChild(pTmpNode);
600  pTmpNode = new ASTNode(AST_FUNCTION_SIN);
601  pTmpNode->addChild(pChild->deepCopy());
602  pResult->addChild(pTmpNode);
603  }
604 
605  return pResult;
606 }
607 
608 /**
609  * This function replaces a call to SINH by (e^X-e^(-X))/2.
610  */
611 ASTNode* replace_SINH(const ASTNode* pChild)
612 {
613  ASTNode* pResult = NULL;
614 
615  if (pChild != NULL)
616  {
617  pResult = new ASTNode(AST_DIVIDE);
618  ASTNode* pTmpNode = new ASTNode(AST_MINUS);
619  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
620  pTmpNode2->addChild(pChild->deepCopy());
621  pTmpNode->addChild(pTmpNode2);
622  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
623  ASTNode* pTmpNode3 = new ASTNode(AST_MINUS);
624  pTmpNode3->addChild(pChild->deepCopy());
625  pTmpNode2->addChild(pTmpNode3);
626  pTmpNode->addChild(pTmpNode2);
627  pResult->addChild(pTmpNode);
628  pTmpNode = new ASTNode(AST_INTEGER);
629  pTmpNode->setValue(2);
630  pResult->addChild(pTmpNode);
631  }
632 
633  return pResult;
634 }
635 
636 /**
637  * This function replaces a call to COSH by (e^X+e^(-X))/2
638  */
639 ASTNode* replace_COSH(const ASTNode* pChild)
640 {
641  ASTNode* pResult = NULL;
642 
643  if (pChild != NULL)
644  {
645  pResult = new ASTNode(AST_DIVIDE);
646  ASTNode* pTmpNode = new ASTNode(AST_PLUS);
647  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
648  pTmpNode2->addChild(pChild->deepCopy());
649  pTmpNode->addChild(pTmpNode2);
650  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
651  ASTNode* pTmpNode3 = new ASTNode(AST_MINUS);
652  pTmpNode3->addChild(pChild->deepCopy());
653  pTmpNode2->addChild(pTmpNode3);
654  pTmpNode->addChild(pTmpNode2);
655  pResult->addChild(pTmpNode);
656  pTmpNode = new ASTNode(AST_INTEGER);
657  pTmpNode->setValue(2);
658  pResult->addChild(pTmpNode);
659  }
660 
661  return pResult;
662 }
663 
664 /**
665  * This function replaces a call to TANH by (e^X-e^(-X))/(e^X+e^(-X))
666  */
667 ASTNode* replace_TANH(const ASTNode* pChild)
668 {
669  ASTNode* pResult = NULL;
670 
671  if (pChild != NULL)
672  {
673  pResult = new ASTNode(AST_DIVIDE);
674  ASTNode* pTmpNode = new ASTNode(AST_MINUS);
675  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
676  pTmpNode2->addChild(pChild->deepCopy());
677  pTmpNode->addChild(pTmpNode2);
678  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
679  ASTNode* pTmpNode3 = new ASTNode(AST_MINUS);
680  pTmpNode3->addChild(pChild->deepCopy());
681  pTmpNode2->addChild(pTmpNode3);
682  pTmpNode->addChild(pTmpNode2);
683  pResult->addChild(pTmpNode);
684  pTmpNode = new ASTNode(AST_PLUS);
685  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
686  pTmpNode2->addChild(pChild->deepCopy());
687  pTmpNode->addChild(pTmpNode2);
688  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
689  pTmpNode3 = new ASTNode(AST_MINUS);
690  pTmpNode3->addChild(pChild->deepCopy());
691  pTmpNode2->addChild(pTmpNode3);
692  pTmpNode->addChild(pTmpNode2);
693  pResult->addChild(pTmpNode);
694  }
695 
696  return pResult;
697 }
698 
699 /**
700  * This function replaces a call to SECH by 2/(e^X+e^(-X))
701  */
702 ASTNode* replace_SECH(const ASTNode* pChild)
703 {
704  ASTNode* pResult = NULL;
705 
706  if (pChild != NULL)
707  {
708  pResult = new ASTNode(AST_DIVIDE);
709  ASTNode* pTmpNode = new ASTNode(AST_INTEGER);
710  pTmpNode->setValue(2);
711  pResult->addChild(pTmpNode);
712  pTmpNode = new ASTNode(AST_PLUS);
713  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
714  pTmpNode2->addChild(pChild->deepCopy());
715  pTmpNode->addChild(pTmpNode2);
716  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
717  ASTNode* pTmpNode3 = new ASTNode(AST_MINUS);
718  pTmpNode3->addChild(pChild->deepCopy());
719  pTmpNode2->addChild(pTmpNode3);
720  pTmpNode->addChild(pTmpNode2);
721  pResult->addChild(pTmpNode);
722  }
723 
724  return pResult;
725 }
726 
727 /**
728  * This function replaces a call to CSCH by 2/(e^X-e^(-X))
729  */
730 ASTNode* replace_CSCH(const ASTNode* pChild)
731 {
732  ASTNode* pResult = NULL;
733 
734  if (pChild != NULL)
735  {
736  pResult = new ASTNode(AST_DIVIDE);
737  ASTNode* pTmpNode = new ASTNode(AST_INTEGER);
738  pTmpNode->setValue(2);
739  pResult->addChild(pTmpNode);
740  pTmpNode = new ASTNode(AST_MINUS);
741  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
742  pTmpNode2->addChild(pChild->deepCopy());
743  pTmpNode->addChild(pTmpNode2);
744  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
745  ASTNode* pTmpNode3 = new ASTNode(AST_MINUS);
746  pTmpNode3->addChild(pChild->deepCopy());
747  pTmpNode2->addChild(pTmpNode3);
748  pTmpNode->addChild(pTmpNode2);
749  pResult->addChild(pTmpNode);
750  }
751 
752  return pResult;
753 }
754 
755 /**
756  * This function replaces a call to COTH by (e^X+e^(-X))/(e^X-e^(-X))
757  */
758 ASTNode* replace_COTH(const ASTNode* pChild)
759 {
760  ASTNode* pResult = NULL;
761 
762  if (pChild != NULL)
763  {
764  pResult = new ASTNode(AST_DIVIDE);
765  ASTNode* pTmpNode = new ASTNode(AST_PLUS);
766  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
767  pTmpNode2->addChild(pChild->deepCopy());
768  pTmpNode->addChild(pTmpNode2);
769  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
770  ASTNode* pTmpNode3 = new ASTNode(AST_MINUS);
771  pTmpNode3->addChild(pChild->deepCopy());
772  pTmpNode2->addChild(pTmpNode3);
773  pTmpNode->addChild(pTmpNode2);
774  pResult->addChild(pTmpNode);
775  pTmpNode = new ASTNode(AST_MINUS);
776  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
777  pTmpNode2->addChild(pChild->deepCopy());
778  pTmpNode->addChild(pTmpNode2);
779  pTmpNode2 = new ASTNode(AST_FUNCTION_EXP);
780  pTmpNode3 = new ASTNode(AST_MINUS);
781  pTmpNode3->addChild(pChild->deepCopy());
782  pTmpNode2->addChild(pTmpNode3);
783  pTmpNode->addChild(pTmpNode2);
784  pResult->addChild(pTmpNode);
785  }
786 
787  return pResult;
788 }
789 
790 /**
791  * This function replaces a call to ARCSINH by log(X + sqrt(X^2 + 1))
792  */
793 ASTNode* replace_ARCSINH(const ASTNode* pChild)
794 {
795  ASTNode* pResult = NULL;
796 
797  if (pChild != NULL)
798  {
799  pResult = new ASTNode(AST_FUNCTION_LOG);
800  ASTNode* pTmpNode = new ASTNode(AST_PLUS);
801  pTmpNode->addChild(pChild->deepCopy());
802  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_POWER);
803  ASTNode* pTmpNode3 = new ASTNode(AST_PLUS);
804  ASTNode* pTmpNode4 = new ASTNode(AST_FUNCTION_POWER);
805  pTmpNode4->addChild(pChild->deepCopy());
806  ASTNode* pTmpNode5 = new ASTNode(AST_INTEGER);
807  pTmpNode5->setValue(2);
808  pTmpNode4->addChild(pTmpNode5);
809  pTmpNode3->addChild(pTmpNode4);
810  pTmpNode4 = new ASTNode(AST_INTEGER);
811  pTmpNode4->setValue(1);
812  pTmpNode3->addChild(pTmpNode4);
813  pTmpNode2->addChild(pTmpNode3);
814  pTmpNode3 = new ASTNode(AST_REAL);
815  pTmpNode3->setValue(0.5);
816  pTmpNode2->addChild(pTmpNode3);
817  pTmpNode->addChild(pTmpNode2);
818  pResult->addChild(pTmpNode);
819  }
820 
821  return pResult;
822 }
823 
824 /**
825  * This function replaces a call to ARCCOSH by log(X + sqrt(X-1) * sqrt(X+1))
826  */
827 ASTNode* replace_ARCCOSH(const ASTNode* pChild)
828 {
829  ASTNode* pResult = NULL;
830 
831  if (pChild != NULL)
832  {
833  pResult = new ASTNode(AST_FUNCTION_LOG);
834  ASTNode* pTmpNode = new ASTNode(AST_PLUS);
835  pTmpNode->addChild(pChild->deepCopy());
836  ASTNode* pTmpNode2 = new ASTNode(AST_TIMES);
837  ASTNode* pTmpNode3 = new ASTNode(AST_FUNCTION_POWER);
838  ASTNode* pTmpNode4 = new ASTNode(AST_MINUS);
839  pTmpNode4->addChild(pChild->deepCopy());
840  ASTNode* pTmpNode5 = new ASTNode(AST_INTEGER);
841  pTmpNode5->setValue(1);
842  pTmpNode4->addChild(pTmpNode5);
843  pTmpNode3->addChild(pTmpNode4);
844  pTmpNode4 = new ASTNode(AST_REAL);
845  pTmpNode4->setValue(0.5);
846  pTmpNode3->addChild(pTmpNode4);
847  pTmpNode2->addChild(pTmpNode3);
848  pTmpNode3 = new ASTNode(AST_FUNCTION_POWER);
849  pTmpNode4 = new ASTNode(AST_PLUS);
850  pTmpNode4->addChild(pChild->deepCopy());
851  pTmpNode5 = new ASTNode(AST_INTEGER);
852  pTmpNode5->setValue(1);
853  pTmpNode4->addChild(pTmpNode5);
854  pTmpNode3->addChild(pTmpNode4);
855  pTmpNode4 = new ASTNode(AST_REAL);
856  pTmpNode4->setValue(0.5);
857  pTmpNode3->addChild(pTmpNode4);
858  pTmpNode2->addChild(pTmpNode3);
859  pTmpNode->addChild(pTmpNode2);
860  pResult->addChild(pTmpNode);
861  }
862 
863  return pResult;
864 }
865 
866 /**
867  * This function replaces a call to ARCTANH by 1/2 * (log(1+X) - log(1-X))
868  */
869 ASTNode* replace_ARCTANH(const ASTNode* pChild)
870 {
871  ASTNode* pResult = NULL;
872 
873  if (pChild != NULL)
874  {
875  pResult = new ASTNode(AST_TIMES);
876  ASTNode* pTmpNode = new ASTNode(AST_RATIONAL);
877  pTmpNode->setValue((long)1, (long)2);
878  pResult->addChild(pTmpNode);
879  pTmpNode = new ASTNode(AST_MINUS);
880  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_LOG);
881  ASTNode* pTmpNode3 = new ASTNode(AST_PLUS);
882  ASTNode* pTmpNode4 = new ASTNode(AST_INTEGER);
883  pTmpNode4->setValue(1);;
884  pTmpNode3->addChild(pTmpNode4);
885  pTmpNode3->addChild(pChild->deepCopy());
886  pTmpNode2->addChild(pTmpNode3);
887  pTmpNode->addChild(pTmpNode2);
888  pTmpNode2 = new ASTNode(AST_FUNCTION_LOG);
889  pTmpNode3 = new ASTNode(AST_MINUS);
890  pTmpNode4 = new ASTNode(AST_INTEGER);
891  pTmpNode4->setValue(1);;
892  pTmpNode3->addChild(pTmpNode4);
893  pTmpNode3->addChild(pChild->deepCopy());
894  pTmpNode2->addChild(pTmpNode3);
895  pTmpNode->addChild(pTmpNode2);
896  pResult->addChild(pTmpNode);
897  }
898 
899  return pResult;
900 }
901 
902 /**
903  * This function replaces a call to ARCSECH by log(sqrt((1/X)-1) * sqrt(1+(1/X)) + 1/X)
904  */
905 ASTNode* replace_ARCSECH(const ASTNode* pChild)
906 {
907  ASTNode* pResult = NULL;
908 
909  if (pChild != NULL)
910  {
911  pResult = new ASTNode(AST_FUNCTION_LOG);
912  ASTNode* pTmpNode = new ASTNode(AST_PLUS);
913  ASTNode* pTmpNode2 = new ASTNode(AST_TIMES);
914  ASTNode* pTmpNode3 = new ASTNode(AST_FUNCTION_POWER);
915  ASTNode* pTmpNode4 = new ASTNode(AST_MINUS);
916  ASTNode* pTmpNode5 = new ASTNode(AST_DIVIDE);
917  ASTNode* pTmpNode6 = new ASTNode(AST_INTEGER);
918  pTmpNode6->setValue(1);
919  pTmpNode5->addChild(pTmpNode6);
920  pTmpNode5->addChild(pChild->deepCopy());
921  pTmpNode4->addChild(pTmpNode5);
922  pTmpNode5 = new ASTNode(AST_INTEGER);
923  pTmpNode5->setValue(1);
924  pTmpNode4->addChild(pTmpNode5);
925  pTmpNode3->addChild(pTmpNode4);
926  pTmpNode4 = new ASTNode(AST_REAL);
927  pTmpNode4->setValue(0.5);
928  pTmpNode3->addChild(pTmpNode4);
929  pTmpNode2->addChild(pTmpNode3);
930  pTmpNode3 = new ASTNode(AST_FUNCTION_POWER);
931  pTmpNode4 = new ASTNode(AST_PLUS);
932  pTmpNode5 = new ASTNode(AST_INTEGER);
933  pTmpNode5->setValue(1);
934  pTmpNode4->addChild(pTmpNode5);
935  pTmpNode5 = new ASTNode(AST_DIVIDE);
936  pTmpNode6 = new ASTNode(AST_INTEGER);
937  pTmpNode6->setValue(1);
938  pTmpNode5->addChild(pTmpNode6);
939  pTmpNode5->addChild(pChild->deepCopy());
940  pTmpNode4->addChild(pTmpNode5);
941  pTmpNode3->addChild(pTmpNode4);
942  pTmpNode4 = new ASTNode(AST_REAL);
943  pTmpNode4->setValue(0.5);
944  pTmpNode3->addChild(pTmpNode4);
945  pTmpNode2->addChild(pTmpNode3);
946  pTmpNode->addChild(pTmpNode2);
947  pTmpNode2 = new ASTNode(AST_DIVIDE);
948  pTmpNode3 = new ASTNode(AST_INTEGER);
949  pTmpNode3->setValue(1);
950  pTmpNode2->addChild(pTmpNode3);
951  pTmpNode2->addChild(pChild->deepCopy());
952  pTmpNode->addChild(pTmpNode2);
953  pResult->addChild(pTmpNode);
954  }
955 
956  return pResult;
957 }
958 
959 /**
960  * This function replaces a call to ARCCSCH by log(sqrt(1+ (1/ (X^2)))+(1/X))
961  */
962 ASTNode* replace_ARCCSCH(const ASTNode* pChild)
963 {
964  ASTNode* pResult = NULL;
965 
966  if (pChild != NULL)
967  {
968  pResult = new ASTNode(AST_FUNCTION_LOG);
969  ASTNode* pTmpNode = new ASTNode(AST_PLUS);
970  ASTNode* pTmpNode2 = new ASTNode(AST_FUNCTION_POWER);
971  ASTNode* pTmpNode3 = new ASTNode(AST_PLUS);
972  ASTNode* pTmpNode4 = new ASTNode(AST_INTEGER);
973  pTmpNode4->setValue(1);
974  pTmpNode3->addChild(pTmpNode4);
975  pTmpNode4 = new ASTNode(AST_DIVIDE);
976  ASTNode* pTmpNode5 = new ASTNode(AST_INTEGER);
977  pTmpNode5->setValue(1);
978  pTmpNode4->addChild(pTmpNode5);
979  pTmpNode5 = new ASTNode(AST_FUNCTION_POWER);
980  pTmpNode5->addChild(pChild->deepCopy());
981  ASTNode* pTmpNode6 = new ASTNode(AST_INTEGER);
982  pTmpNode6->setValue(2);
983  pTmpNode5->addChild(pTmpNode6);
984  pTmpNode4->addChild(pTmpNode5);
985  pTmpNode3->addChild(pTmpNode4);
986  pTmpNode2->addChild(pTmpNode3);
987  pTmpNode->addChild(pTmpNode2);
988  pTmpNode2 = new ASTNode(AST_DIVIDE);
989  pTmpNode3 = new ASTNode(AST_INTEGER);
990  pTmpNode3->setValue(1);
991  pTmpNode2->addChild(pTmpNode3);
992  pTmpNode2->addChild(pChild->deepCopy());
993  pTmpNode->addChild(pTmpNode2);
994  pResult->addChild(pTmpNode);
995  }
996 
997  return pResult;
998 }
999 
1000 /**
1001  * This method expands the function calls in the given expression.
1002  * On failure NULL is returned, otherwise a copy of the original node
1003  * is returned where all function calls have been expanded.
1004  */
1006 {
1007  CEvaluationNode* pResult = NULL;
1008  const CEvaluationNodeCall* pCall = dynamic_cast<const CEvaluationNodeCall*>(pNode);
1009 
1010  if (pCall != NULL)
1011  {
1012  pResult = expand_function_call(pCall, pFunctionDB);
1013 
1014  if (pResult == NULL)
1015  {
1016  return NULL;
1017  }
1018 
1019  CEvaluationNode* pTmp = expand_function_calls(pResult, pFunctionDB);
1020 
1021  if (pTmp == NULL)
1022  {
1023  delete pResult;
1024  return NULL;
1025  }
1026 
1027  delete pResult;
1028  pResult = pTmp;
1029  }
1030  else
1031  {
1032  // only make a shallow copy
1033  std::vector<CEvaluationNode*> v;
1034  pResult = pNode->copyNode(v);
1035  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pNode->getChild());
1036  CEvaluationNode* pNewChild = NULL;
1037 
1038  while (pChild != NULL)
1039  {
1040  pNewChild = expand_function_calls(pChild, pFunctionDB);
1041 
1042  if (pNewChild == NULL)
1043  {
1044  delete pResult;
1045  pResult = NULL;
1046  break;
1047  }
1048 
1049  pResult->addChild(pNewChild);
1050  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
1051  }
1052  }
1053 
1054  return pResult;
1055 }
1056 
1057 /**
1058  * This method expands the given function call.
1059  * On failure NULL is returned, otherwise on expression of the expanded
1060  * function call is returned.
1061  */
1063 {
1064  // find the function that belongs to the call
1065  CEvaluationNode* pResult = NULL;
1066  const CEvaluationTree* pTree = pFunctionDB->findFunction(pCall->getData());
1067 
1068  if (pTree != NULL)
1069  {
1070  const CFunction* pFunctionDefinition = dynamic_cast<const CFunction*>(pTree);
1071  // create the mapping
1072  assert(pFunctionDefinition != NULL);
1073  const CFunctionParameters& functionParameters = pFunctionDefinition->getVariables();
1074  unsigned int i, iMax = functionParameters.size();
1075  // map the first function argument to the first child in the call etc.
1076  std::map<std::string, const CEvaluationNode*> argumentMap;
1077  i = 0;
1078  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pCall->getChild());
1079 
1080  while (i < iMax)
1081  {
1082  assert(pChild != NULL);
1083  argumentMap[functionParameters[i]->getObjectName()] = pChild;
1084  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
1085  ++i;
1086  }
1087 
1088  // create the resulting tree
1089  pResult = pFunctionDefinition->getRoot()->copyBranch();
1090  CEvaluationNode* pTmpNode = replace_variable_names(pResult, argumentMap);
1091  assert(pTmpNode != NULL);
1092  delete pResult;
1093  assert(pChild == NULL);
1094  pResult = pTmpNode;
1095  }
1096 
1097  return pResult;
1098 }
1099 
1100 CEvaluationNode* replace_variable_names(const CEvaluationNode* pNode, const std::map<std::string, const CEvaluationNode*>& argumentMap)
1101 {
1102  CEvaluationNode* pResult = NULL;
1103 
1104  if (dynamic_cast<const CEvaluationNodeVariable*>(pNode) != NULL)
1105  {
1106  std::map<std::string, const CEvaluationNode*>::const_iterator pos = argumentMap.find(pNode->getData());
1107 
1108  if (pos != argumentMap.end())
1109  {
1110  pResult = pos->second->copyBranch();
1111  }
1112  }
1113  else
1114  {
1115  // only make a shallow copy
1116  std::vector<CEvaluationNode*> v;
1117  pResult = pNode->copyNode(v);
1118  const CEvaluationNode* pChild = dynamic_cast<const CEvaluationNode*>(pNode->getChild());
1119  CEvaluationNode* pNewChild = NULL;
1120 
1121  while (pChild != NULL)
1122  {
1123  pNewChild = replace_variable_names(pChild, argumentMap);
1124  assert(pNewChild != NULL);
1125  pResult->addChild(pNewChild);
1126  pChild = dynamic_cast<const CEvaluationNode*>(pChild->getSibling());
1127  }
1128  }
1129 
1130  return pResult;
1131 }
1132 
1133 
1134 bool is_mass_action(const CNormalFraction* pFrac, const CModel* pModel, const CChemEq* pChemEq)
1135 {
1136  bool result = true;
1137 
1138  // all objects must be valid and the denominator of the fraction must be one
1139  if (pFrac != NULL && pModel != NULL && pChemEq != NULL && pFrac->checkDenominatorOne())
1140  {
1141  const CNormalSum* pNumerator = &pFrac->getNumerator();
1142 
1143  if (pNumerator != NULL && pNumerator->getFractions().empty())
1144  {
1145  // the numerator has to have either one element if the reaction
1146  // is irreversible or two if the reaction is reversible
1147  if ((pChemEq->getReversibility() == true && pNumerator->getProducts().size() == 2) || pNumerator->getProducts().size() == 1)
1148  {
1149  // if the reaction is reversible we have to find out which element
1150  // contains the substrates and which contains the products
1151  const CNormalProduct* pSubstrates = NULL;
1152 
1153  if (pChemEq->getReversibility() == true)
1154  {
1155  const CNormalProduct* pProducts = NULL;
1156  C_FLOAT64 factor1 = (*pNumerator->getProducts().begin())->getFactor();
1157  C_FLOAT64 factor2 = (*(++(pNumerator->getProducts().begin())))->getFactor();
1158 
1159  if (fabs(factor1 + 1.0) < 1e-23 && fabs(factor2 - 1.0) < 1e-23)
1160  {
1161  pProducts = *pNumerator->getProducts().begin();
1162  pSubstrates = *(++(pNumerator->getProducts().begin()));
1163  }
1164  else if (fabs(factor1 - 1.0) < 1e-23 && fabs(factor2 + 1.0) < 1e-23)
1165  {
1166  pSubstrates = *pNumerator->getProducts().begin();
1167  pProducts = *(++(pNumerator->getProducts().begin()));
1168  }
1169 
1170  if (pProducts != NULL)
1171  {
1172  result = contains_necessary_mass_action_elements(pChemEq->getProducts(), pProducts, pModel);
1173  }
1174  else
1175  {
1176  result = false;
1177  }
1178  }
1179  else
1180  {
1181  if (fabs((*pNumerator->getProducts().begin())->getFactor() - 1.0) < 1e-23)
1182  {
1183  pSubstrates = *pNumerator->getProducts().begin();
1184  }
1185  else
1186  {
1187  result = false;
1188  }
1189  }
1190 
1191  if (result == true && pSubstrates != NULL)
1192  {
1193  // check if pSubstrates constains a product
1194  // that consists of all the substrates of the reaction with the correct
1195  // exponents
1196  // as well as some parameter
1197  result = contains_necessary_mass_action_elements(pChemEq->getSubstrates(), pSubstrates, pModel);
1198  }
1199  }
1200  }
1201  else
1202  {
1203  result = false;
1204  }
1205  }
1206  else
1207  {
1208  result = false;
1209  }
1210 
1211  return result;
1212 }
1213 
1214 
1216 {
1217  // check if pProducts contains a product
1218  // that consists of all the products of the reaction with the correct
1219  // exponents
1220  // as well as some parameter
1221  bool result = true;
1222 
1223  if (pModel != NULL && pProduct != NULL && elements.size() > 0)
1224  {
1225  const CCopasiObject* pObject = NULL;
1226  const CNormalItem* pItem = NULL;
1227  const CMetab* pMetab = NULL;
1228  const CCopasiDataModel* pDatamodel = dynamic_cast<const CCopasiDataModel*>(pModel->getObjectParent());
1229  assert(pDatamodel != NULL);
1230  std::vector<CCopasiContainer*> listOfContainers;
1231  listOfContainers.push_back(const_cast<CModel*>(pModel));
1232 
1233  CCopasiVector<CChemEqElement> tmpV = elements;
1234  std::vector<const CCopasiObject*> tmpObjects;
1235  const std::set<CNormalItemPower*, compareItemPowers >& itemPowers = pProduct->getItemPowers();
1236  std::set <CNormalItemPower*, compareItemPowers >::const_iterator iit = itemPowers.begin(), iendit = itemPowers.end();
1237 
1238  while (iit != iendit && result != false)
1239  {
1240 
1241  // check that the item is an instance of CNormalItem with type VARIABLE
1242  // and that the variable corresponds to the common name of one of the
1243  // products
1244  // check if iit has the correct exponent
1245  if ((*iit)->getItemType() == CNormalItemPower::ITEM)
1246  {
1247  pItem = dynamic_cast<const CNormalItem*>(&(*iit)->getItem());
1248 
1249  if (pItem != NULL && pItem->getType() == CNormalItem::VARIABLE)
1250  {
1251  std::string cn = pItem->getName();
1252  pObject = pDatamodel->ObjectFromName(listOfContainers, cn);
1253 
1254  if (pObject != NULL)
1255  {
1256  if (pObject->isReference())
1257  {
1258  pObject = pObject->getObjectParent();
1259  assert(pObject != NULL);
1260  }
1261 
1262  pMetab = dynamic_cast<const CMetab*>(pObject);
1263 
1264  if (pMetab != NULL)
1265  {
1266  CCopasiVector<CChemEqElement>::iterator tmpVIt = tmpV.begin(), tmpVEndit = tmpV.end();
1267 
1268  while (tmpVIt != tmpVEndit)
1269  {
1270  // check if we have found the metab and if the exponent is correct
1271  if (pMetab == (*tmpVIt)->getMetabolite() && fabs((*tmpVIt)->getMultiplicity() - (*iit)->getExp()) < 1e-23)
1272  {
1273  // delete the item from tmpV
1274  tmpV.remove(*tmpVIt);
1275  break;
1276  }
1277 
1278  ++tmpVIt;
1279  }
1280  }
1281  else
1282  {
1283  // the exponent has to be 1
1284  if (fabs((*iit)->getExp() - 1.0) < 1e-23)
1285  {
1286  tmpObjects.push_back(pObject);
1287  }
1288  else
1289  {
1290  result = false;
1291  }
1292  }
1293  }
1294  else
1295  {
1296  result = false;
1297  }
1298  }
1299  else
1300  {
1301  result = false;
1302  }
1303  }
1304  else
1305  {
1306  result = false;
1307  }
1308 
1309  ++iit;
1310  }
1311 
1312  // only the entry for the parameter should be left in tmpV
1313  if (tmpV.size() == 0 && tmpObjects.size() == 1)
1314  {
1315  // check if the item is a local or global parameter
1316  if (!(dynamic_cast<const CModelValue*>(tmpObjects[0]) || dynamic_cast<const CCopasiParameter*>(tmpObjects[0])))
1317  {
1318  result = false;
1319  }
1320  }
1321  else
1322  {
1323  result = false;
1324  }
1325  }
1326  else
1327  {
1328  result = false;
1329  }
1330 
1331  return result;
1332 }
CNormalSum & getNumerator()
ASTNode * replace_ARCTANH(const ASTNode *pChild)
CEvaluationNode * copyBranch() const
ASTNode * replace_COT(const ASTNode *pChild)
Header file of class CModelEntity and CModelValue.
ChoiceSetOfSets & getChoices()
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
static CNormalFraction * normAndSimplifyReptdly(const CEvaluationTree *tree0, unsigned int depth=0)
const std::string & getObjectName() const
CEvaluationNode * copyNode(CEvaluationNode *child1, CEvaluationNode *child2) const
static void cleanSetOfSets(TemplateSetOfSets< TYPE > &s)
virtual size_t size() const
const CNormalFraction & getTrueExpression() const
ASTNode * replace_COTH(const ASTNode *pChild)
CNormalFraction & getLeft()
iterator begin()
bool setName(const std::string &name)
Definition: CNormalItem.cpp:62
ASTNode * expand_function_call(const ASTNode *pCall, const ListOfFunctionDefinitions *pFunctions)
CNormalFraction & getLeft()
bool are_equal(const CNormalFraction *pLHS, const CNormalFraction *pRHS)
const CNormalLogical & getCondition() const
ASTNode * replace_variable_names(const ASTNode *pNode, const std::map< std::string, const ASTNode * > &argumentMap)
Definition: CMetab.h:178
ASTNode * replace_ARCCSCH(const ASTNode *pChild)
ASTNode * replace_SEC(const ASTNode *pChild)
static CEvaluationNode * fromAST(const ASTNode *pASTNode)
ASTNode * replace_CSCH(const ASTNode *pChild)
ASTNode * replace_ARCSECH(const ASTNode *pChild)
const CNormalFraction & getFalseExpression() const
ASTNode * replace_COSH(const ASTNode *pChild)
const CCopasiVector< CChemEqElement > & getProducts() const
Definition: CChemEq.cpp:63
const std::set< CNormalFraction * > & getFractions() const
Definition: CNormalSum.cpp:425
iterator end()
const Type & getType() const
Definition: CNormalItem.cpp:91
virtual const Data & getData() const
bool isReference() const
CNormalFraction * create_simplified_normalform(const ASTNode *pSource)
void setAndSets(const ItemSetOfSets &set)
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
CNormalSum & getDenominator()
const bool & getReversibility() const
Definition: CChemEq.cpp:77
const std::set< CNormalItemPower *, compareItemPowers > & getItemPowers() const
bool contains_necessary_mass_action_elements(const CCopasiVector< CChemEqElement > &elements, const CNormalProduct *pProduct, const CModel *pModel)
void setChoices(const ChoiceSetOfSets &set)
CNormalFraction & getRight()
const CCopasiVector< CChemEqElement > & getSubstrates() const
Definition: CChemEq.cpp:60
void setFractions(const std::set< CNormalFraction * > &set)
Definition: CNormalSum.cpp:603
ASTNode * replace_TANH(const ASTNode *pChild)
const CArrayAnnotation * pResult
virtual void remove(const size_t &index)
bool is_mass_action(const CNormalFraction *pFrac, const CModel *pModel, const CChemEq *pChemEq)
bool checkDenominatorOne() const
ASTNode * replace_SECH(const ASTNode *pChild)
ASTNode * replace_SINH(const ASTNode *pChild)
void setItemPowers(const std::set< CNormalItemPower *, compareItemPowers > &set)
static ASTNode * shallowCopy(const ASTNode *pOrig)
ASTNode * create_expression(const ASTNode *pSource, const ListOfFunctionDefinitions *pFunctions)
CNormalFraction * createNormalRepresentation(const CEvaluationNode *node)
#define C_FLOAT64
Definition: copasi.h:92
ASTNode * replace_ARCCOSH(const ASTNode *pChild)
void setProducts(const std::set< CNormalProduct *, compareProducts > &set)
Definition: CNormalSum.cpp:583
The class for handling a chemical kinetic function.
Definition: CFunction.h:29
CNormalBase & getItem()
Definition: CModel.h:50
const std::string getName() const
Definition: CNormalItem.cpp:82
virtual const Data & getData() const
Definition: CCopasiNode.h:118
ASTNode * replace_CSC(const ASTNode *pChild)
CNormalFraction * create_normalform(const ASTNode *pSource)
ASTNode * expand_function_calls(const ASTNode *pNode, const ListOfFunctionDefinitions *pFunctions)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
void normalize_variable_names(CNormalBase *pBase, std::map< std::string, std::string > &variableMap)
CFunction * findFunction(const std::string &functionName)
CCopasiObject * ObjectFromName(const std::vector< CCopasiContainer * > &listOfContainer, const CCopasiObjectName &CN) const
ASTNode * replace_ARCSINH(const ASTNode *pChild)
CEvaluationNode * getRoot()
CNormalFraction & getFraction()
const std::set< CNormalProduct *, compareProducts > & getProducts() const
Definition: CNormalSum.cpp:416
CFunctionParameters & getVariables()
Definition: CFunction.cpp:148
CCopasiContainer * getObjectParent() const
CNormalFraction & getRight()
ItemSetOfSets & getAndSets()