Ejemplo n.º 1
0
def waxman_1_topology(n,
                      alpha=0.4,
                      beta=0.1,
                      L=1.0,
                      distance_unit='Km',
                      seed=None):
    r"""
    Return a Waxman-1 random topology.

    The Waxman-1 random topology models assigns link between nodes with
    probability

    .. math::
            p = \alpha*exp(-d/(\beta*L)).

    where the distance *d* is chosen randomly in *[0,L]*.

    Parameters
    ----------
    n : int
        Number of nodes
    alpha : float
        Model parameter chosen in *(0,1]* (higher alpha increases link density)
    beta : float
        Model parameter chosen in *(0,1]* (higher beta increases difference
        between density of short and long links)
    L : float
        Maximum distance between nodes.
    seed : int, optional
        Seed for random number generator (default=None).

    Returns
    -------
    G : Topology

    Notes
    -----
    Each node of G has the attributes *latitude* and *longitude*. These
    attributes are not expressed in degrees but in *distance_unit*.

    Each edge of G has the attribute *length*, which is also expressed in
    *distance_unit*.

    References
    ----------
    .. [1]  B. M. Waxman, Routing of multipoint connections.
       IEEE J. Select. Areas Commun. 6(9),(1988) 1617-1622.
    """
    # validate input parameters
    if not isinstance(n, int) or n <= 0:
        raise ValueError('n must be a positive integer')
    if alpha > 1 or alpha <= 0 or beta > 1 or beta <= 0:
        raise ValueError('alpha and beta must be float values in (0,1]')
    if L <= 0:
        raise ValueError('L must be a positive number')
    if seed is not None:
        random.seed(seed)

    G = Topology(type='waxman_1', distance_unit=distance_unit)

    G.name = "waxman_1_topology(%s, %s, %s, %s)" % (n, alpha, beta, L)
    G.add_nodes_from(range(n))
    nodes = G.nodes()
    while nodes:
        u = nodes.pop()
        for v in nodes:
            d = L * random.random()
            if random.random() < alpha * math.exp(-d / (beta * L)):
                G.add_edge(u, v, length=d)
    return G
Ejemplo n.º 2
0
def extended_barabasi_albert_topology(n, m, m0, p, q, seed=None):
    r"""
    Return a random topology using the extended Barabasi-Albert preferential
    attachment model.

    Differently from the original Barabasi-Albert model, this model takes into
    account the presence of local events, such as the addition of new links or
    the rewiring of existing links.

    More precisely, the Barabasi-Albert topology is built as follows. First, a
    topology with *m0* isolated nodes is created. Then, at each step:
    with probability *p* add *m* new links between existing nodes, selected
    with probability:

    .. math::
        \Pi(i) = \frac{deg(i) + 1}{\sum_{v \in V} (deg(v) + 1)}

    with probability *q* rewire *m* links. Each link to be rewired is selected as
    follows: a node i is randomly selected and a link is randomly removed from
    it. The node i is then connected to a new node randomly selected with
    probability :math:`\Pi(i)`,
    with probability :math:`1-p-q` add a new node and attach it to m nodes of
    the existing topology selected with probability :math:`\Pi(i)`

    Repeat the previous step until the topology comprises n nodes in total.

    Parameters
    ----------
    n : int
        Number of nodes
    m : int
        Number of edges to attach from a new node to existing nodes
    m0 : int
        Number of edges initially attached to the network
    p : float
        The probability that new links are added
    q : float
        The probability that existing links are rewired
    seed : int, optional
        Seed for random number generator (default=None).

    Returns
    -------
    G : Topology

    References
    ----------
    .. [1] A. L. Barabasi and R. Albert "Topology of evolving networks: local
       events and universality", Physical Review Letters 85(24), 2000.
    """
    def calc_pi(G):
        """Calculate extended-BA Pi function for all nodes of the graph"""
        degree = G.degree()
        den = float(sum(degree.values()) + G.number_of_nodes())
        return {node: (degree[node] + 1) / den for node in G.nodes_iter()}

    # input parameters
    if n < 1 or m < 1 or m0 < 1:
        raise ValueError('n, m and m0 must be a positive integer')
    if m >= m0:
        raise ValueError('m must be <= m0')
    if n < m0:
        raise ValueError('n must be > m0')
    if p > 1 or p < 0:
        raise ValueError('p must be included between 0 and 1')
    if q > 1 or q < 0:
        raise ValueError('q must be included between 0 and 1')
    if p + q > 1:
        raise ValueError('p + q must be <= 1')
    if seed is not None:
        random.seed(seed)
    G = Topology(type='extended_ba')
    G.name = "ext_ba_topology(%d, %d, %d, %f, %f)" % (n, m, m0, p, q)
    # Step 1: Add m0 isolated nodes
    G.add_nodes_from(range(m0))

    while G.number_of_nodes() < n:
        pi = calc_pi(G)
        r = random.random()

        if r <= p:
            # add m new links with probability p
            n_nodes = G.number_of_nodes()
            n_edges = G.number_of_edges()
            max_n_edges = (n_nodes * (n_nodes - 1)) / 2
            if n_edges + m > max_n_edges:  # cannot add m links
                continue  # rewire or add nodes
            new_links = 0
            while new_links < m:
                u = random_from_pdf(pi)
                v = random_from_pdf(pi)
                if u is not v and not G.has_edge(u, v):
                    G.add_edge(u, v)
                    new_links += 1

        elif r > p and r <= p + q:
            # rewire m links with probability q
            rewired_links = 0
            while rewired_links < m:
                i = random.choice(G.nodes())  # pick up node randomly (uniform)
                if len(G.edge[i]) is 0:  # if i has no edges, I cannot rewire
                    break
                j = random.choice(list(
                    G.edge[i].keys()))  # node to be disconnected
                k = random_from_pdf(pi)  # new node to be connected
                if i is not k and j is not k and not G.has_edge(i, k):
                    G.remove_edge(i, j)
                    G.add_edge(i, k)
                    rewired_links += 1
        else:
            # add a new node with probability 1 - p - q
            new_node = G.number_of_nodes()
            G.add_node(new_node)
            new_links = 0
            while new_links < m:
                existing_node = random_from_pdf(pi)
                if not G.has_edge(new_node, existing_node):
                    G.add_edge(new_node, existing_node)
                    new_links += 1
    return G
