Ejemplo n.º 1
0
	def iterate_distributions(self,indices,k):
		""" Iterate a number of distributions k steps from their last iteration.

		This is the core method for iterating distributions to stationarity.

		It will automatically set the stationary distribution if it is previously unknown
		and reached during the iteration.

		indices: list containing indices of distributions to be iterated
		k: number of iterations to perform
		"""
		x = []
		for i in indices:
			x.append(self.get_last_iteration(i))

		# invoke the external method performing the iteration
		y = mkm.iterate_distributions(self.p,numpy.array(x),k)

		for idx, val in enumerate(indices):
			self.add_iteration(val,self.last_iteration_time(val)+k,y[idx,:])

		# did we find the stationary distribution?
		# determine this by checking the defintion of stationarity
		# selecting the number of iterations and the threshold is a numerical task
		if not(self.stationary_distribution_known()):
			for i in indices:
				last = self.get_last_iteration(i)
				last_iterated = mkm.iterate_distributions(self.p,last,100)
				
				# 1e-6 is a good threshold?
				if mkm.relative_error(last,last_iterated) < 1e-6:
					self.sd = last
Ejemplo n.º 2
0
    def iterate_distributions(self, indices, k, tv_tol=0.05):
        """ Iterate a number of distributions k steps from their last iteration.

		This is the core method for iterating distributions to stationarity.

		If the number of distributions is >= 3, it will automatically 
		set the stationary distribution, if unknown and found.

		indices: list containing indices of distributions to be iterated
		k: number of iterations to perform
		"""
        x = []
        for i in indices:
            x.append(self.get_last_iteration(i))

        # invoke the external method performing the iteration
        y = mkm.iterate_distributions(self.p, numpy.array(x), k)

        for idx, val in enumerate(indices):
            self.add_iteration(val,
                               self.last_iteration_time(val) + k, y[idx, :])

        # check if we found the stationary distribution
        if len(indices) >= 3:
            # first check the definition of stationarity for all iterations
            for i in indices:
                last = self.get_last_iteration(i)
                last_iterated = mkm.iterate_distributions(self.p, last, 100)

                # is 1e-6 a good threshold? (however this can never be trusted -> cutoff)
                if mkm.relative_error(last, last_iterated) > 1e-6:
                    return

            # check pairwise distance <= tol
            for i in indices:
                d_i = self.get_last_iteration(i)

                for j in indices:
                    d_j = self.get_last_iteration(j)

                    if mkm.total_variation(d_i, d_j) > tv_tol:
                        return

            # take the arithmetic mean of all iterations as the stationary distribution
            stationary_candidate = numpy.zeros(self.n)

            for i in indices:
                stationary_candidate = stationary_candidate + self.get_last_iteration(
                    i)

            stationary_candidate = stationary_candidate / len(indices)

            self.set_stationary(stationary_candidate)
Ejemplo n.º 3
0
	def iterate_distributions(self,indices,k,tv_tol=0.05):
		""" Iterate a number of distributions k steps from their last iteration.

		This is the core method for iterating distributions to stationarity.

		If the number of distributions is >= 3, it will automatically 
		set the stationary distribution, if unknown and found.

		indices: list containing indices of distributions to be iterated
		k: number of iterations to perform
		"""
		x = []
		for i in indices:
			x.append(self.get_last_iteration(i))

		# invoke the external method performing the iteration
		y = mkm.iterate_distributions(self.p,numpy.array(x),k)

		for idx, val in enumerate(indices):
			self.add_iteration(val,self.last_iteration_time(val)+k,y[idx,:])

		# check if we found the stationary distribution
		if len(indices) >= 3:
			# first check the definition of stationarity for all iterations
			for i in indices:
				last = self.get_last_iteration(i)
				last_iterated = mkm.iterate_distributions(self.p,last,100)
						
				# is 1e-6 a good threshold? (however this can never be trusted -> cutoff)
				if mkm.relative_error(last,last_iterated) > 1e-6:
					return

			# check pairwise distance <= tol
			for i in indices:
				d_i = self.get_last_iteration(i)

				for j in indices:
					d_j = self.get_last_iteration(j)

					if mkm.total_variation(d_i, d_j) > tv_tol:
						return

			# take the arithmetic mean of all iterations as the stationary distribution
			stationary_candidate = numpy.zeros(self.n)

			for i in indices:
				stationary_candidate = stationary_candidate + self.get_last_iteration(i)

			stationary_candidate = stationary_candidate / len(indices)

			self.set_stationary(stationary_candidate)			
Ejemplo n.º 4
0
	def assert_iteration(self,indices,t):
		""" For the distributions given by indices, assert that there exists
		an iteration at time t.

		indices: list with indices of distributions
		t: time 
		"""
		for i in indices:
			t0 = 0

			for t1 in self.get_iteration_times(i):
				if t1 > t0 and t1 <= t:
					t0 = t1

			if t0 != t:
				y = mkm.iterate_distributions(self.p,self.get_iteration(i,t0),t-t0)
				self.add_iteration(i,t,y)
Ejemplo n.º 5
0
    def refine_iterations(self, indices, refine):
        """
		Refine the iterations (that is add iterations in between existing iterations)
		until they meet a certain criterion.

		indices: list containing indices of distributions to be iterated
		
		refine: boolean function of two iterations where a return value of
		'True' means that an additional iteration in between the 
		given iterations is necessary (i.e. refine(t1, iteration1, t2, iteration2))
		"""
        import time

        print "INFO: Refining " + ` len(
            indices
        ) ` + " distribution(s) for a Markov chain with n=" + ` self.get_n(
        ) ` + "."
        print "INFO: For multiple distributions, refinement might take longer than iterating to stationarity."

        # Iterating distributions one after another
        for i in indices:
            t = 0

            while t != self.last_iteration_time(i):
                next_t = self.next_iteration_time(i, t)

                while t + 1 != next_t and refine(t, self.get_iteration(
                        i, t), next_t, self.get_iteration(i, next_t)) == True:

                    k = int((next_t - t) / 2)

                    start = time.time()
                    y = mkm.iterate_distributions(self.p,
                                                  self.get_iteration(i, t), k)
                    seconds = time.time() - start

                    self.add_iteration(i, t + k, y)

                    next_t = self.next_iteration_time(i, t)

                t = next_t
        return

        print "INFO: Done."
