CCopasiObject::DataObjectSet CMetab::getDeletedObjects() const { CCopasiObject::DataObjectSet Deleted = CModelEntity::getDeletedObjects(); Deleted.insert(mpIConcReference); Deleted.insert(mpConcReference); Deleted.insert(mpConcRateReference); Deleted.insert(mpTTReference); return Deleted; }
// virtual bool CEvent::mustBeDeleted(const CCopasiObject::DataObjectSet & deletedObjects) const { bool MustBeDeleted = false; CCopasiObject::DataObjectSet ChildObjects; if (mpTriggerExpression != NULL) { ChildObjects.insert(mpTriggerExpression); } if (mpDelayExpression != NULL) { ChildObjects.insert(mpDelayExpression); } if (mpPriorityExpression != NULL) { ChildObjects.insert(mpPriorityExpression); } // We need to add all assignment targets and expressions CCopasiVector< CEventAssignment >::const_iterator itAssignment = mAssignments.begin(); CCopasiVector< CEventAssignment >::const_iterator endAssignment = mAssignments.end(); for (; itAssignment != endAssignment; ++itAssignment) { if (itAssignment->getTargetObject() != NULL) { ChildObjects.insert(itAssignment->getTargetObject()); } if (itAssignment->getExpressionPtr() != NULL) { ChildObjects.insert(itAssignment->getExpressionPtr()); } } DataObjectSet::const_iterator it = ChildObjects.begin(); DataObjectSet::const_iterator end = ChildObjects.end(); for (; it != end; ++it) { if ((*it)->mustBeDeleted(deletedObjects)) { MustBeDeleted = true; break; } } return MustBeDeleted; }
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; }
bool CQUnitDM::removeRows(QModelIndexList rows, const QModelIndex&) { if (rows.isEmpty()) return false; assert(CCopasiRootContainer::getDatamodelList()->size() > 0); CCopasiDataModel* pDataModel = &CCopasiRootContainer::getDatamodelList()->operator[](0); assert(pDataModel != NULL); CModel * pModel = pDataModel->getModel(); if (pModel == NULL) return false; // Build the list of pointers to items to be deleted // before actually deleting any item. QList <CUnitDefinition *> pUnitDefQList; QModelIndexList::const_iterator i; CUnitDefinition * pUnitDef; for (i = rows.begin(); i != rows.end(); ++i) { if (!isDefaultRow(*i) && (pUnitDef = &CCopasiRootContainer::getUnitList()->operator[](i->row())) != NULL && pModel->getUnitSymbolUsage(pUnitDef->getSymbol()).empty() && !pUnitDef->isReadOnly())//Don't delete built-ins or used units pUnitDefQList.append(&CCopasiRootContainer::getUnitList()->operator[](i->row())); } for (QList <CUnitDefinition *>::const_iterator j = pUnitDefQList.begin(); j != pUnitDefQList.end(); ++j) { size_t delRow = CCopasiRootContainer::getUnitList()->CCopasiVector< CUnitDefinition >::getIndex(*j); if (delRow != C_INVALID_INDEX) { CCopasiObject::DataObjectSet DeletedObjects; DeletedObjects.insert(*j); QMessageBox::StandardButton choice = CQMessageBox::confirmDelete(NULL, "unit", FROM_UTF8((*j)->getObjectName()), DeletedObjects); if (choice == QMessageBox::Ok) removeRow((int) delRow); } } return true; }
// static bool CCopasiObject::compare(const CCopasiObject * lhs, const CCopasiObject * rhs) { if (lhs != rhs) { CCopasiObject::DataObjectSet Candidates; CCopasiObject::DataObjectSet VerifiedSet; Candidates.insert(lhs); if (rhs->hasCircularDependencies(Candidates, VerifiedSet)) return true; } return false; }
void CMetab::compileIsInitialConcentrationChangeAllowed() { // We check whether changing the initial concentration will lead to circular // dependencies in the system. // These circular dependencies must always involve the initial particle number, i.e., // it suffices to check whether the initial particle number has circular dependencies when the // concentration is changes. CCopasiObject::DataObjectSet Candidates; CCopasiObject::DataObjectSet Verified; CCopasiObject::DataObjectSet Context; Context.insert(this->mpIConcReference); mIsInitialConcentrationChangeAllowed = !mpIValueReference->hasCircularDependencies(Candidates, Verified, Context); return; }
void CCopasiObject::getAllDependencies(CCopasiObject::DataObjectSet & dependencies, const CCopasiObject::DataObjectSet & context) const { 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; for (; it != end; ++it) { // Dual purpose insert Inserted = dependencies.insert(*it); // The direct dependency *it was among the dependencies // we assume also its dependencies have been added already. if (!Inserted.second) continue; // Add all the dependencies of the direct dependency *it. (*it)->getAllDependencies(dependencies, context); } }
//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; }
void CMetab::setStatus(const CModelEntity::Status & status) { Status OldStatus = getStatus(); CModelEntity::setStatus(status); if (status == OldStatus) return; CCopasiObject::DataObjectSet Dependencies; const CCopasiObject * pVolumeReference = NULL; if (mpCompartment) pVolumeReference = mpCompartment->getValueReference(); switch (getStatus()) { case FIXED: break; case ASSIGNMENT: Dependencies.insert(mpConcReference); if (pVolumeReference) Dependencies.insert(pVolumeReference); mpValueReference->setDirectDependencies(Dependencies); mpConcReference->setDirectDependencies(mpExpression->getDirectDependencies()); // The dependencies and refresh of the rate are correct (see CModelEntity::setStatus). mpConcRateReference->setDirectDependencies(mpRateReference->getDirectDependencies()); break; case ODE: mpValueReference->setDirectDependencies(Dependencies); Dependencies.insert(mpValueReference); if (pVolumeReference) Dependencies.insert(pVolumeReference); mpConcReference->setDirectDependencies(Dependencies); Dependencies.clear(); Dependencies.insert(mpConcRateReference); if (pVolumeReference) Dependencies.insert(pVolumeReference); mpRateReference->setDirectDependencies(Dependencies); mpConcRateReference->setDirectDependencies(mpExpression->getDirectDependencies()); break; case REACTIONS: mpValueReference->setDirectDependencies(Dependencies); if (pVolumeReference) Dependencies.insert(pVolumeReference); Dependencies.insert(mpValueReference); mpConcReference->setDirectDependencies(Dependencies); Dependencies.clear(); if (pVolumeReference) Dependencies.insert(pVolumeReference); Dependencies.insert(mpRateReference); mpConcRateReference->setDirectDependencies(Dependencies); break; default: break; } if (mpModel && mpCompartment) refreshConcentration(); }