void CStochNextReactionMethod::updatePriorityQueue(C_INT32 reaction_index, C_FLOAT64 time) { //first the new time for the currently fired reaction C_FLOAT64 new_time = time + generateReactionTime(reaction_index); mPQ.updateNode(reaction_index, new_time); //now the updates for the other reactions (whose propensities may have changed) //if the model contains assignment we use a less efficient loop over all reactions since // we do not know the exact dependencies if (mHasAssignments) { unsigned C_INT32 i; for (i = 0; i < mNumReactions; ++i) { if (i != (unsigned C_INT32)reaction_index) { if (mAmu[i] == mAmuOld[i]) continue; C_FLOAT64 new_time; if (mAmuOld[i] > 0) { new_time = time + (mAmuOld[i] / mAmu[i]) * (mPQ.getKey(i) - time); } else { new_time = time + generateReactionTime(i); } mPQ.updateNode(i, new_time); } } } else { const std::set<unsigned C_INT32> & dep_nodes = mDG.getDependents(reaction_index); std::set<unsigned C_INT32>::const_iterator di; for (di = dep_nodes.begin(); di != dep_nodes.end(); ++di) { if (*di != (unsigned C_INT32) reaction_index) { C_INT32 index = *di; C_FLOAT64 new_time; if (mAmuOld[index] > 0) { new_time = time + (mAmuOld[index] / mAmu[index]) * (mPQ.getKey(index) - time); } else { new_time = time + generateReactionTime(index); } mPQ.updateNode(index, new_time); } } } }
/** * Updates the partitioning of the system depending on the particle * numbers present. */ void CHybridMethod::partitionSystem() { bool StateChange = false; size_t i; std::set <size_t>::iterator it, end; for (i = 0; i < mNumVariableMetabs; i++) { if ((mMetabFlags[i] == LOW) && (mCurrentState[i] >= mUpperStochLimit)) { StateChange = true; mMetabFlags[i] = HIGH; // go through all corresponding reactions and update flags for (it = mMetab2React[i].begin(), end = mMetab2React[i].end(); it != end; it++) { mReactionFlags[*it].mValue--; // if reaction gets deterministic, insert it into the linked list of deterministic reactions if (mReactionFlags[*it].mValue == 0) { insertDeterministicReaction(*it); mPQ.removeStochReaction(*it); } } } if ((mMetabFlags[i] == HIGH) && (mCurrentState[i] < mLowerStochLimit)) { StateChange = true; mMetabFlags[i] = LOW; mCurrentState[i] = floor(mCurrentState[i]); // go through all corresponding reactions and update flags for (it = mMetab2React[i].begin(), end = mMetab2React[i].end(); it != end; it++) { if (mReactionFlags[*it].mValue == 0) { removeDeterministicReaction(*it); /* mPQ.insertStochReaction(*iter, 1234567.8); // juergen: have to beautify this, number has to be the biggest C_FLOAT64 !!! */ const_cast< CMathObject * >(mReactions[*it].getPropensityObject())->calculateValue(); mAmu[*it] = * (C_FLOAT64 *) mReactions[*it].getPropensityObject()->getValuePointer(); mAmuOld[*it] = mAmu[*it]; mPQ.insertStochReaction(*it, *mpContainerStateTime + generateReactionTime(*it)); } mReactionFlags[*it].mValue++; } } } if (StateChange) { stateChange(CMath::State); } return; }
void CStochNextReactionMethod::setupPriorityQueue(C_FLOAT64 start_time) { C_FLOAT64 time; mPQ.clear(); for (unsigned C_INT32 i = 0; i < mpModel->getReactions().size(); i++) { time = start_time + generateReactionTime(i); mPQ.pushPair(i, time); } mPQ.buildHeap(); }
/** * Updates the priority queue. * * @param rIndex A size_t giving the index of the fired reaction (-1, if no * stochastic reaction has fired) * @param time A C_FLOAT64 holding the current time */ void CHybridMethod::updatePriorityQueue(size_t rIndex, C_FLOAT64 time) { C_FLOAT64 newTime; // Update all propensities depending on the current reaction (rIndex) if (rIndex != C_INVALID_INDEX) { mpContainer->applyUpdateSequence(mUpdateSequences[rIndex]); } else { mpContainer->updateSimulatedValues(false); CMathReaction * pReaction = mReactions.array(); CMathReaction * pReactionEnd = pReaction + mReactions.size(); for (; pReaction != pReactionEnd; ++pReaction) { const_cast< CMathObject * >(pReaction->getPropensityObject())->calculateValue(); } } std::vector< CHybridStochFlag >::const_iterator it = mReactionFlags.begin(); std::vector< CHybridStochFlag >::const_iterator end = mReactionFlags.end(); for (; it != end; ++it) { if (it->mpPrev == NULL) // reaction is stochastic! { mAmuOld[it->mIndex] = mAmu[it->mIndex]; mAmu[it->mIndex] = * (C_FLOAT64 *) mReactions[it->mIndex].getPropensityObject()->getValuePointer(); if (it->mIndex != rIndex) updateTauMu(it->mIndex, time); } } // draw new random number and update the reaction just fired if (rIndex != C_INVALID_INDEX && mReactionFlags[rIndex].mpPrev == NULL) { // reaction is stochastic newTime = time + generateReactionTime(rIndex); mPQ.updateNode(rIndex, newTime); } return; }
/** * Sets up the priority queue. * * @param startTime The time at which the simulation starts. */ void CHybridMethod::setupPriorityQueue() { size_t i; C_FLOAT64 time; mPQ.clear(); mPQ.initializeIndexPointer(mReactions.size()); for (i = 0; i < mReactions.size(); i++) { if (mReactionFlags[i].mpPrev == NULL) // Reaction is stochastic! { const_cast< CMathObject * >(mReactions[i].getPropensityObject())->calculateValue(); mAmu[i] = * (C_FLOAT64 *) mReactions[i].getPropensityObject()->getValuePointer(); time = *mpContainerStateTime + generateReactionTime(i); mPQ.insertStochReaction(i, time); } } return; }
/** * Updates the putative reaction time of a stochastic reaction in the * priority queue. The corresponding amu and amu_old must be set prior to * the call of this method. * * @param rIndex A size_t specifying the index of the reaction */ void CHybridMethod::updateTauMu(size_t rIndex, C_FLOAT64 time) { C_FLOAT64 newTime; // One must make sure that the calculation yields reasonable results even in the cases where mAmu=0 or mAmuOld=0 or both =0. Therefore mAmuOld=0 is checked. If mAmuOld equals 0, then a new random number has to be drawn, because tau equals inf and the stoch. information is lost. If both values equal 0, then tau should remain inf and the update of the queue can be skipped! if (mAmuOld[rIndex] == 0.0) { if (mAmu[rIndex] != 0.0) { newTime = time + generateReactionTime(rIndex); mPQ.updateNode(rIndex, newTime); } } else { newTime = time + (mAmuOld[rIndex] / mAmu[rIndex]) * (mPQ.getKey(rIndex) - time); mPQ.updateNode(rIndex, newTime); } return; }