Ejemplo n.º 6
0
    def assert_iteration(self, indices, t):
        """ For the distributions given by indices, assert that there exists
		an iteration at time t.

		indices: list with indices of distributions
		t: time 
		"""
        for i in indices:
            t0 = 0

            for t1 in self.get_iteration_times(i):
                if t1 > t0 and t1 <= t:
                    t0 = t1

            if t0 != t:
                y = mkm.iterate_distributions(self.p,
                                              self.get_iteration(i,
                                                                 t0), t - t0)
                self.add_iteration(i, t, y)
Ejemplo n.º 7
0
	def refine_iterations(self,indices,refine):
		"""
		Refine the iterations (that is add iterations in between existing iterations)
		until they meet a certain criterion.

		indices: list containing indices of distributions to be iterated
		
		refine: boolean function of two iterations where a return value of
		'True' means that an additional iteration in between the 
		given iterations is necessary (i.e. refine(t1, iteration1, t2, iteration2))
		"""
		import time

		print "INFO: Refining "+`len(indices)`+" distribution(s) for a Markov chain with n="+`self.get_n()`+"."
		print "INFO: For multiple distributions, refinement might take longer than iterating to stationarity."

		# Iterating distributions one after another
		for i in indices:
			t = 0

			while t != self.last_iteration_time(i):
				next_t = self.next_iteration_time(i,t)

				while t+1 != next_t and refine(t, self.get_iteration(i,t), next_t, self.get_iteration(i,next_t)) == True:

					k = int((next_t-t)/2)

					start = time.time()
					y = mkm.iterate_distributions(self.p,self.get_iteration(i,t),k)
					seconds = time.time() - start

					self.add_iteration(i,t+k,y)
					
					next_t = self.next_iteration_time(i,t)

				t = next_t
		return

		print "INFO: Done."
Ejemplo n.º 8
0
	def refine_iterations(self,indices,refine):
		"""
		Refine the iterations (that is add iterations in between existing iterations)
		until they meet a certain criterion.

		indices: list containing indices of distributions to be iterated
		
		refine: boolean function of two iterations where a return value of
		'True' means that an additional iteration in between the 
		given iterations is necessary
		"""
		import time

		print "INFO: Refining "+`len(indices)`+" distribution(s) for a Markov chain with n="+`self.get_n()`+"."
		print "INFO: Iterating distributions one after another."

		for i in indices:
			t = 0

			while t != self.last_iteration_time(i):
				next_t = self.next_iteration_time(i,t)

				while t+1 != next_t and refine(self.get_iteration(i,t), self.get_iteration(i,next_t)) == True:
					
					k = int((next_t-t)/2)

					start = time.time()
					y = mkm.iterate_distributions(self.p,self.get_iteration(i,t),k)
					seconds = time.time() - start
					print time.strftime("%d %b %H:%M", time.localtime())+": "+`k`+" iteration step(s) completed (that took %(sec).2f seconds)." % {'sec': seconds}

					self.add_iteration(i,t+k,y)
					
					next_t = self.next_iteration_time(i,t)

				t = next_t
		return
Ejemplo n.º 9
0
def test_iteration():
	import numpy, time, random

	N = 10000
	k = 10000
	P = mkm.line_lazy_transition_matrix(N)
	P = P.transpose()
	P = P.tocsr()
	
	# single distribution
	x = mkm.delta_distribution(N,0)
	start = time.time()
	for i in xrange(k):
		x = P.dot(x)
	end = time.time()
	print "Python loop:"
	print end - start 
	print x

	x = mkm.delta_distribution(N,0)
	start = time.time()
	x = mkm.matrix_vector_iteration_local(P,x,k)
	end = time.time()
	print "Python local iteration:"
	print end - start 
	print x

	x = mkm.delta_distribution(N,0)
	start = time.time()
	x = mkm.matrix_vector_iteration_by_processes(P,x,k)
	end = time.time()
	print "Python iterating (multiple processes):"
	print end - start 
	print x

	P = P.transpose()
	x = mkm.delta_distribution(N,0)
	start = time.time()
	x = mkm.iterate_distributions(P,x,k)
	end = time.time()
	print "Generic Python iteration:"
	print end - start 
	print x
	P = P.transpose()

	# multiple distributions
	k = 10000
	nd = 10

	random.seed(0)
	x = mkm.random_delta_distributions(N,nd).transpose()
	start = time.time()
	x = mkm.matrix_vector_iteration_local(P,x,k)
	end = time.time()
	print "Python local iteration:"
	print end - start 
	print x

	random.seed(0)
	x = mkm.random_delta_distributions(N,nd).transpose()
	start = time.time()
	x = mkm.matrix_vector_iteration_by_processes(P,x,k)
	end = time.time()
	print "Python iterating (multiple processes):"
	print end - start 
	print x

	random.seed(0)
	P = P.transpose()
	x = mkm.random_delta_distributions(N,nd)
	start = time.time()
	x = mkm.iterate_distributions(P,x,k).transpose()
	end = time.time()
	print "Generic Python iteration:"
	print end - start 
	print x
	P = P.transpose()