COPASI API  4.16.103
CMathDependencyGraph.cpp
Go to the documentation of this file.
1 // Copyright (C) 2011 - 2013 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 <sstream>
7 
8 #include "copasi.h"
9 
10 #include "CMathDependencyGraph.h"
11 #include "CMathDependencyNode.h"
12 #include "CMathObject.h"
13 
17 
19  mObjects2Nodes(),
20  mObject2Index()
21 {}
22 
24 {
25  clear();
26 }
27 
29 {
30  iterator it = mObjects2Nodes.begin();
31  iterator end = mObjects2Nodes.end();
32 
33  for (; it != end; ++it)
34  {
35  delete(it->second);
36  }
37 
38  mObjects2Nodes.clear();
39 }
40 
42 {
43  iterator found = mObjects2Nodes.find(pObject);
44 
45  if (found == mObjects2Nodes.end())
46  {
47  found = mObjects2Nodes.insert(std::make_pair(pObject, new CMathDependencyNode(pObject))).first;
48 
49  const CObjectInterface::ObjectSet & Prerequisites = pObject->getPrerequisites();
50  CObjectInterface::ObjectSet::const_iterator it = Prerequisites.begin();
51  CObjectInterface::ObjectSet::const_iterator end = Prerequisites.end();
52 
53  for (; it != end; ++it)
54  {
55  iterator foundPrerequisite = mObjects2Nodes.find(*it);
56 
57  if (foundPrerequisite == mObjects2Nodes.end())
58  {
59  foundPrerequisite = addObject(*it);
60  }
61 
62  foundPrerequisite->second->addDependent(found->second);
63  found->second->addPrerequisite(foundPrerequisite->second);
64  }
65  }
66 
67  return found;
68 }
69 
71  const CObjectInterface::ObjectSet & changedObjects,
72  const CObjectInterface::ObjectSet & requestedObjects,
73  CObjectInterface::UpdateSequence & updateSequence)
74 {
75 
76  bool success = true;
77 
78  iterator found;
79  iterator notFound = mObjects2Nodes.end();
80 
81  updateSequence.clear();
82 
83  CObjectInterface::ObjectSet::const_iterator it = changedObjects.begin();
84  CObjectInterface::ObjectSet::const_iterator end = changedObjects.end();
85 
86  const_iterator itCheck = mObjects2Nodes.begin();
87  const_iterator endCheck = mObjects2Nodes.end();
88 
89  // Mark all nodes which are changed or need to be calculated
90  for (; it != end && success; ++it)
91  {
92  found = mObjects2Nodes.find(*it);
93 
94  if (found != notFound)
95  {
96  success &= found->second->updateDependentState(context, changedObjects);
97  continue;
98  }
99 
100  success = false;
101  }
102 
103  if (!success) goto finish;
104 
105  it = requestedObjects.begin();
106  end = requestedObjects.end();
107 
108  // Mark all nodes which are requested and its prerequisites.
109  for (; it != end && success; ++it)
110  {
111  found = mObjects2Nodes.find(*it);
112 
113  if (found != notFound)
114  {
115  found->second->setRequested(true);
116  success &= found->second->updatePrerequisiteState(context, changedObjects);
117  continue;
118  }
119 
120  success = false;
121  }
122 
123 #ifdef COPASI_DEBUG_TRACE
124 {
125  std::ofstream GetUpdateSequence("GetUpdateSequence.dot");
126  exportDOTFormat(GetUpdateSequence, "GetUpdateSequence");
127  GetUpdateSequence.close();
128 }
129 #endif //COPASI_DEBUG_TRACE
130 
131  if (!success) goto finish;
132 
133  it = requestedObjects.begin();
134  end = requestedObjects.end();
135 
136  for (; it != end && success; ++it)
137  {
138  found = mObjects2Nodes.find(*it);
139 
140  if (found != notFound)
141  {
142  success &= found->second->buildUpdateSequence(context, updateSequence);
143  continue;
144  }
145 
146  success = false;
147  }
148 
149  if (!success) goto finish;
150 
151  for (; itCheck != endCheck; ++itCheck)
152  {
153  // Reset the dependency nodes for the next call.
154  itCheck->second->setChanged(false);
155  itCheck->second->setRequested(false);
156  }
157 
158 finish:
159 
160  if (!success)
161  {
162  updateSequence.clear();
163 
164  CCopasiMessage(CCopasiMessage::ERROR, MCMathModel + 3, (*it)->getCN().c_str());
165  }
166 
167 #ifdef XXXX
168  CObjectInterface::UpdateSequence::const_iterator itSeq = updateSequence.begin();
169  CObjectInterface::UpdateSequence::const_iterator endSeq = updateSequence.end();
170 
171  std::cout << std::endl << "Start" << std::endl;
172 
173  for (; itSeq != endSeq; ++itSeq)
174  {
175  if (dynamic_cast< const CMathObject * >(*itSeq))
176  {
177  std::cout << *static_cast< const CMathObject * >(*itSeq);
178  }
179  else
180  {
181  std::cout << (*itSeq)->getCN() << std::endl;
182  }
183  }
184 
185  std::cout << "End" << std::endl;
186 #endif //
187 
188  return success;
189 }
190 
191 void CMathDependencyGraph::exportDOTFormat(std::ostream & os, const std::string & name) const
192 {
193  os << "digraph " << name << " {" << std::endl;
194  os << "rankdir=LR;" << std::endl;
195 
196  mObject2Index.clear();
197 
198  const_iterator it = mObjects2Nodes.begin();
199  const_iterator end = mObjects2Nodes.end();
200 
201  for (; it != end; ++it)
202  {
203  const CObjectInterface * pObject = it->second->getObject();
204 
205  const std::vector< CMathDependencyNode * > & Dependents = it->second->getDependents();
206  std::vector< CMathDependencyNode * >::const_iterator itDep = Dependents.begin();
207  std::vector< CMathDependencyNode * >::const_iterator endDep = Dependents.end();
208 
209  for (; itDep != endDep; ++itDep)
210  {
211  os << "\"";
212  os << getDOTNodeId(pObject);
213  os << ((it->second->isChanged()) ? "\\nC" : "\\no");
214  os << ((it->second->isRequested()) ? "R" : "o");
215  os << "\"";
216  os << " -> ";
217  os << "\"";
218  os << getDOTNodeId((*itDep)->getObject());
219  os << (((*itDep)->isChanged()) ? "\\nC" : "\\no");
220  os << (((*itDep)->isRequested()) ? "R" : "o");
221  os << "\"";
222  os << ";" << std::endl;
223  }
224  }
225 
226  os << "}" << std::endl;
227 }
228 
229 // static
230 std::string CMathDependencyGraph::getDOTNodeId(const CObjectInterface * pObject) const
231 {
232  const CCopasiObject * pDataObject = dynamic_cast< const CCopasiObject * >(pObject);
233  const CMathObject * pMathObject = dynamic_cast< const CMathObject * >(pObject);
234 
235  if (pDataObject == NULL && pMathObject == NULL)
236  {
237  return "Invalid Node";
238  }
239 
240  if (pDataObject == NULL)
241  {
242  pDataObject = pMathObject->getDataObject();
243  }
244 
245  if (pDataObject == NULL)
246  {
247  std::ostringstream os;
248 
249  switch (pMathObject->getValueType())
250  {
252  os << "ValueTypeUndefined";
253  break;
254 
255  case CMath::Value:
256  os << "Value";
257  break;
258 
259  case CMath::Rate:
260  os << "ValueRate";
261  break;
262 
263  case CMath::ParticleFlux:
264  os << "ParticleFlux";
265  break;
266 
267  case CMath::Flux:
268  os << "Flux";
269  break;
270 
271  case CMath::Propensity:
272  os << "Propensity";
273  break;
274 
275  case CMath::TotalMass:
276  os << "TotalMass";
277  break;
278 
280  os << "DependentMass";
281  break;
282 
284  os << "Discontinuous";
285  break;
286 
287  case CMath::EventDelay:
288  os << "EventDelay";
289  break;
290 
292  os << "EventPriority";
293  break;
294 
296  os << "EventAssignment";
297  break;
298 
299  case CMath::EventTrigger:
300  os << "EventTrigger";
301  break;
302 
303  case CMath::EventRoot:
304  os << "EventRoot";
305  break;
306 
308  os << "EventRootState";
309  break;
310  }
311 
312  std::map< const CObjectInterface *, size_t >::const_iterator found = mObject2Index.find(pMathObject);
313 
314  if (found != mObject2Index.end())
315  {
316  os << "::" << found->second;
317  }
318  else
319  {
320  os << "::" << mObject2Index.size();
321  mObject2Index[pMathObject] = mObject2Index.size();
322  }
323 
324  return os.str();
325  }
326 
327  return pDataObject->getObjectParent()->getObjectName() + "::" + pDataObject->getObjectName();
328 }
const std::string & getObjectName() const
virtual const CObjectInterface::ObjectSet & getPrerequisites() const =0
NodeMap::iterator iterator
NodeMap::const_iterator const_iterator
#define MCMathModel
bool getUpdateSequence(const CMath::SimulationContextFlag &context, const CObjectInterface::ObjectSet &changedObjects, const CObjectInterface::ObjectSet &requestedObjects, CObjectInterface::UpdateSequence &updateSequence)
void exportDOTFormat(std::ostream &os, const std::string &name) const
Header file of class CCopasiContainer.
std::set< const CObjectInterface * > ObjectSet
iterator addObject(const CObjectInterface *pObject)
virtual const CObjectInterface * getObject(const CCopasiObjectName &cn) const =0
const CMath::ValueType & getValueType() const
std::string getDOTNodeId(const CObjectInterface *pObject) const
CCopasiContainer * getObjectParent() const
std::vector< CObjectInterface * > UpdateSequence
const CCopasiObject * getDataObject() const
std::map< const CObjectInterface *, size_t > mObject2Index