Ejemplo n.º 3
0
def waxman_2_topology(n,
                      alpha=0.4,
                      beta=0.1,
                      domain=(0, 0, 1, 1),
                      distance_unit='Km',
                      seed=None):
    r"""Return a Waxman-2 random topology.

    The Waxman-2 random topology models place n nodes uniformly at random
    in a rectangular domain. Two nodes u, v are connected with a link
    with probability

    .. math::
            p = \alpha*exp(-d/(\beta*L)).

    where the distance *d* is the Euclidean distance between the nodes u and v.
    and *L* is the maximum distance between all nodes in the graph.


    Parameters
    ----------
    n : int
        Number of nodes
    alpha : float
        Model parameter chosen in *(0,1]* (higher alpha increases link density)
    beta : float
        Model parameter chosen in *(0,1]* (higher beta increases difference
        between density of short and long links)
    domain : tuple of numbers, optional
         Domain size (xmin, ymin, xmax, ymax)
    seed : int, optional
        Seed for random number generator (default=None).

    Returns
    -------
    G : Topology

    Notes
    -----
    Each edge of G has the attribute *length*

    References
    ----------
    .. [1]  B. M. Waxman, Routing of multipoint connections.
       IEEE J. Select. Areas Commun. 6(9),(1988) 1617-1622.
    """
    # validate input parameters
    if not isinstance(n, int) or n <= 0:
        raise ValueError('n must be a positive integer')
    if alpha > 1 or alpha <= 0 or beta > 1 or beta <= 0:
        raise ValueError('alpha and beta must be float values in (0,1]')
    if not isinstance(domain, tuple) or len(domain) != 4:
        raise ValueError('domain must be a tuple of 4 number')
    (xmin, ymin, xmax, ymax) = domain
    if xmin > xmax:
        raise ValueError('In domain, xmin cannot be greater than xmax')
    if ymin > ymax:
        raise ValueError('In domain, ymin cannot be greater than ymax')
    if seed is not None:
        random.seed(seed)

    G = Topology(type='waxman_2', distance_unit=distance_unit)
    G.name = "waxman_2_topology(%s, %s, %s)" % (n, alpha, beta)
    G.add_nodes_from(range(n))

    for v in G.nodes_iter():
        G.node[v]['latitude'] = (ymin + (ymax - ymin)) * random.random()
        G.node[v]['longitude'] = (xmin + (xmax - xmin)) * random.random()

    l = {}
    nodes = G.nodes()
    while nodes:
        u = nodes.pop()
        for v in nodes:
            x_u = G.node[u]['longitude']
            x_v = G.node[v]['longitude']
            y_u = G.node[u]['latitude']
            y_v = G.node[v]['latitude']
            l[(u, v)] = math.sqrt((x_u - x_v)**2 + (y_u - y_v)**2)
    L = max(l.values())
    for (u, v), d in l.items():
        if random.random() < alpha * math.exp(-d / (beta * L)):
            G.add_edge(u, v, length=d)

    return G
