예제 #1
0
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;
}
예제 #2
0
//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;
}