Ejemplo n.º 1
0
def createXi( xi, n, maxiter = 9999 ):
	'''

	Xi = createXi( xi, n )

	In: n is an integer
		xi is a probability distribution on the integers
		(must be able to calculate the probabilities of 
		multiple integers at once),
		OR xi is a vector (list, numpy.ndarray, ...)
		such that sum(xi) = 1,
		maxiter is an integer (default maxiter = 999)
	
	Out: Xi is a random vector such that Xi[i] ~ xi for all i
		and sum(Xi) = n - 1.
		The program crashes if the number of trials exceeds maxiter.

	The algorithm is described in 'Simulating size-constrained
	Galton-Watson trees' by Luc Devroye.

	Note that the algorithm does not necessarily ever stop if the expected
	value of xi is far from 1!

	'''

	# Check if xi is a probability distribution,
	# or else a vector of probabilities.
	if hasattr(xi,'__call__'):
	
		Multinom = lambda m,zeta: graphUtil.multinomial( m, zeta )
	
	else:
	
		Multinom = lambda m,P: np.random.multinomial( m, P )

	
	# Multinomial method, page 8.
	
	trials = 0
	
	while True:
	
		N = Multinom( n, xi )
	
		K = len(N)
	
		trials += 1
	
		# If sum( j*N[j] ) == n-1, then we are done.
		# If not, then we try again.
		if ( np.arange(K) * N ).sum() == n-1:
	
			break
	
		if trials >= maxiter:
	
			raise RuntimeError('Maximum number of trials reached' +\
								' (%d). ' % maxiter +\
								'Try again or choose another' +\
								' probability distribution.')
	

	print '\t%d trials' % trials

	
	# Create a vector with N[j] copies of j
	# for j = 0, ..., K-1 and permute it randomly.
	Xi = np.concatenate([ j * np.ones( N[j] ) for j in range(K) ])
	Xi = np.random.permutation( Xi )

	# Random walk, page 5. 
	
	S = 1	# S_0
	minS = 1
	index = 0

	for t in range( n - 1 ):
		# S_t = S_(t-1) + Xi[t] - 1
		# minS_t = min{r <= t: S_r} = S_index
	
		S = S + Xi[t+1] - 1 # S_(t+1)
	
		if S < minS:
	
			minS = S		#minS_(t+1)

			index = t + 1


	# Rotate Xi such that the random walk ends at 0.
	Xi = np.roll( Xi, -index - 1 )

	return Xi.astype( int )
Ejemplo n.º 2
0
def labelMobileRand( M, odd, parent ):
	'''

	labelMobileRand( M, odd, parent )

	In: M is a mobile.
		odd and parent are vertices in M.
		{odd,parent} is an edge in M.
		odd is of an odd generation (and thus,
		parent is of even generation).
		parent has already been given a label.
	
	Out: All descendants of odd of even generation
		have been given a random label.

	'''

	# The children to be labeled.
	children = graphUtil.childrenOf( odd, M, parent )

	# Make sure that the children get the labels in the correct order.
	children.sort()

	n = len(children)

	if n == 0:
		return

	# Make use of the multinomial method to get labels
	# such that the differences of nearby labels are
	# i.i.d.

	# Maximum number of trials:
	maxiter = 999

	# Probability distribution of jumps + 1:
	xi = lambda k: 0.5 ** ( k + 1. )
	
	
	trials = 0

	while True:
	
		N = graphUtil.multinomial( n + 1, xi )
		
		K = len(N)

		trials += 1
		
		# If sum( (j-1)*N[j] ) == 0, then we are done.
		# If not, try again.
		if ( ( np.arange(K) - 1 ) * N ).sum() == 0:

			break

		if trials >= maxiter:

			raise RuntimeError('Maximum number of trials reached' +\
								' (%d). ' % maxiter +\
								'Try again or choose another' +\
								'probability distribution.')
	

	# Create a vector with N[j] copies of j
	# for j = 0, ..., K-1 and permute it randomly.
	Jumps = np.concatenate([ ( j - 1 ) * np.ones( N[j] ) for j in range(K) ])

	Jumps = np.random.permutation( Jumps ).astype( int )

	# Now, Jumps is a vector of n + 1 independent random variables
	# distributed by f(k) = 0.5^(k+2) for k >= -1 and sum(Jumps) == 0.

	# The labels are determined by the label of odd's parent.
	currentLabel = M.node[parent][ 'label' ]
	
	# Label odd's children.
	for i in range(len( children )):
		
		v = children[i]

		currentLabel =  currentLabel + Jumps[i]
		
		M.node[v][ 'label' ] = currentLabel
		
		# Find all children of v (they are of an odd generation)
		# and label them.
		childrenOf_v = graphUtil.childrenOf( v, M, odd )
		
		for child_v in childrenOf_v:

			labelMobileRand( M, child_v, v )
Ejemplo n.º 3
0
def createXi(xi, n, maxiter=9999):
    '''

	Xi = createXi( xi, n )

	In: n is an integer
		xi is a probability distribution on the integers
		(must be able to calculate the probabilities of
		multiple integers at once),
		OR xi is a vector (list, numpy.ndarray, ...)
		such that sum(xi) = 1,
		maxiter is an integer (default maxiter = 999)

	Out: Xi is a random vector such that Xi[i] ~ xi for all i
		and sum(Xi) = n - 1.
		The program crashes if the number of trials exceeds maxiter.

	The algorithm is described in 'Simulating size-constrained
	Galton-Watson trees' by Luc Devroye.

	Note that the algorithm does not necessarily ever stop if the expected
	value of xi is far from 1!

	'''

    # Check if xi is a probability distribution,
    # or else a vector of probabilities.
    if hasattr(xi, '__call__'):

        Multinom = lambda m, zeta: graphUtil.multinomial(m, zeta)

    else:

        Multinom = lambda m, P: np.random.multinomial(m, P)

    # Multinomial method, page 8.

    trials = 0

    while True:

        N = Multinom(n, xi)

        K = len(N)

        trials += 1

        # If sum( j*N[j] ) == n-1, then we are done.
        # If not, then we try again.
        if (np.arange(K) * N).sum() == n - 1:

            break

        if trials >= maxiter:

            raise RuntimeError('Maximum number of trials reached' +\
                 ' (%d). ' % maxiter +\
                 'Try again or choose another' +\
                 ' probability distribution.')

    print '\t%d trials' % trials

    # Create a vector with N[j] copies of j
    # for j = 0, ..., K-1 and permute it randomly.
    Xi = np.concatenate([j * np.ones(N[j]) for j in range(K)])
    Xi = np.random.permutation(Xi)

    # Random walk, page 5.

    S = 1  # S_0
    minS = 1
    index = 0

    for t in range(n - 1):
        # S_t = S_(t-1) + Xi[t] - 1
        # minS_t = min{r <= t: S_r} = S_index

        S = S + Xi[t + 1] - 1  # S_(t+1)

        if S < minS:

            minS = S  #minS_(t+1)

            index = t + 1

    # Rotate Xi such that the random walk ends at 0.
    Xi = np.roll(Xi, -index - 1)

    return Xi.astype(int)