Ejemplo n.º 4
0
def waxman_1_topology(n, alpha=0.4, beta=0.1, L=1.0,
                      distance_unit='Km', seed=None):
    r"""
    Return a Waxman-1 random topology.

    The Waxman-1 random topology models assigns link between nodes with
    probability

    .. math::
            p = \alpha*exp(-d/(\beta*L)).

    where the distance *d* is chosen randomly in *[0,L]*.

    Parameters
    ----------
    n : int
        Number of nodes
    alpha : float
        Model parameter chosen in *(0,1]* (higher alpha increases link density)
    beta : float
        Model parameter chosen in *(0,1]* (higher beta increases difference
        between density of short and long links)
    L : float
        Maximum distance between nodes.
    seed : int, optional
        Seed for random number generator (default=None).

    Returns
    -------
    G : Topology

    Notes
    -----
    Each node of G has the attributes *latitude* and *longitude*. These
    attributes are not expressed in degrees but in *distance_unit*.

    Each edge of G has the attribute *length*, which is also expressed in
    *distance_unit*.

    References
    ----------
    .. [1]  B. M. Waxman, Routing of multipoint connections.
       IEEE J. Select. Areas Commun. 6(9),(1988) 1617-1622.
    """
    # validate input parameters
    if not isinstance(n, int) or n <= 0:
        raise ValueError('n must be a positive integer')
    if alpha > 1 or alpha <= 0 or beta > 1 or beta <= 0:
        raise ValueError('alpha and beta must be float values in (0,1]')
    if L <= 0:
        raise ValueError('L must be a positive number')
    if seed is not None:
        random.seed(seed)

    G = Topology(type='waxman_1', distance_unit=distance_unit)

    G.name = "waxman_1_topology(%s, %s, %s, %s)" % (n, alpha, beta, L)
    G.add_nodes_from(range(n))
    nodes = list(G.nodes())
    while nodes:
        u = nodes.pop()
        for v in nodes:
            d = L * random.random()
            if random.random() < alpha * math.exp(-d / (beta * L)):
                G.add_edge(u, v, length=d)
    return G
Ejemplo n.º 5
0
def extended_barabasi_albert_topology(n, m, m0, p, q, seed=None):
    r"""
    Return a random topology using the extended Barabasi-Albert preferential
    attachment model.

    Differently from the original Barabasi-Albert model, this model takes into
    account the presence of local events, such as the addition of new links or
    the rewiring of existing links.

    More precisely, the Barabasi-Albert topology is built as follows. First, a
    topology with *m0* isolated nodes is created. Then, at each step:
    with probability *p* add *m* new links between existing nodes, selected
    with probability:

    .. math::
        \Pi(i) = \frac{deg(i) + 1}{\sum_{v \in V} (deg(v) + 1)}

    with probability *q* rewire *m* links. Each link to be rewired is selected as
    follows: a node i is randomly selected and a link is randomly removed from
    it. The node i is then connected to a new node randomly selected with
    probability :math:`\Pi(i)`,
    with probability :math:`1-p-q` add a new node and attach it to m nodes of
    the existing topology selected with probability :math:`\Pi(i)`

    Repeat the previous step until the topology comprises n nodes in total.

    Parameters
    ----------
    n : int
        Number of nodes
    m : int
        Number of edges to attach from a new node to existing nodes
    m0 : int
        Number of edges initially attached to the network
    p : float
        The probability that new links are added
    q : float
        The probability that existing links are rewired
    seed : int, optional
        Seed for random number generator (default=None).

    Returns
    -------
    G : Topology

    References
    ----------
    .. [1] A. L. Barabasi and R. Albert "Topology of evolving networks: local
       events and universality", Physical Review Letters 85(24), 2000.
    """
    def calc_pi(G):
        """Calculate extended-BA Pi function for all nodes of the graph"""
        degree = dict(G.degree())
        den = float(sum(degree.values()) + G.number_of_nodes())
        return {node: (degree[node] + 1) / den for node in G.nodes()}

    # input parameters
    if n < 1 or m < 1 or m0 < 1:
        raise ValueError('n, m and m0 must be a positive integer')
    if m >= m0:
        raise ValueError('m must be <= m0')
    if n < m0:
        raise ValueError('n must be > m0')
    if p > 1 or p < 0:
        raise ValueError('p must be included between 0 and 1')
    if q > 1 or q < 0:
        raise ValueError('q must be included between 0 and 1')
    if p + q > 1:
        raise ValueError('p + q must be <= 1')
    if seed is not None:
        random.seed(seed)
    G = Topology(type='extended_ba')
    G.name = "ext_ba_topology(%d, %d, %d, %f, %f)" % (n, m, m0, p, q)
    # Step 1: Add m0 isolated nodes
    G.add_nodes_from(range(m0))

    while G.number_of_nodes() < n:
        pi = calc_pi(G)
        r = random.random()

        if r <= p:
            # add m new links with probability p
            n_nodes = G.number_of_nodes()
            n_edges = G.number_of_edges()
            max_n_edges = (n_nodes * (n_nodes - 1)) / 2
            if n_edges + m > max_n_edges:  # cannot add m links
                continue  # rewire or add nodes
            new_links = 0
            while new_links < m:
                u = random_from_pdf(pi)
                v = random_from_pdf(pi)
                if u is not v and not G.has_edge(u, v):
                    G.add_edge(u, v)
                    new_links += 1

        elif r > p and r <= p + q:
            # rewire m links with probability q
            rewired_links = 0
            while rewired_links < m:
                i = random.choice(list(G.nodes()))  # pick up node randomly (uniform)
                if len(G.adj[i]) is 0:  # if i has no edges, I cannot rewire
                    break
                j = random.choice(list(G.adj[i].keys()))  # node to be disconnected
                k = random_from_pdf(pi)  # new node to be connected
                if i is not k and j is not k and not G.has_edge(i, k):
                    G.remove_edge(i, j)
                    G.add_edge(i, k)
                    rewired_links += 1
        else:
            # add a new node with probability 1 - p - q
            new_node = G.number_of_nodes()
            G.add_node(new_node)
            new_links = 0
            while new_links < m:
                existing_node = random_from_pdf(pi)
                if not G.has_edge(new_node, existing_node):
                    G.add_edge(new_node, existing_node)
                    new_links += 1
    return G
