bool CCopasiObject::hasCircularDependencies(CCopasiObject::DataObjectSet & candidates, CCopasiObject::DataObjectSet & verified, const CCopasiObject::DataObjectSet & context) const { bool hasCircularDependencies = false; if (verified.count(this) != 0) return hasCircularDependencies; const CCopasiObject::DataObjectSet & DirectDependencies = getDirectDependencies(context); CCopasiObject::DataObjectSet::const_iterator it = DirectDependencies.begin(); CCopasiObject::DataObjectSet::const_iterator end = DirectDependencies.end(); std::pair<CCopasiObject::DataObjectSet::iterator, bool> Inserted; // Dual purpose insert Inserted = candidates.insert(this); // Check whether the insert was successful, if not // the object "this" was among the candidates. Thus we have a detected // a circular dependency if (Inserted.second) { for (; it != end && !hasCircularDependencies; ++it) { hasCircularDependencies = (*it)->hasCircularDependencies(candidates, verified, context); } // Remove the inserted object this from the candidates to avoid any // side effects. candidates.erase(this); } else hasCircularDependencies = true; // The element has been checked and does not need to be checked again. verified.insert(this); return hasCircularDependencies; }
//static std::vector< Refresh * > CCopasiObject::buildUpdateSequence(const CCopasiObject::DataObjectSet & objects, const CCopasiObject::DataObjectSet & uptoDateObjects, const CCopasiObject::DataObjectSet & context) { CCopasiObject::DataObjectSet DependencySet; CCopasiObject::DataObjectSet VerifiedSet; CCopasiObject::DataObjectSet::const_iterator itSet; CCopasiObject::DataObjectSet::const_iterator endSet = objects.end(); std::pair<CCopasiObject::DataObjectSet::iterator, bool> InsertedObject; assert(objects.count(NULL) == 0); // Check whether we have any circular dependencies for (itSet = objects.begin(); itSet != endSet; ++itSet) if ((*itSet)->hasCircularDependencies(DependencySet, VerifiedSet, context)) CCopasiMessage(CCopasiMessage::EXCEPTION, MCObject + 1, (*itSet)->getCN().c_str()); // Build the complete set of dependencies for (itSet = objects.begin(); itSet != endSet; ++itSet) { // At least the object itself needs to be up to date. InsertedObject = DependencySet.insert(*itSet); // Add all its dependencies if (InsertedObject.second) (*itSet)->getAllDependencies(DependencySet, context); } // Remove all objects which do not have any refresh method as they will // be ignored anyway, i.e., no need to sort them. for (itSet = DependencySet.begin(), endSet = DependencySet.end(); itSet != endSet;) if ((*itSet)->getRefresh() == NULL || ((dynamic_cast< const CParticleReference * >(*itSet) != NULL || dynamic_cast< const CConcentrationReference * >(*itSet) != NULL) && (*itSet)->getDirectDependencies(context).size() == 0)) { const CCopasiObject * pObject = *itSet; ++itSet; DependencySet.erase(pObject); } else ++itSet; // Build the list of all up to date objects CCopasiObject::DataObjectSet UpToDateSet; for (itSet = uptoDateObjects.begin(), endSet = uptoDateObjects.end(); itSet != endSet; ++itSet) { // At least the object itself is up to date. InsertedObject = UpToDateSet.insert(*itSet); // Add all its dependencies too if (InsertedObject.second) (*itSet)->getAllDependencies(UpToDateSet, context); } // Now remove all objects in the dependency set which are up to date for (itSet = UpToDateSet.begin(), endSet = UpToDateSet.end(); itSet != endSet; ++itSet) DependencySet.erase(*itSet); // Create a properly sorted list. std::list< const CCopasiObject * > SortedList = sortObjectsByDependency(DependencySet.begin(), DependencySet.end(), context); std::list< const CCopasiObject * >::iterator itList; std::list< const CCopasiObject * >::iterator endList; // Build the vector of pointers to refresh methods Refresh * pRefresh; std::vector< Refresh * > UpdateVector; std::vector< Refresh * >::const_iterator itUpdate; std::vector< Refresh * >::const_iterator endUpdate; itList = SortedList.begin(); endList = SortedList.end(); for (; itList != endList; ++itList) { pRefresh = (*itList)->getRefresh(); itUpdate = UpdateVector.begin(); endUpdate = UpdateVector.end(); while (itUpdate != endUpdate && !(*itUpdate)->isEqual(pRefresh)) ++itUpdate; if (itUpdate == endUpdate) UpdateVector.push_back(pRefresh); } return UpdateVector; }