Exemple #1
0
def duplication_divergence_iky(n, s, **kwargs):
	"""
	Generate a random graph using the duplication-divergence model proposed by Ispolatov, Krapivski, and Yuryev (2008).
	
	**Args**:
	
		* ``n`` (int): the target size of the network.
		* ``s`` (float): the probability that a link connected to a newly duplicated node will exist
	
	**KwArgs**:
		* ``directed [=False]`` (boolean): whether to build the graph directed.  If ``True``, then the ``m`` edges created
		  by a node upon its creation are instantiated as out-edges.  All others are in-edges to that node.
		* ``seed [=-1]`` (int): a seed for the random number generator
		* ``graph [=None]`` (:py:class:`zen.Graph` or :py:class:`zen.DiGraph`): this is the actual graph instance to populate. It must be
		  empty and its directionality must agree with the value of ``directed``.
	
	**Returns**:
		:py:class:`zen.Graph` or :py:class:`zen.DiGraph`. The graph generated.  If ``directed = True``, then a :py:class:`DiGraph` will be returned.
	
	.. note::
		Source: I. Ispolatov, P. L. Krapivski, and A. Yuryev "Duplication-divergence model of protein interaction network", ??, 2008.
	"""
	seed = kwargs.pop('seed',None)
	directed = kwargs.pop('directed',False)
	graph = kwargs.pop('graph',None)
	
	if graph is not None:
		if len(graph) > 0:
			raise ZenException, 'the graph must be empty, if provided'
		if graph.is_directed() != directed:
			raise ZenException, 'graph and directed arguments must agree'
	
	if len(kwargs) > 0:
		raise ZenException, 'Unknown arguments: %s' % ', '.join(kwargs.keys())
		
	if seed is None:
		seed = -1
		
	# initialize the random number generator
	if seed >= 0:
		random.seed(seed)
			
	if type(n) != int:
		raise ZenException, 'Parameter n must be an integer'
	if type(s) != float and type(s) != int and type(s) != double:
		print type(s)
		raise ZenException, 'Parameter s must be a float, double, or an int'
		
	G = graph
	if graph is None:
		if directed:
			G = DiGraph()
		else:
			G = Graph()
		
	# initialize the graph with two connected nodes
	G.add_edge(0,1)
		
	# build the rest of the graph
	i = 2
	while i < n:
		
		# pick an existing node to copy
		cn_seed = random.randint(0,100000)
		u = choose_node(G,seed=cn_seed)
		
		#####
		# create the partial copy
		G.add_node(i)
		
		# copy edges
		if not directed:
			for w in G.neighbors(u):
				if random.random() <= s:
					G.add_edge(i,w)
		else:
			for w in G.in_neighbors(u):
				if random.random() <= s:
					G.add_edge(w,i)
			for w in G.out_neighbors(u):
				if random.random() <= s:
					G.add_edge(i,w)
					
		# if the node doesn't have any connections, then ditch it
		if G.degree(i) == 0:
			G.rm_node(i)
		else:
			i += 1
					
	# done!
	return G
Exemple #2
0
def local_attachment(n, m, r, **kwargs):
    """
	Generate a random graph using the local attachment model.
	
	**Args**:
	
		* ``n`` (int): the number of nodes to add to the graph
		* ``m`` (int): the number of edges a new node will add to the graph
		* ``r`` (int): the number of edges (of the ``m``) that a node will add to uniformly selected random nodes.
		  All others will be added to neighbors of the ``r`` selected nodes.
	
	**KwArgs**:
		* ``seed [=-1]`` (int): a seed for the random number generator
		* ``graph [=None]`` (:py:class:`zen.DiGraph`): the graph that will be populated.  If the graph is ``None``, 
		  then a new graph will be created.
	
	**Returns**:
		:py:class:`zen.DiGraph`. The graph generated.
	
	.. note::
		Source: M. O. Jackson and B. O. Rogers "Meeting strangers and friends of friends: How random are social networks?" The American Economic Review, 2007.
	"""
    seed = kwargs.pop('seed', None)
    graph = kwargs.pop('graph', None)

    if graph is not None and not graph.is_directed():
        raise ZenException, 'The graph provided must be directed'
    if graph is not None and len(graph) > 0:
        raise ZenException, 'The graph provided is not empty'

    if len(kwargs) > 0:
        raise ZenException, 'Unknown arguments: %s' % ', '.join(kwargs.keys())

    if type(r) != int:
        raise ZenException, 'r must be an integer'
    elif r < 1:
        raise ZenException, 'r must be 1 or larger'

    if seed is None:
        seed = -1

    if seed >= 0:
        random.seed(seed)

    #####
    # build the initial graph

    G = graph
    if G is None:
        G = DiGraph()

    # populate with nodes
    for i in range(m + 1):
        G.add_node(i)

    # according to Jackson's paper, all initial nodes have m neighbors.
    for i in range(m + 1):
        for j in range(m + 1):
            if j != i:
                G.add_edge(j, i)

    ######
    # Build the rest of the graph
    node_list = list(range(m + 1))
    for i in range(m + 1, n):
        G.add_node(i)

        # pick random neighbors (the parents)
        parents = random.sample(node_list, r)

        # pick neighbors from the parents' neighborhoods
        potentials = set()
        for n in parents:
            potentials.update(G.out_neighbors(n))

        potentials.difference_update(parents)
        nsize = min([m - r, len(potentials)])
        neighbors = random.sample(potentials, nsize)

        # connect
        for v in (parents + neighbors):
            G.add_edge(i, v)

        node_list.append(i)

    # done
    return G