Ejemplo n.º 6
0
def waxman_2_topology(n, alpha=0.4, beta=0.1, domain=(0, 0, 1, 1),
                      distance_unit='Km', seed=None):
    r"""Return a Waxman-2 random topology.

    The Waxman-2 random topology models place n nodes uniformly at random
    in a rectangular domain. Two nodes u, v are connected with a link
    with probability

    .. math::
            p = \alpha*exp(-d/(\beta*L)).

    where the distance *d* is the Euclidean distance between the nodes u and v.
    and *L* is the maximum distance between all nodes in the graph.


    Parameters
    ----------
    n : int
        Number of nodes
    alpha : float
        Model parameter chosen in *(0,1]* (higher alpha increases link density)
    beta : float
        Model parameter chosen in *(0,1]* (higher beta increases difference
        between density of short and long links)
    domain : tuple of numbers, optional
         Domain size (xmin, ymin, xmax, ymax)
    seed : int, optional
        Seed for random number generator (default=None).

    Returns
    -------
    G : Topology

    Notes
    -----
    Each edge of G has the attribute *length*

    References
    ----------
    .. [1]  B. M. Waxman, Routing of multipoint connections.
       IEEE J. Select. Areas Commun. 6(9),(1988) 1617-1622.
    """
    # validate input parameters
    if not isinstance(n, int) or n <= 0:
        raise ValueError('n must be a positive integer')
    if alpha > 1 or alpha <= 0 or beta > 1 or beta <= 0:
        raise ValueError('alpha and beta must be float values in (0,1]')
    if not isinstance(domain, tuple) or len(domain) != 4:
        raise ValueError('domain must be a tuple of 4 number')
    (xmin, ymin, xmax, ymax) = domain
    if xmin > xmax:
        raise ValueError('In domain, xmin cannot be greater than xmax')
    if  ymin > ymax:
        raise ValueError('In domain, ymin cannot be greater than ymax')
    if seed is not None:
        random.seed(seed)

    G = Topology(type='waxman_2', distance_unit=distance_unit)
    G.name = "waxman_2_topology(%s, %s, %s)" % (n, alpha, beta)
    G.add_nodes_from(range(n))


    for v in G.nodes():
        G.node[v]['latitude'] = (ymin + (ymax - ymin)) * random.random()
        G.node[v]['longitude'] = (xmin + (xmax - xmin)) * random.random()

    l = {}
    nodes = list(G.nodes())
    while nodes:
        u = nodes.pop()
        for v in nodes:
            x_u = G.node[u]['longitude']
            x_v = G.node[v]['longitude']
            y_u = G.node[u]['latitude']
            y_v = G.node[v]['latitude']
            l[(u, v)] = math.sqrt((x_u - x_v) ** 2 + (y_u - y_v) ** 2)
    L = max(l.values())
    for (u, v), d in l.items():
        if random.random() < alpha * math.exp(-d / (beta * L)):
            G.add_edge(u, v, length=d)

    return G