def from_networkx(G): """ Convert a NetworkX graph into a Zen graph object. In creating the object, the NetworkX node object and node/edge data will be copied over (a shallow copy). **Returns**: The return type depends on the input type. * :py:class:`zen.Graph` if the input graph was a :py:class:`networkx.Graph`. * :py:class:`zen.DiGraph` if the input graph was a :py:class:`networkx.DiGraph`. """ Gdest = None if type(G) == networkx.DiGraph: Gdest = DiGraph() elif type(G) == networkx.Graph: Gdest = Graph() else: raise Exception('Unable to convert graph object type %s' % str(type(G))) # add nodes for n, nd in G.nodes_iter(data=True): Gdest.add_node(n, nd) # add edges for x, y, ed in G.edges_iter(data=True): Gdest.add_edge(x, y, ed) return Gdest
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
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
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
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