COPASI API  4.16.103
CMathTrigger.cpp
Go to the documentation of this file.
1 // Copyright (C) 2011 - 2014 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 #include <cmath>
7 
8 #include "copasi.h"
9 
10 #include "CMathTrigger.h"
13 
15  CCopasiContainer("Root", pParent),
16  mRoot("Expression", this),
17  mpRootValue(NULL),
18  mEquality(false),
19  mDiscrete(false),
20  mTrue(0.0),
21  mLastToggleTime(std::numeric_limits< C_FLOAT64 >::quiet_NaN())
22 {
23  initObjects();
24 }
25 
27  const CCopasiContainer * pParent) :
28  CCopasiContainer(src, pParent),
29  mRoot(src.mRoot, this),
30  mpRootValue(NULL),
31  mEquality(src.mEquality),
32  mDiscrete(src.mDiscrete),
33  mTrue(src.mTrue),
34  mLastToggleTime(src.mLastToggleTime)
35 {
36  initObjects();
37 }
38 
40 {}
41 
43 {
44  mpRootValue =
45  (C_FLOAT64 *)mRoot.getObject(std::string("Reference=Value"))->getValuePointer();
46 
47  addDirectDependency(&mRoot);
49 }
50 
51 bool CMathTrigger::CRootFinder::compile(std::vector< CCopasiContainer * > listOfContainer)
52 {
53  bool success = true;
54 
55  success &= mRoot.compile(listOfContainer);
56 
57  return true;
58 }
59 
60 void CMathTrigger::CRootFinder::determineDiscrete(const std::set< const CCopasiObject * > & stateVariables)
61 {
62  mDiscrete = !mRoot.dependsOn(stateVariables);
63 }
64 
66 {
67  return mDiscrete;
68 }
69 
71 {
72  return mEquality;
73 }
74 
76 {
77  return mTrue > 0.5;
78 }
79 
81 {
82  CEvaluationNode * pTrueExpression = NULL;
83 
84  pTrueExpression = new CEvaluationNodeLogical(CEvaluationNodeLogical::GT, "GT");
85  pTrueExpression->addChild(new CEvaluationNodeObject(&mTrue));
86  pTrueExpression->addChild(new CEvaluationNodeNumber(CEvaluationNodeNumber::DOUBLE, "0.5"));
87 
88  return pTrueExpression;
89 }
90 
92  const bool & equality,
93  const bool & continous)
94 {
95  // This function must only be called if we found a root, i.e., the
96  // value of the root expression changes sign. In that case it is save
97  // to toggle the activity.
98 
99  if (continous &&
100  !isnan(mLastToggleTime) &&
101  mLastToggleTime == time)
102  {
103  return;
104  }
105 
106  if (mDiscrete &&
107  equality == true)
108  {
109  mTrue = (mTrue > 0.5) ? 0.0 : 1.0;
110  mLastToggleTime = time;
111  }
112  else if (!mDiscrete)
113  {
114  if (equality == mEquality && mTrue < 0.5)
115  {
116  mTrue = 1.0;
117  mLastToggleTime = time;
118  }
119  else if (equality != mEquality && mTrue > 0.5)
120  {
121  mTrue = 0.0;
122  mLastToggleTime = time;
123  }
124  }
125 
126  return;
127 }
128 
130 {
131  // This function must only be called if we found a root, i.e., the
132  // value of the root expression changes sign. In that case it is save
133  // to toggle the activity.
134 
135  mTrue = (mTrue > 0.5) ? 0.0 : 1.0;
136  mLastToggleTime = time;
137 
138  return;
139 }
140 
142 {
144  mLastToggleTime = std::numeric_limits< C_FLOAT64 >::quiet_NaN();
145 }
146 
148 {
149  if ((*mpRootValue < 0.0) ||
150  ((*mpRootValue <= 0.0) && !mEquality))
151  {
152  mTrue = 0.0;
153  }
154  else
155  {
156  mTrue = 1.0;
157  }
158 }
159 
161 {
162  return mpRootValue;
163 }
164 
166  CCopasiContainer("MathTrigger", pParent, "MathTrigger"),
167  mTrueExpression("TrueExpression", this),
168  mRootFinders("ListOfRoots", this),
170 {}
171 
173  const CCopasiContainer * pParent) :
174  CCopasiContainer(src, pParent),
175  mTrueExpression(src.mTrueExpression, this),
176  mRootFinders(src.mRootFinders, this),
177  mFunctionVariableMap()
178 {}
179 
181 {}
182 
184 {
185  // Calculate the initial truth value for the root finders
188 
189  for (; itRoot != endRoot; ++itRoot)
190  {
191  (*itRoot)->applyInitialValues();
192  }
193 }
194 
196 {
197  // Calculate the current truth value for the root finders
200 
201  for (; itRoot != endRoot; ++itRoot)
202  {
203  (*itRoot)->calculateTrueValue();
204  }
205 }
206 
208 {
209  return mTrueExpression.calcValue() > 0.0;
210 }
211 
212 bool CMathTrigger::compile(const CExpression * pTriggerExpression,
213  std::vector< CCopasiContainer * > listOfContainer)
214 {
215  if (pTriggerExpression == NULL)
216  return false;
217 
218  const CEvaluationNode * pRoot = pTriggerExpression->getRoot();
219 
220  if (pRoot == NULL)
221  return false;
222 
223  // This is a boolean expression thus the root node must be a logical operator.
224  if (!pRoot->isBoolean())
225  return false;
226 
228  mRootFinders.clear();
229 
230  CEvaluationNode * pTrueExpression = NULL;
231 
232  bool success = compile(pRoot, pTrueExpression);
233 
234  // Build the true expression
235  mTrueExpression.setRoot(pTrueExpression);
236  success &= mTrueExpression.compile(listOfContainer);
237 
238  // Compile all root finder
241 
242  for (; it != end; ++it)
243  {
244  success &= (*it)->compile(listOfContainer);
245  }
246 
247  assert(mFunctionVariableMap.empty());
248 
249  return success;
250 }
251 
253 {
254  return mRootFinders;
255 }
256 
258  CEvaluationNode * & pTrueExpression)
259 {
260  bool success = true;
261  const CEvaluationNode::Type & Type = pNode->getType();
262 
263  switch (CEvaluationNode::type(Type))
264  {
266 
267  switch ((int) CEvaluationNode::subType(Type))
268  {
270  success = compileAND(pNode, pTrueExpression);
271  break;
272 
274  success = compileOR(pNode, pTrueExpression);
275  break;
276 
278  success = compileXOR(pNode, pTrueExpression);
279  break;
280 
282  success = compileEQ(pNode, pTrueExpression);
283  break;
284 
286  success = compileNE(pNode, pTrueExpression);
287  break;
288 
290  success = compileLE(pNode, pTrueExpression);
291  break;
292 
294  success = compileLT(pNode, pTrueExpression);
295  break;
296 
298  success = compileGE(pNode, pTrueExpression);
299  break;
300 
302  success = compileGT(pNode, pTrueExpression);
303  break;
304 
305  default:
306  success = false;
307  break;
308  }
309 
310  break;
311 
313 
314  switch ((int) CEvaluationNode::subType(Type))
315  {
317  success = compileNOT(pNode, pTrueExpression);
318  break;
319 
320  default:
321  success = false;
322  break;
323  }
324 
325  break;
326 
328 
329  switch ((int) CEvaluationNode::subType(Type))
330  {
332  success = compileFUNCTION(pNode, pTrueExpression);
333  break;
334 
336  success = compileEXPRESSION(pNode, pTrueExpression);
337  break;
338 
339  default:
340  success = false;
341  break;
342  }
343 
344  break;
345 
347 
348  switch ((int) CEvaluationNode::subType(Type))
349  {
351  success = compileVARIABLE(pNode, pTrueExpression);
352  break;
353 
354  default:
355  success = false;
356  break;
357  }
358 
359  break;
360 
362 
363  switch ((int) CEvaluationNode::subType(Type))
364  {
366  pTrueExpression = new CEvaluationNodeConstant(CEvaluationNodeConstant::TRUE, "TRUE");
367  success = true;
368  break;
369 
371  pTrueExpression = new CEvaluationNodeConstant(CEvaluationNodeConstant::FALSE, "FALSE");
372  success = true;
373  break;
374 
375  default:
376  success = false;
377  break;
378  }
379 
380  break;
381 
382  default:
383  success = false;
384  break;
385  }
386 
387  return success;
388 }
389 
391  CEvaluationNode * & pTrueExpression)
392 {
393  bool success = true;
394 
395  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
396  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
397 
398  CEvaluationNode * pLeftTrueExpression = NULL;
399 
400  success &= compile(pLeft, pLeftTrueExpression);
401 
402  CEvaluationNode * pRightTrueExpression = NULL;
403 
404  success &= compile(pRight, pRightTrueExpression);
405 
406  pTrueExpression = new CEvaluationNodeLogical(CEvaluationNodeLogical::AND, "AND");
407  pTrueExpression->addChild(pLeftTrueExpression);
408  pTrueExpression->addChild(pRightTrueExpression);
409 
410  return success;
411 }
412 
414  CEvaluationNode * & pTrueExpression)
415 {
416  bool success = true;
417 
418  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
419  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
420 
421  CEvaluationNode * pLeftTrueExpression = NULL;
422 
423  success &= compile(pLeft, pLeftTrueExpression);
424 
425  CEvaluationNode * pRightTrueExpression = NULL;
426 
427  success &= compile(pRight, pRightTrueExpression);
428 
429  pTrueExpression = new CEvaluationNodeLogical(CEvaluationNodeLogical::OR, "OR");
430  pTrueExpression->addChild(pLeftTrueExpression);
431  pTrueExpression->addChild(pRightTrueExpression);
432 
433  return success;
434 }
435 
437  CEvaluationNode * & pTrueExpression)
438 {
439  bool success = true;
440 
441  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
442  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
443 
444  CEvaluationNode * pLeftTrueExpression = NULL;
445 
446  success &= compile(pLeft, pLeftTrueExpression);
447 
448  CEvaluationNode * pRightTrueExpression = NULL;
449 
450  success &= compile(pRight, pRightTrueExpression);
451 
452  pTrueExpression = new CEvaluationNodeLogical(CEvaluationNodeLogical::XOR, "XOR");
453  pTrueExpression->addChild(pLeftTrueExpression);
454  pTrueExpression->addChild(pRightTrueExpression);
455 
456  return success;
457 }
458 
460  CEvaluationNode * & pTrueExpression)
461 {
462  bool success = true;
463 
464  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
465  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
466 
467  // Equality can be determined between Boolean and double values.
469  {
470  // We treat x EQ y as (x GE y) AND (y GE x)
471 
472  // Create a temporary expression and compile it.
475  pGE->addChild(copyBranch(pLeft));
476  pGE->addChild(copyBranch(pRight));
477  pAND->addChild(pGE);
478 
480  pGE->addChild(copyBranch(pRight));
481  pGE->addChild(copyBranch(pLeft));
482  pAND->addChild(pGE);
483 
484  success &= compileAND(pAND, pTrueExpression);
485 
486  // Delete the temporary
487  pdelete(pAND);
488  }
489  else
490  {
491  CEvaluationNode * pLeftTrueExpression = NULL;
492 
493  success &= compile(pLeft, pLeftTrueExpression);
494 
495  CEvaluationNode * pRightTrueExpression = NULL;
496 
497  success &= compile(pRight, pRightTrueExpression);
498 
499  pTrueExpression = new CEvaluationNodeLogical(CEvaluationNodeLogical::EQ, "EQ");
500  pTrueExpression->addChild(pLeftTrueExpression);
501  pTrueExpression->addChild(pRightTrueExpression);
502  }
503 
504  return success;
505 }
506 
508  CEvaluationNode * & pTrueExpression)
509 {
510  bool success = true;
511 
512  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
513  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
514 
515  // We treat this as NOT and EQ.
516  // For this we create a modified copy of the current node.
517 
520  pEqNode->addChild(pLeft->copyBranch());
521  pEqNode->addChild(pRight->copyBranch());
522  pNotNode->addChild(pEqNode);
523 
524  success &= compileNOT(pNotNode, pTrueExpression);
525 
526  // Delete the temporary
527  delete pNotNode;
528 
529  return success;
530 }
531 
533  CEvaluationNode * & pTrueExpression)
534 {
535  bool success = true;
536 
537  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
538  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
539 
540  CEvaluationNode * pNode;
541 
542  // We need to create a root finding structures
544  pNode->addChild(copyBranch(pRight));
545  pNode->addChild(copyBranch(pLeft));
546 
547  CRootFinder * pRootFinder = new CRootFinder();
548  pRootFinder->mRoot.setRoot(pNode);
549  pRootFinder->mEquality = true;
550  mRootFinders.add(pRootFinder, true);
551 
552  pTrueExpression = pRootFinder->getTrueExpression();
553 
554  return success;
555 }
556 
558  CEvaluationNode * & pTrueExpression)
559 {
560  bool success = true;
561 
562  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
563  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
564 
565  CEvaluationNode * pNode;
566 
567  // We need to create a root finding structures
569  pNode->addChild(copyBranch(pRight));
570  pNode->addChild(copyBranch(pLeft));
571 
572  CRootFinder * pRootFinder = new CRootFinder();
573  pRootFinder->mRoot.setRoot(pNode);
574  pRootFinder->mEquality = false;
575  mRootFinders.add(pRootFinder, true);
576 
577  pTrueExpression = pRootFinder->getTrueExpression();
578 
579  return success;
580 }
581 
583  CEvaluationNode * & pTrueExpression)
584 {
585  bool success = true;
586 
587  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
588  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
589 
590  CEvaluationNode * pNode;
591 
592  // We need to create a root finding structures
594  pNode->addChild(copyBranch(pLeft));
595  pNode->addChild(copyBranch(pRight));
596 
597  CRootFinder * pRootFinder = new CRootFinder();
598  pRootFinder->mRoot.setRoot(pNode);
599  pRootFinder->mEquality = true;
600  mRootFinders.add(pRootFinder, true);
601 
602  pTrueExpression = pRootFinder->getTrueExpression();
603 
604  return success;
605 }
606 
608  CEvaluationNode * & pTrueExpression)
609 {
610  bool success = true;
611 
612  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
613  const CEvaluationNode * pRight = static_cast<const CEvaluationNode *>(pLeft->getSibling());
614 
615  CEvaluationNode * pNode;
616 
617  // We need to create a root finding structures
619  pNode->addChild(copyBranch(pLeft));
620  pNode->addChild(copyBranch(pRight));
621 
622  CRootFinder * pRootFinder = new CRootFinder();
623  pRootFinder->mRoot.setRoot(pNode);
624  pRootFinder->mEquality = false;
625  mRootFinders.add(pRootFinder, true);
626 
627  pTrueExpression = pRootFinder->getTrueExpression();
628 
629  return success;
630 }
631 
633  CEvaluationNode * & pTrueExpression)
634 {
635  bool success = true;
636 
637  const CEvaluationNode * pLeft = static_cast<const CEvaluationNode *>(pSource->getChild());
638 
639  CEvaluationNode * pLeftTrueExpression = NULL;
640 
641  success &= compile(pLeft, pLeftTrueExpression);
642 
643  pTrueExpression = new CEvaluationNodeFunction(CEvaluationNodeFunction::NOT, "NOT");
644  pTrueExpression->addChild(pLeftTrueExpression);
645 
646  return success;
647 }
648 
650  CEvaluationNode * & pTrueExpression)
651 {
652  if (!pSource->isBoolean())
653  return false;
654 
655  const CEvaluationNodeCall * pSrc =
656  static_cast< const CEvaluationNodeCall * >(pSource);
657 
658  std::vector< const CEvaluationNode * > Variables;
659 
660  const CEvaluationNode * pChild =
661  static_cast< const CEvaluationNode * >(pSrc->getChild());
662 
663  while (pChild != NULL)
664  {
665  Variables.push_back(pChild);
666  pChild = static_cast< const CEvaluationNode * >(pChild->getSibling());
667  }
668 
669  mFunctionVariableMap.push(Variables);
670 
671  const CEvaluationNode * pNode = pSrc->getCalledTree()->getRoot();
672 
673  bool success = compile(pNode, pTrueExpression);
674 
675  mFunctionVariableMap.pop();
676 
677  return success;
678 }
679 
681  CEvaluationNode * & pTrueExpression)
682 {
683  if (!pSource->isBoolean())
684  return false;
685 
686  const CEvaluationNode * pNode =
687  static_cast< const CEvaluationNodeCall * >(pSource)->getCalledTree()->getRoot();
688 
689  return compile(pNode, pTrueExpression);
690 }
691 
693  CEvaluationNode * & pTrueExpression)
694 {
695  assert(!mFunctionVariableMap.empty());
696 
697  size_t Index =
698  static_cast< const CEvaluationNodeVariable * >(pSource)->getIndex();
699 
700  const CEvaluationNode * pNode = mFunctionVariableMap.top()[Index];
701 
702  if (!pNode->isBoolean())
703  return false;
704 
705  return compile(pNode, pTrueExpression);
706 }
707 
709 {
710  if (pSource->getType() == CEvaluationNode::VARIABLE)
711  {
712  if (!mFunctionVariableMap.empty())
713  {
714  size_t Index = static_cast< const CEvaluationNodeVariable * >(pSource)->getIndex();
715 
716  if (Index != C_INVALID_INDEX &&
717  Index < mFunctionVariableMap.top().size())
718  {
719  return mFunctionVariableMap.top()[Index]->copyBranch();
720  }
721  }
722 
723  // We have an invalid variables and therefore create an constant node with the
724  // variable name and value NaN.
726  }
727 
728  return pSource->copyBranch();
729 }
CCopasiVector< CRootFinder > mRootFinders
Definition: CMathTrigger.h:250
virtual bool setRoot(CEvaluationNode *pRootNode)
CEvaluationNode * copyBranch() const
bool compileNE(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
const CEvaluationTree * getCalledTree() const
virtual bool setInfix(const std::string &infix)
Definition: CExpression.cpp:63
void setRefresh(CType *pType, void(CType::*method)(void))
#define pdelete(p)
Definition: copasi.h:215
CCopasiNode< Data > * getSibling()
Definition: CCopasiNode.h:353
bool compile(std::vector< CCopasiContainer * > listOfContainer)
bool compileOR(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
CEvaluationNode * copyBranch(const CEvaluationNode *pSource)
const Type & getType() const
#define C_INVALID_INDEX
Definition: copasi.h:222
virtual bool compile(std::vector< CCopasiContainer * > listOfContainer=CCopasiContainer::EmptyList)
Definition: CExpression.cpp:97
bool compileFUNCTION(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
CExpression mTrueExpression
Definition: CMathTrigger.h:245
bool compileNOT(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
void applyInitialValues()
CEvaluationNode * getTrueExpression() const
const bool & isDiscrete() const
static Type type(const Type &type)
bool compileLT(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
bool compileEXPRESSION(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
void addDirectDependency(const CCopasiObject *pObject)
std::stack< std::vector< const CEvaluationNode * > > mFunctionVariableMap
Definition: CMathTrigger.h:256
bool compileGT(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
bool compileAND(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
virtual const C_FLOAT64 & calcValue()
virtual bool addChild(CCopasiNode< Data > *pChild, CCopasiNode< Data > *pAfter=NULL)
Definition: CCopasiNode.h:156
bool compileLE(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
bool compileGE(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
void determineDiscrete(const std::set< const CCopasiObject * > &stateVariables)
bool compileVARIABLE(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
CRootFinder(const CCopasiContainer *pParent=NULL)
virtual ~CMathTrigger()
void toggle(const C_FLOAT64 &time, const bool &equality, const bool &continous)
static Type subType(const Type &type)
CMathTrigger(const CCopasiContainer *pParent=NULL)
#define C_FLOAT64
Definition: copasi.h:92
virtual bool isBoolean() const
std::vector< CType * >::iterator iterator
Definition: CCopasiVector.h:56
bool compileXOR(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
void calculateTrueValue()
virtual const Data & getData() const
Definition: CCopasiNode.h:118
const bool & isEquality() const
void refresh()
bool compileEQ(const CEvaluationNode *pSource, CEvaluationNode *&pTrueExpression)
CCopasiNode< Data > * getChild()
Definition: CCopasiNode.h:210
CEvaluationNode * getRoot()
bool compile(const CExpression *pTriggerExpression, std::vector< CCopasiContainer * > listOfContainer)
CCopasiVector< CRootFinder > & getRootFinders()