<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Encontro 22
Step1:  Início da Atividade 1
Definindo uma função que gera um grafo aleatório tal que a probabilidade de uma aresta existir é c sobre o número de nós
Step2:  Gerando um grafo passando parâmetros específicos para a função acima.
Step3:  Verificando se a distribuição dos graus de pg segue uma Poisson com média c
Step4:  Calculando variação de clustering coefficient e average distance conforme aumentamos num_nodes
Step5:  Plotando variação de clustering coefficient
Step6:  Plotando variação de average distance
Step7:  Início da Atividade 2
Definindo uma função que gera um grafo circular
Step8:  Calculando variação de clustering coefficient e average distance conforme aumentamos num_nodes
Step9:  Plotando variação de clustering coefficient
Step10:  Plotando variação de average distance
Step11:  Início da Atividade 3
Definindo uma função que gera um grafo híbrido
Step12:  Os próximos gráficos serão para N e C fixos. Por conveniência, vamos repetir a definição.
Step13:  Calculando variação de clustering coefficient e average distance conforme aumentamos p
Step14:  Comparando variação de clustering coefficient com o valor de referência do modelo aleatório.
Em um "pequeno mundo", espera-se um clustering coefficient acima desse valor de referência.
Step15:  Comparando variação de average distance com o valor de referência do modelo circular.
Em um "pequeno mundo", espera-se um average distance abaixo desse valor de referência.
<ASSISTANT_TASK:>
Python Code:
import sys
sys.path.append('..')
import socnet as sn
import matplotlib.pyplot as plt
%matplotlib inline  
Explanation: Encontro 22: Mundos Pequenos
Importando as bibliotecas:
End of explanation
from random import random
def generate_random_graph(num_nodes, c):
    g = sn.generate_empty_graph(num_nodes)
    nodes = list(g.nodes)
    for i in range(num_nodes):
        n = nodes[i]
        for j in range(i + 1, num_nodes):
            m = nodes[j]
            if random() < c / num_nodes:
                g.add_edge(n, m)
    return g
Explanation: Início da Atividade 1
Definindo uma função que gera um grafo aleatório tal que a probabilidade de uma aresta existir é c sobre o número de nós:
End of explanation
N = 100
C = 10
rg = generate_random_graph(N, C)
Explanation: Gerando um grafo passando parâmetros específicos para a função acima.
End of explanation
from scipy.stats import poisson
x = range(N)
plt.hist([rg.degree(n) for n in rg.nodes], x, normed=True)
plt.plot(x, poisson.pmf(C, x));
Explanation: Verificando se a distribuição dos graus de pg segue uma Poisson com média c:
End of explanation
x = []
rcc = []
rad = []
for num_nodes in range(C + 1, N):
    g = generate_random_graph(num_nodes, C)
    x.append(num_nodes)
    rcc.append(sn.average_clustering_coefficient(g))
    rad.append(sn.average_distance(g))
Explanation: Calculando variação de clustering coefficient e average distance conforme aumentamos num_nodes:
End of explanation
plt.plot(x, rcc);
Explanation: Plotando variação de clustering coefficient:
End of explanation
plt.plot(x, rad);
Explanation: Plotando variação de average distance:
End of explanation
def generate_circular_graph(num_nodes, c):
    g = sn.generate_empty_graph(num_nodes)
    nodes = list(g.nodes)
    for i in range(num_nodes):
        n = nodes[i]
        for delta in range(1, c // 2 + 1):
            j = (i + delta) % num_nodes
            m = nodes[j]
            g.add_edge(n, m)
    return g
Explanation: Início da Atividade 2
Definindo uma função que gera um grafo circular:
End of explanation
ccc = []
cad = []
for num_nodes in x:
    g = generate_circular_graph(num_nodes, C)
    ccc.append(sn.average_clustering_coefficient(g))
    cad.append(sn.average_distance(g))
Explanation: Calculando variação de clustering coefficient e average distance conforme aumentamos num_nodes:
End of explanation
plt.plot(x, ccc);
Explanation: Plotando variação de clustering coefficient:
End of explanation
plt.plot(x, cad);
Explanation: Plotando variação de average distance:
End of explanation
from random import choice
def generate_hybrid_graph(num_nodes, c, p):
    g = generate_circular_graph(num_nodes, c)
    for n in g.nodes:
        non_neighbors = set(g.nodes)
        for m in g.neighbors(n):
            non_neighbors.remove(m)
        non_neighbors.remove(n)
        for m in list(g.neighbors(n)):
            if random() < p:
                g.remove_edge(n, m)
                non_neighbors.add(m)
                l = choice(list(non_neighbors))
                non_neighbors.remove(l)
                g.add_edge(n, l)
    return g
Explanation: Início da Atividade 3
Definindo uma função que gera um grafo híbrido:
End of explanation
N = 100
C = 10
Explanation: Os próximos gráficos serão para N e C fixos. Por conveniência, vamos repetir a definição.
End of explanation
x = []
hcc = []
had = []
for ip in range(0, 11):
    p = ip / 10
    g = generate_hybrid_graph(N, C, p)
    x.append(p)
    hcc.append(sn.average_clustering_coefficient(g))
    had.append(sn.average_distance(g))
Explanation: Calculando variação de clustering coefficient e average distance conforme aumentamos p:
End of explanation
plt.plot(x, 11 * [C / N])
plt.plot(x, hcc);
Explanation: Comparando variação de clustering coefficient com o valor de referência do modelo aleatório.
Em um "pequeno mundo", espera-se um clustering coefficient acima desse valor de referência.
End of explanation
plt.plot(x, 11 * [N / (2 * C)])
plt.plot(x, had);
Explanation: Comparando variação de average distance com o valor de referência do modelo circular.
Em um "pequeno mundo", espera-se um average distance abaixo desse valor de referência.
End of explanation
<END_TASK>