def nextReaction(x, t, stateChangeMat, dependencyGraph, oldRates, jumpTimes, transitionFunc): ''' The next reaction method ''' # smallest time :) index = numpy.argmin(jumpTimes) # moving state and time newX = _updateStateWithJump(x, index, stateChangeMat) t = jumpTimes[index] # recalculate the new transition matrix if hasattr(transitionFunc, '__call__'): rates = transitionFunc(x,t) # update the jump time jumpTimes[index] = t + rexp(1, rates[index]) elif hasattr(transitionFunc, '__iter__'): jumpTimes[index] = t + rexp(1, transitionFunc[index](x, t)) else: raise InputError("transitionFunc should be a callable or a list of callable") # then go through the remaining transitions for i, anew in enumerate(rates): # obviously, not the target transition as we have already fixed it if i != index: # and only if the rate has been affected by the state update if dependencyGraph[i,index] != 0: aold = oldRates[i] if anew > 0: jumpTimes[i] = (aold/anew)*(jumpTimes[i] - t) + t else: jumpTimes[i] = numpy.Inf # done :) return newX, t, True, rates, jumpTimes else: raise SimulationError("Cannot perform any more reactions")
def _newJumpTimes(rates): ''' Generate the new jump times assuming that the rates follow an exponential distribution ''' tau = [rexp(1, r) if r > 0 else numpy.Inf for r in rates] return numpy.array(tau)
def directReaction(x, t, stateChangeMat, transitionFunc, seed=None): ''' The direct reaction method. Same as :func:`firstReaction` for both input and output, only differ in internal computation ''' if seed: seed = np.random.RandomState() rates = transitionFunc(x, t) totalRate = sum(rates) jumpRate = np.cumsum(rates) if totalRate > 0: jumpTime = rexp(1, totalRate, seed=seed) # U \sim \UnifDist[0,1] U = runif(1) targetRate = totalRate * U # find the index that covers the probability of jump using binary search transitionIndex = np.searchsorted(jumpRate, targetRate) # we can move!! move particles newX = _updateStateWithJump(x, transitionIndex, stateChangeMat) return _checkJump(x, newX, t, jumpTime) else: # we can't jump raise SimulationError("Cannot perform any more reactions")
def _newJumpTimes(rates, seed=None): """ Generate the new jump times assuming that the rates follow an exponential distribution """ tau = [rexp(1, r, seed=seed) if r > 0 else np.Inf for r in rates] return np.array(tau)
def nextReaction(x, t, state_change_mat, dependency_graph, old_rates, jump_times, transition_func, seed=None): """ The next reaction method """ # smallest time :) index = np.argmin(jump_times) # moving state and time new_x = _updateStateWithJump(x, index, state_change_mat) t = jump_times[index] # recalculate the new transition matrix if hasattr(transition_func, '__call__'): rates = transition_func(x, t) # update the jump time jump_times[index] = t + rexp(1, rates[index], seed=seed) elif hasattr(transition_func, '__iter__'): rates = transition_func[index](x, t) jump_times[index] = t + rexp(1, rates, seed=seed) else: raise InputError( "transition_func should be a single or list of callable") # then go through the remaining transitions for i, anew in enumerate(rates): # obviously, not the target transition as we have already fixed it if i != index: # and only if the rate has been affected by the state update if dependency_graph[i, index] != 0: aold = old_rates[i] if anew > 0: jump_times[i] = (aold / anew) * (jump_times[i] - t) + t else: jump_times[i] = np.Inf # done :) return new_x, t, True, rates, jump_times else: raise SimulationError("Cannot perform any more reactions")
def directReaction(x, t, stateChangeMat, transitionFunc): ''' The direct reaction method. Same as :func:`firstReaction` for both input and output, only differ in internal computation ''' rates = transitionFunc(x,t) totalRate = sum(rates) jumpRate = numpy.cumsum(rates) if totalRate > 0: jumpTime = rexp(1, totalRate) # U \sim \UnifDist[0,1] U = runif(1) targetRate = totalRate * U # find the index that covers the probability of jump using binary search transitionIndex = numpy.searchsorted(jumpRate, targetRate) # we can move!! move particles newX = _updateStateWithJump(x, transitionIndex, stateChangeMat) return _checkJump(x, newX, t, jumpTime) else: # we can't jump raise SimulationError("Cannot perform any more reactions")
def directReaction(x, t, state_change_mat, transition_func, seed=None): """ The direct reaction method. Same as :func:`firstReaction` for both input and output, only differ in internal computation """ rates = transition_func(x, t) total_rate = sum(rates) jump_rate = np.cumsum(rates) if total_rate > 0: jump_time = rexp(1, total_rate, seed=seed) # U \sim \UnifDist[0,1] u = runif(1) target_rate = total_rate * u # find the index that covers the probability of jump using binary search transition_index = np.searchsorted(jump_rate, target_rate) # we can move!! move particles new_x = _updateStateWithJump(x, transition_index, state_change_mat) return _checkJump(x, new_x, t, jump_time) else: # we can't jump raise SimulationError("Cannot perform any more reactions")