Exemple #3
0
def duplication_divergence_iky(n, s, **kwargs):
    """
	Generate a random graph using the duplication-divergence model proposed by Ispolatov, Krapivski, and Yuryev (2008).
	
	**Args**:
	
		* ``n`` (int): the target size of the network.
		* ``s`` (float): the probability that a link connected to a newly duplicated node will exist
	
	**KwArgs**:
		* ``directed [=False]`` (boolean): whether to build the graph directed.  If ``True``, then the ``m`` edges created
		  by a node upon its creation are instantiated as out-edges.  All others are in-edges to that node.
		* ``seed [=-1]`` (int): a seed for the random number generator
		* ``graph [=None]`` (:py:class:`zen.Graph` or :py:class:`zen.DiGraph`): this is the actual graph instance to populate. It must be
		  empty and its directionality must agree with the value of ``directed``.
	
	**Returns**:
		:py:class:`zen.Graph` or :py:class:`zen.DiGraph`. The graph generated.  If ``directed = True``, then a :py:class:`DiGraph` will be returned.
	
	.. note::
		Source: I. Ispolatov, P. L. Krapivski, and A. Yuryev "Duplication-divergence model of protein interaction network", ??, 2008.
	"""
    seed = kwargs.pop('seed', None)
    directed = kwargs.pop('directed', False)
    graph = kwargs.pop('graph', None)

    if graph is not None:
        if len(graph) > 0:
            raise ZenException, 'the graph must be empty, if provided'
        if graph.is_directed() != directed:
            raise ZenException, 'graph and directed arguments must agree'

    if len(kwargs) > 0:
        raise ZenException, 'Unknown arguments: %s' % ', '.join(kwargs.keys())

    if seed is None:
        seed = -1

    # initialize the random number generator
    if seed >= 0:
        random.seed(seed)

    if type(n) != int:
        raise ZenException, 'Parameter n must be an integer'
    if type(s) != float and type(s) != int and type(s) != double:
        print type(s)
        raise ZenException, 'Parameter s must be a float, double, or an int'

    G = graph
    if graph is None:
        if directed:
            G = DiGraph()
        else:
            G = Graph()

    # initialize the graph with two connected nodes
    G.add_edge(0, 1)

    # build the rest of the graph
    i = 2
    while i < n:

        # pick an existing node to copy
        cn_seed = random.randint(0, 100000)
        u = choose_node(G, seed=cn_seed)

        #####
        # create the partial copy
        G.add_node(i)

        # copy edges
        if not directed:
            for w in G.neighbors(u):
                if random.random() <= s:
                    G.add_edge(i, w)
        else:
            for w in G.in_neighbors(u):
                if random.random() <= s:
                    G.add_edge(w, i)
            for w in G.out_neighbors(u):
                if random.random() <= s:
                    G.add_edge(i, w)

        # if the node doesn't have any connections, then ditch it
        if G.degree(i) == 0:
            G.rm_node(i)
        else:
            i += 1

    # done!
    return G
Exemple #4
0
def local_attachment(n, m, r, **kwargs):
	"""
	Generate a random graph using the local attachment model.
	
	**Args**:
	
		* ``n`` (int): the number of nodes to add to the graph
		* ``m`` (int): the number of edges a new node will add to the graph
		* ``r`` (int): the number of edges (of the ``m``) that a node will add to uniformly selected random nodes.
		  All others will be added to neighbors of the ``r`` selected nodes.
	
	**KwArgs**:
		* ``seed [=-1]`` (int): a seed for the random number generator
		* ``graph [=None]`` (:py:class:`zen.DiGraph`): the graph that will be populated.  If the graph is ``None``, 
		  then a new graph will be created.
	
	**Returns**:
		:py:class:`zen.DiGraph`. The graph generated.
	
	.. note::
		Source: M. O. Jackson and B. O. Rogers "Meeting strangers and friends of friends: How random are social networks?" The American Economic Review, 2007.
	"""
	seed = kwargs.pop('seed',None)
	graph = kwargs.pop('graph',None)
	
	if graph is not None and not graph.is_directed():
		raise ZenException, 'The graph provided must be directed'
	if graph is not None and len(graph) > 0:
		raise ZenException, 'The graph provided is not empty'
	
	if len(kwargs) > 0:
		raise ZenException, 'Unknown arguments: %s' % ', '.join(kwargs.keys())
	
	if type(r) != int:
		raise ZenException, 'r must be an integer'
	elif r < 1:
		raise ZenException, 'r must be 1 or larger'
		
	if seed is None:
		seed = -1
	
	if seed >= 0:
		random.seed(seed)
		
	#####
	# build the initial graph
	
	G = graph
	if G is None:
		G = DiGraph()
	
	# populate with nodes
	for i in range(m+1):
		G.add_node(i)
		
	# according to Jackson's paper, all initial nodes have m neighbors.
	for i in range(m+1):
		for j in range(m+1):
			if j != i:
				G.add_edge(j,i)
			
	######
	# Build the rest of the graph
	node_list = list(range(m+1))
	for i in range(m+1,n):
		G.add_node(i)
		
		# pick random neighbors (the parents)
		parents = random.sample(node_list,r)
		
		# pick neighbors from the parents' neighborhoods
		potentials = set()
		for n in parents:
			potentials.update(G.out_neighbors(n))
			
		potentials.difference_update(parents)
		nsize = min([m-r,len(potentials)])
		neighbors = random.sample(potentials,nsize)
		
		# connect
		for v in (parents + neighbors):
			G.add_edge(i,v)
			
		node_list.append(i)
			
	# done
	return G