COPASI API  4.16.103
CFunction.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 - 2015 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 // Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
7 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
8 // and The University of Manchester.
9 // All rights reserved.
10 
11 // Copyright (C) 2002 - 2007 by Pedro Mendes, Virginia Tech Intellectual
12 // Properties, Inc. and EML Research, gGmbH.
13 // All rights reserved.
14 
15 #include <algorithm>
16 
17 #include "copasi.h"
18 
19 #include "CFunction.h"
20 #include "CFunctionDB.h"
21 
23 #include "utilities/copasimathml.h"
24 
25 CFunction::CFunction(const std::string & name,
26  const CCopasiContainer * pParent,
27  const CEvaluationTree::Type & type):
28  CEvaluationTree(name, pParent, type),
29  CAnnotation(),
30  mSBMLId(""),
31  mVariables("Function Parameters", this),
32  mCallParametersBegin(),
33  mReversible(TriUnspecified)
34 {
35  mKey = CCopasiRootContainer::getKeyFactory()->add("Function", this);
36 }
37 
39  const CCopasiContainer * pParent):
40  CEvaluationTree(src, pParent),
41  CAnnotation(src),
42  mSBMLId(src.mSBMLId),
43  mVariables(src.mVariables, this),
44  mCallParametersBegin(src.mCallParametersBegin),
45  mReversible(src.mReversible)
46 {
47  mKey = CCopasiRootContainer::getKeyFactory()->add("Function", this);
48 
50  compile();
51 }
52 
54 {
56 }
57 
58 const std::string & CFunction::getKey() const
59 {
60  return CAnnotation::getKey();
61 }
62 
63 void CFunction::setSBMLId(const std::string& id)
64 {
65  this->mSBMLId = id;
66 }
67 
68 const std::string& CFunction::getSBMLId() const
69 {
70  return this->mSBMLId;
71 }
72 
73 bool CFunction::setInfix(const std::string & infix)
74 {
75  return setInfix(infix, true);
76 }
77 
78 bool CFunction::setInfix(const std::string & infix, bool compile)
79 {
80  if (!CEvaluationTree::setInfix(infix)) return false;
81 
82  if (mpNodeList == NULL) return true;
83 
84  // We need to check that the function does not contain any objects, calls to expression
85  // or delay nodes.
86  std::vector< CEvaluationNode * >::const_iterator it = mpNodeList->begin();
87  std::vector< CEvaluationNode * >::const_iterator end = mpNodeList->end();
88 
89  for (; it != end; ++it)
90  {
91  switch (CEvaluationNode::type((*it)->getType()))
92  {
95  return false;
96  break;
97 
99 
101  {
102  return false;
103  }
104 
105  break;
106 
107  default:
108  break;
109  }
110  }
111 
112  if (!initVariables()) return false;
113 
114  if (compile) compileNodes();
115 
116  return true;
117 }
118 
119 bool CFunction::operator == (const CFunction & rhs) const
120 {
121  if (!(*static_cast< const CEvaluationTree * >(this) == rhs))
122  return false;
123 
124  if (!(*static_cast< const CAnnotation * >(this) == rhs))
125  return false;
126 
127  if (!(mVariables == rhs.mVariables))
128  return false;
129 
130  return true;
131 }
132 
133 size_t CFunction::getVariableIndex(const std::string & name) const
134 {
135  CFunctionParameter::DataType VariableType;
136  return mVariables.findParameterByName(name, VariableType);
137 }
138 
139 const C_FLOAT64 & CFunction::getVariableValue(const size_t & index) const
140 {return *(mCallParametersBegin + index)->value;}
141 
142 void CFunction::setReversible(const TriLogic & reversible)
143 {mReversible = reversible;}
144 
146 {return mReversible;}
147 
149 {return mVariables;}
150 
152 {return mVariables;}
153 
154 bool CFunction::addVariable(const std::string & name,
156  const CFunctionParameter::DataType & type)
157 {return mVariables.add(name, type, usage);}
158 
160 {
161  mCallParametersBegin = callParameters.begin();
162 
163  calculate();
164 
165  return mValue;
166 }
167 
168 bool CFunction::dependsOn(const C_FLOAT64 * parameter,
169  const CCallParameters<C_FLOAT64> & callParameters) const
170 {
172  CCallParameters<C_FLOAT64>::const_iterator end = callParameters.end();
173 
174  while (it != end && parameter != it->value) it++;
175 
176  if (it != end)
177  return true;
178  else
179  return false;
180 }
181 
182 void CFunction::load(CReadConfig & configBuffer,
183  CReadConfig::Mode mode)
184 {
185  // cleanup();
186 
187  C_INT32 Type;
188 
189  mode = CReadConfig::SEARCH;
190  configBuffer.getVariable("User-defined", "C_INT32", &Type, mode);
191 
192  switch (Type)
193  {
194  case 1:
196  break;
197 
198  default:
199  fatalError();
200  break;
201  }
202 
203  configBuffer.getVariable("Reversible", "C_INT32", &mReversible);
204 
205  mode = CReadConfig::SEARCH;
206 
207  std::string tmp;
208  configBuffer.getVariable("FunctionName", "string", &tmp, mode);
209  setObjectName(tmp);
210 
211  configBuffer.getVariable("Description", "string", &tmp);
212  setInfix(tmp);
213 
214  // For older file version the parameters have to be build from information
215  // dependend on the function type. Luckilly, only user defined functions are
216  // the only ones occuring in those files.
217 }
218 
220 {
221  if (mpNodeList == NULL && mInfix != "") return false;
222 
223  CFunctionParameters NewVariables;
224 
225  if (mInfix != "")
226  {
227  //first add all variables to the existing list
228  std::vector< CEvaluationNode * >::iterator it = mpNodeList->begin();
229  std::vector< CEvaluationNode * >::iterator end = mpNodeList->end();
230 
231  for (; it != end; ++it)
232  if (CEvaluationNode::type((*it)->getType()) == CEvaluationNode::VARIABLE)
233  {
234  mVariables.add((*it)->getData(),
237  NewVariables.add((*it)->getData(),
240  }
241  }
242 
243  //now remove all variables that are not in the tree anymore
245  size_t i;
246 
247  for (i = mVariables.size() - 1; i != C_INVALID_INDEX; i--)
250 
251  return true;
252 }
253 
254 bool CFunction::isSuitable(const size_t noSubstrates,
255  const size_t noProducts,
256  const TriLogic reversible)
257 {
258  // A function which in neither restricted to reversible nor to irreversible reactions is always suitable
259  // independent from the number of substrates or products
260  if (isReversible() == TriUnspecified)
261  return true;
262 
263  //first reversibility:
264  if (reversible != isReversible())
265  return false;
266 
267  //check substrates
269  {
270  if (noSubstrates == 0 || noSubstrates == C_INVALID_INDEX)
271  return false;
272  }
273  else //is no vector
274  {
276  noSubstrates != C_INVALID_INDEX)
277  return false;
278  }
279 
280  //check products
281  if (reversible == TriTrue)
282  {
284  {
285  if (noProducts == 0 || noProducts == C_INVALID_INDEX)
286  return false;
287  }
288  else //is no vector
289  {
291  noProducts != C_INVALID_INDEX)
292  return false;
293  }
294  }
295 
296  //no VARIABLE variables allowed for kinetic functions
298  return false;
299 
300  return true;
301 }
302 
303 bool CFunction::completeFunctionList(std::vector< CFunction * > & list,
304  const size_t & added)
305 {
306  unsigned Added = 0;
307 
308  size_t i, imax = list.size();
309  size_t Index;
310 
311  CEvaluationTree * pTree;
312  std::vector< CEvaluationNode * >::const_iterator it;
313  std::vector< CEvaluationNode * >::const_iterator end;
314 
315  CCopasiVectorN< CFunction > & Functions =
317 
318  for (i = (added) ? imax - added : 0; i < imax; i++)
319  {
320  pTree = list[i];
321 
322  for (it = pTree->getNodeList().begin(), end = pTree->getNodeList().end(); it != end; ++it)
323  {
324  if (((*it)->getType() & 0xFF000000) == CEvaluationNode::CALL &&
325  (Index = Functions.getIndex((*it)->getData())) != C_INVALID_INDEX &&
326  list.end() == std::find(list.begin(), list.end(), Functions[Index]))
327  {
328  list.push_back(Functions[Index]);
329  Added++;
330  }
331  }
332  }
333 
334  if (Added)
335  return completeFunctionList(list, Added);
336  else
337  return true;
338 }
339 
340 void CFunction::createListOfParametersForMathML(std::vector<std::vector<std::string> > & env)
341 {
342  size_t i, imax = getVariables().size();
343 
344  env.clear();
345  env.resize(imax);
346 
347  for (i = 0; i < imax; ++i)
348  {
349  env[i].push_back("<mi>" + CMathMl::fixName(getVariables()[i]->getObjectName()) + "</mi>");
350  }
351 }
352 
353 // virtual
354 std::string CFunction::writeMathML(const std::vector< std::vector< std::string > > & variables,
355  bool expand, bool fullExpand) const
356 {
357  std::ostringstream out;
358 
359  if (expand && mpRoot)
360  {
361  bool flag = false; //TODO include check if parentheses are necessary
362 
363  if (flag) out << "<mfenced>" << std::endl;
364 
365  out << mpRoot->buildMMLString(fullExpand, variables);
366 
367  if (flag) out << "</mfenced>" << std::endl;
368  }
369  else //no expand
370  {
371  out << "<mrow>" << std::endl;
372  out << CMathMl::fixName(getObjectName()) << std::endl;
373  out << "<mfenced>" << std::endl;
374 
375  size_t i, imax = variables.size();
376 
377  for (i = 0; i < imax; ++i)
378  {
379  out << variables[i][0] << std::endl;
380  }
381 
382  out << "</mfenced>" << std::endl;
383  out << "</mrow>" << std::endl;
384  }
385 
386  return out.str();
387 }
388 
389 void CFunction::writeMathML(std::ostream & out, size_t l) const
390 {
391  //out << "<math>" << std::endl;
392 
393  out << SPC(l) << "<mrow>" << std::endl;
394  out << SPC(l + 1) << CMathMl::fixName(getObjectName()) << std::endl;
395  out << SPC(l + 1) << "<mfenced>" << std::endl;
396 
397  size_t i, imax = getVariables().size();
398 
399  for (i = 0; i < imax; ++i)
400  {
401  out << SPC(l + 2) << "<mi>" << CMathMl::fixName(getVariables()[i]->getObjectName()) << "</mi>" << std::endl;
402  }
403 
404  out << SPC(l + 1) << "</mfenced>" << std::endl;
405  out << SPC(l) << "</mrow>" << std::endl;
406 
407  //out << "</math>" << std::endl;
408 }
409 
410 std::ostream& operator<<(std::ostream &os, const CFunction & f)
411 {
412  os << "CFunction: " << f.getObjectName() << " ";
413 
414  if (f.mReversible == TriUnspecified)
415  os << "(general)";
416  else if (f.mReversible == TriFalse)
417  os << "(irreversible)";
418  else
419  os << "(reversible)";
420 
421  os << std::endl;
422  os << f.mVariables;
423  os << f.getInfix() << std::endl;
424 
425  return os;
426 }
427 
429 {
430  CFunction* newFunction = new CFunction();
431 
432  //newFunction->mVariables = this->mVariables; //WRONG! only shallow copy!!
433  newFunction->mReversible = this->mReversible;
434 
435  if (this->mpRoot)
436  newFunction->setRoot(this->mpRoot->copyBranch());
437 
438  //newFunction->mInfix = newFunction->mpRoot->getInfix();
439 
440  return newFunction;
441 }
442 
443 #include "CFunctionAnalyzer.h"
444 
445 std::pair<CFunction *, CFunction *> CFunction::splitFunction(const CEvaluationNode * /* node */,
446  const std::string & name1,
447  const std::string & name2) const
448 {
449  if (!this->mpRoot) return std::pair<CFunction *, CFunction *>((CFunction*)NULL, (CFunction*)NULL);
450 
451  if (this->mReversible != TriTrue) return std::pair<CFunction *, CFunction *>((CFunction*)NULL, (CFunction*)NULL);
452 
453  //create 2 new functions
454  CFunction* newFunction1 = new CFunction();
455  newFunction1->setObjectName(name1);
456 
457  CFunction* newFunction2 = new CFunction();
458  newFunction2->setObjectName(name2);
459 
460  //when searching for a split point we need to analyze subtrees. For
461  //doing this a representation of the call parameters in the format
462  //used by CFunctionAnalyzer is needed.
463  std::vector<CFunctionAnalyzer::CValue> callParameters;
464  CFunctionAnalyzer::constructCallParameters(this->getVariables(), callParameters, true);
465  // find the split point
466  const CEvaluationNode* splitnode = this->mpRoot->findTopMinus(callParameters);
467 
468  if (!splitnode) return std::pair<CFunction *, CFunction *>((CFunction*)NULL, (CFunction*)NULL);
469 
470  //create the 2 split trees
471  CEvaluationNode* tmpRoots1 = this->mpRoot->splitBranch(splitnode, true); //left side
472  CEvaluationNode* tmpRoots2 = this->mpRoot->splitBranch(splitnode, false); //right side
473 
474  if (tmpRoots1)
475  newFunction1->setRoot(tmpRoots1);
476 
477  if (tmpRoots2)
478  newFunction2->setRoot(tmpRoots2);
479 
480  newFunction1->mVariables = this->mVariables; //copy the parameter list
481  newFunction1->initVariables(); //remove unused parameters
482  newFunction1->mReversible = TriFalse;
483 
484  newFunction2->mVariables = this->mVariables; //copy the parameter list
485  newFunction2->initVariables(); //remove unused parameters
486  newFunction2->mReversible = TriFalse;
487 
488  //update the roles
489  size_t i, imax;
490 
491  imax = newFunction1->mVariables.size();
492 
493  for (i = 0; i < imax; ++i)
494  {
495  if (newFunction1->mVariables[i]->getUsage() == CFunctionParameter::PRODUCT)
496  newFunction1->mVariables[i]->setUsage(CFunctionParameter::MODIFIER);
497  }
498 
499  imax = newFunction2->mVariables.size();
500 
501  for (i = 0; i < imax; ++i)
502  {
503  if (newFunction2->mVariables[i]->getUsage() == CFunctionParameter::PRODUCT)
504  newFunction2->mVariables[i]->setUsage(CFunctionParameter::SUBSTRATE);
505  else if (newFunction2->mVariables[i]->getUsage() == CFunctionParameter::SUBSTRATE)
506  newFunction2->mVariables[i]->setUsage(CFunctionParameter::MODIFIER);
507  }
508 
509  newFunction1->compile();
510  newFunction2->compile();
511  return std::pair<CFunction *, CFunction *>(newFunction1, newFunction2);
512 }
bool remove(const std::string &key)
void setType(const CEvaluationTree::Type &type)
CCopasiVectorN< CFunction > & loadedFunctions()
virtual bool setRoot(CEvaluationNode *pRootNode)
const_iterator begin() const
const CEvaluationNode * findTopMinus(const std::vector< CFunctionAnalyzer::CValue > &callParameters) const
CEvaluationNode * copyBranch() const
static bool completeFunctionList(std::vector< CFunction * > &list, const size_t &added=0)
Definition: CFunction.cpp:303
virtual bool dependsOn(const C_FLOAT64 *parameter, const CCallParameters< C_FLOAT64 > &callParameters) const
Definition: CFunction.cpp:168
bool operator==(const CFunction &rhs) const
Definition: CFunction.cpp:119
CFunctionParameters mVariables
Definition: CFunction.h:210
std::vector< CEvaluationNode * > * mpNodeList
virtual size_t getVariableIndex(const std::string &name) const
Definition: CFunction.cpp:133
const std::string & getObjectName() const
bool initVariables()
Definition: CFunction.cpp:219
std::ostream & operator<<(std::ostream &os, const CFunction &f)
Definition: CFunction.cpp:410
std::string mSBMLId
Definition: CFunction.h:203
bool isVector(CFunctionParameter::Role role) const
static std::string fixName(const std::string &name)
Definition: copasimathml.h:33
TriLogic
Definition: copasi.h:125
#define fatalError()
size_t findParameterByName(const std::string &name, CFunctionParameter::DataType &dataType) const
size_t getNumberOfParametersByUsage(CFunctionParameter::Role usage) const
bool isSuitable(const size_t noSubstrates, const size_t noProducts, const TriLogic reversible)
Definition: CFunction.cpp:254
#define C_INVALID_INDEX
Definition: copasi.h:222
bool addVariable(const std::string &name, CFunctionParameter::Role usage=CFunctionParameter::VARIABLE, const CFunctionParameter::DataType &type=CFunctionParameter::FLOAT64)
Definition: CFunction.cpp:154
virtual size_t getIndex(const std::string &name) const
std::string mInfix
void setMiriamAnnotation(const std::string &miriamAnnotation, const std::string &newId, const std::string &oldId)
#define C_INT32
Definition: copasi.h:90
virtual bool setInfix(const std::string &infix)
Definition: CFunction.cpp:73
const std::string & getKey() const
Definition: CFunction.cpp:58
const std::string & getMiriamAnnotation() const
void setReversible(const TriLogic &reversible)
Definition: CFunction.cpp:142
static void constructCallParameters(const CFunctionParameters &fp, std::vector< CValue > &callParameters, bool posi)
std::string mKey
Definition: CAnnotation.h:119
static Type type(const Type &type)
void add(const CFunctionParameter &parameter)
#define SPC(level)
const TriLogic & isReversible() const
Definition: CFunction.cpp:145
virtual ~CFunction()
Definition: CFunction.cpp:53
void setSBMLId(const std::string &id)
Definition: CFunction.cpp:63
virtual void load(CReadConfig &configBuffer, CReadConfig::Mode mode=CReadConfig::SEARCH)
Definition: CFunction.cpp:182
std::pair< CFunction *, CFunction * > splitFunction(const CEvaluationNode *node, const std::string &name1, const std::string &name2) const
Definition: CFunction.cpp:445
virtual void writeMathML(std::ostream &out, size_t l=0) const
Definition: CFunction.cpp:389
void remove(const std::string &name)
virtual const C_FLOAT64 & getVariableValue(const size_t &index) const
Definition: CFunction.cpp:139
TriLogic mReversible
Definition: CFunction.h:220
void createListOfParametersForMathML(std::vector< std::vector< std::string > > &env)
Definition: CFunction.cpp:340
std::string add(const std::string &prefix, CCopasiObject *pObject)
static CFunctionDB * getFunctionList()
virtual const C_FLOAT64 & calcValue(const CCallParameters< C_FLOAT64 > &callParameters)
Definition: CFunction.cpp:159
long int flag
Definition: f2c.h:52
std::string buildMMLString(bool expand, const std::vector< std::vector< std::string > > &variables) const
static Type subType(const Type &type)
static CKeyFactory * getKeyFactory()
CFunction(const std::string &name="NoName", const CCopasiContainer *pParent=NULL, const Type &type=Function)
Definition: CFunction.cpp:25
const std::string & getSBMLId() const
Definition: CFunction.cpp:68
CFunction * createCopy() const
Definition: CFunction.cpp:428
#define C_FLOAT64
Definition: copasi.h:92
CCallParameters< C_FLOAT64 >::const_iterator mCallParametersBegin
Definition: CFunction.h:215
virtual bool compile()
The class for handling a chemical kinetic function.
Definition: CFunction.h:29
const_iterator end() const
C_INT32 getVariable(const std::string &name, const std::string &type, void *pout, CReadConfig::Mode mode=CReadConfig::NEXT)
Definition: CReadConfig.cpp:81
bool setObjectName(const std::string &name)
const std::vector< CEvaluationNode * > & getNodeList() const
CEvaluationNode * splitBranch(const CEvaluationNode *splitnode, bool left) const
const std::string & getInfix() const
CFunctionParameters & getVariables()
Definition: CFunction.cpp:148
virtual bool setInfix(const std::string &infix)
virtual const std::string & getKey() const
CEvaluationNode * mpRoot