Local Interaction: Animation


In [1]:
from __future__ import division, print_function
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import networkx as nx
from localint import LocalInteraction

In [2]:
def animation(li, init_actions=None, pos='circular', node_size=200,
              node_colors=None, linewidth=2, interval=200, figsize=(16,10)):
    num_actions = li.num_actions

    if node_colors is None:
        node_colors = mpl.rcParams['axes.color_cycle']
    num_colors = len(node_colors)
    if num_colors < num_actions:
        raise ValueError('{0} colors required '.format(num_actions) +
                         '(only {0} provided)'.format(num_colors))

    G = nx.DiGraph(li.adj_matrix)

    if isinstance(pos, dict):
        pos = pos
    else:
        try:
            layout_func = getattr(nx, '{0}_layout'.format(pos))
            pos = layout_func(G)
        except:
            raise ValueError(
                "pos must be a dictionary of node-position pairs, or one of " +
                "{'circular', 'random', 'shell', 'spring', 'spectral'}")

    def get_fig(n):
        for i in range(num_actions):
            nodelist = np.where(li.current_actions == i)[0].tolist()
            nx.draw_networkx_nodes(G, pos, node_size=node_size,
                                   nodelist=nodelist,
                                   node_color=node_colors[i])
        li.play()
        return fig

    li.set_init_actions(init_actions)

    fig = plt.figure(figsize=figsize, facecolor='w')
    nx.draw_networkx_edges(G, pos, alpha=0.5, width=linewidth, arrows=False)
    anim = FuncAnimation(fig, get_fig, interval=interval)
    plt.axis('off')
    plt.show()
    plt.close()

Networks


In [3]:
def draw_graph(graph_dict, figsize=(16,10), node_size=200, linewidth=2):
    fig = plt.figure(figsize=figsize, facecolor='w')
    nx.draw_networkx_nodes(graph_dict['G'], graph_dict['pos'],
                           node_size=node_size, node_color='w')
    nx.draw_networkx_edges(graph_dict['G'], graph_dict['pos'],
                           alpha=0.5, width=linewidth, arrows=False)
    plt.axis('off')
    plt.show()

Circle


In [4]:
N = 100
circle = {}
G = nx.cycle_graph(n=N)
circle['G'] = G
circle['adj_matrix'] = nx.adjacency_matrix(G)
circle['pos'] = nx.circular_layout(G)

In [5]:
draw_graph(circle)

Two-dimensional lattice


In [6]:
N = 100
lattice2d = {}
m, n = 10, 10
G = nx.grid_2d_graph(m, n)
lattice2d['adj_matrix'] = nx.adjacency_matrix(G)
lattice2d['G'] = nx.Graph(lattice2d['adj_matrix'])
lattice2d['pos'] = {}
for i, (x, y) in enumerate(G.nodes_iter()):
    lattice2d[(x, y)] = i 
    lattice2d['pos'][i] = (x/(m-1), y/(n-1))

In [7]:
draw_graph(lattice2d)

Coordination Games


In [8]:
a, b, c, d = 11, 0, 3, 10

In [9]:
coordination_game = np.array([[a, b],
                              [c, d]])

In [10]:
coordination_game


Out[10]:
array([[11,  0],
       [ 3, 10]])

In [11]:
def coordination_game_normalized(q):
    a = np.array([[q, 0  ],
                  [0, 1-q]])
    return a

In [12]:
coordination_game_normalized(0.2)


Out[12]:
array([[ 0.2,  0. ],
       [ 0. ,  0.8]])

In [13]:
node_colors_2 = ['b', 'y']

Circle


In [14]:
li_coor = LocalInteraction(coordination_game, circle['adj_matrix'])

In [15]:
init_actions = np.zeros(li_coor.N, dtype=int)
init_actions[[0, -1]] = 1
animation(li_coor, init_actions=init_actions, pos=circle['pos'],
          node_colors=node_colors_2, interval=100)

Two-dimensional lattice


In [16]:
coor = coordination_game_normalized(0.2)
li_coor = LocalInteraction(coor, lattice2d['adj_matrix'])

In [17]:
# m, n = 10, 10
init_actions = np.zeros(li_coor.N, dtype=int)
for node in [(m//2-i, n//2-j) for i in range(2) for j in range(2)]:
    init_actions[lattice2d[node]] = 1
animation(li_coor, init_actions=init_actions, pos=lattice2d['pos'],
          node_colors=node_colors_2, interval=500)

Bilingual Game


In [18]:
def bilingual_game(e, a=11, b=0, c=3, d=10):
    a = np.array([[a  , a  , b],
                  [a-e, a-e, d-e],
                  [c  , d  , d]])
    return a

In [19]:
bg = bilingual_game(e=0.1)
bg


Out[19]:
array([[ 11. ,  11. ,   0. ],
       [ 10.9,  10.9,   9.9],
       [  3. ,  10. ,  10. ]])

In [20]:
node_colors_3=['b', 'r', 'y']

Circle


In [21]:
li_bg = LocalInteraction(bg, circle['adj_matrix'])

In [22]:
init_actions = np.ones(li_bg.N, dtype=int) * 2
init_actions[[0, 1, -2, -1]] = 0
animation(li_bg, init_actions=init_actions, pos=circle['pos'],
          node_colors=node_colors_3, interval=100)

Two-dimensional lattice


In [23]:
li_bg = LocalInteraction(bg, lattice2d['adj_matrix'])

In [24]:
# m, n = 10, 10
init_actions = np.ones(li_bg.N, dtype=int) * 2
for node in [(m//2-i, n//2-j) for i in range(2) for j in range(2)]:
    init_actions[lattice2d[node]] = 0
animation(li_bg, init_actions=init_actions, pos=lattice2d['pos'],
          node_colors=node_colors_3, interval=500)

Tree versus Ladder

Tree


In [25]:
r = 2
h = 7
N = r**h - 1  # 127
tree = {}
G = nx.balanced_tree(r=r, h=h)
tree['G'] = G
tree['adj_matrix'] = nx.adjacency_matrix(G)
tree['pos'] = nx.spring_layout(G)

In [26]:
draw_graph(tree)

Ladder


In [27]:
N = 128
ladder = {}
G = nx.ladder_graph(n=N//2)
ladder['G'] = G
ladder['adj_matrix'] = nx.adjacency_matrix(G)
ladder['pos'] = {}
for i in range(N//2):
    ladder['pos'][i] = (i/(N-1), 0.4)
    ladder['pos'][N//2+i] = (i/(N-1), 0.6)

In [28]:
draw_graph(ladder)

Coordination game


In [29]:
coor = coordination_game_normalized(0.3)
li_coor_tree = LocalInteraction(coor, tree['adj_matrix'])
li_coor_ladder = LocalInteraction(coor, ladder['adj_matrix'])

Tree


In [30]:
init_actions = np.zeros(li_coor_tree.N, dtype=int)
init_actions[[0, 1, 2]] = 1
animation(li_coor_tree, init_actions=init_actions, pos=tree['pos'],
          node_colors=node_colors_2, interval=500)

Ladder


In [31]:
init_actions = np.zeros(li_coor_ladder.N, dtype=int)
init_actions[[li_coor_ladder.N//4, li_coor_ladder.N*3//4]] = 1
animation(li_coor_ladder, init_actions=init_actions, pos=ladder['pos'],
          node_colors=node_colors_2, interval=200)

Bilingual game


In [32]:
bg = bilingual_game(e=3.1)
bg


Out[32]:
array([[ 11. ,  11. ,   0. ],
       [  7.9,   7.9,   6.9],
       [  3. ,  10. ,  10. ]])

In [33]:
li_bg_tree = LocalInteraction(bg, tree['adj_matrix'])
li_bg_ladder = LocalInteraction(bg, ladder['adj_matrix'])

In [34]:
action_dists = [(2, 1, 0), (2, 0, 1), (1, 1, 1)]
for action_dist in action_dists:
    br = li_bg_tree.players[0].best_response(action_dist)
    print('best response to {a}: {b}'.format(a=action_dist, b=br))


best response to (2, 1, 0): 0
best response to (2, 0, 1): 1
best response to (1, 1, 1): 2

Tree


In [35]:
init_actions = np.zeros(li_bg_tree.N, dtype=int) * 0
init_actions[range(0, 31)] = 2
animation(li_bg_tree, init_actions=init_actions, pos=tree['pos'],
          node_colors=node_colors_3, interval=500)

Ladder


In [36]:
init_actions = np.zeros(li_bg_ladder.N, dtype=int)
init_actions[[li_coor_ladder.N*k//4-i for i in range(2) for k in [1, 3]]] = 2
animation(li_bg_ladder, init_actions=init_actions, pos=ladder['pos'],
          node_colors=node_colors_3, interval=200)

Random Networks

Random regular graph


In [37]:
N = 500
d = 3  # Degree
random_regular = {}
G = nx.random_regular_graph(d=d, n=N)
random_regular['G'] = G
random_regular['adj_matrix'] = nx.adjacency_matrix(G)
random_regular['pos'] = nx.random_layout(G)

In [38]:
draw_graph(random_regular)

Coordination game


In [39]:
# coor = coordination_game_normalized(0.3)
li_coor = LocalInteraction(coordination_game, random_regular['adj_matrix'])

In [40]:
init_actions = np.ones(li_coor.N, dtype=int)
init_actions[np.random.randint(li_coor.N, size=150)] = 0
animation(li_coor, init_actions=init_actions, pos=random_regular['pos'],
          linewidth=0.5, node_colors=node_colors_2, interval=300)

Bilingual game


In [41]:
bg = bilingual_game(e=0.1)
li_bg = LocalInteraction(bg, random_regular['adj_matrix'])

In [42]:
init_actions = np.ones(li_bg.N, dtype=int) * 2
init_actions[np.random.randint(li_bg.N, size=1)] = 0
animation(li_bg, init_actions=init_actions, pos=random_regular['pos'],
          linewidth=0.2, node_colors=node_colors_3, interval=300)

Erdos-Renyi graph


In [43]:
N = 250
p=0.1
erdos_reny = {}
G = nx.fast_gnp_random_graph(n=N, p=p)
erdos_reny['G'] = G
erdos_reny['adj_matrix'] = nx.adjacency_matrix(G)
erdos_reny['pos'] = nx.spring_layout(G)

In [44]:
draw_graph(erdos_reny, linewidth=0.2)

Coordination game


In [45]:
li_coor = LocalInteraction(coordination_game, erdos_reny['adj_matrix'])

In [46]:
init_actions = np.ones(li_coor.N, dtype=int)
init_actions[np.random.randint(li_coor.N, size=N//5)] = 0
animation(li_coor, init_actions=init_actions, pos=erdos_reny['pos'],
          linewidth=0.5, node_colors=node_colors_2, interval=300)

Bilingual game


In [47]:
bg = bilingual_game(e=0.1)
li_bg = LocalInteraction(bg, erdos_reny['adj_matrix'])

In [48]:
init_actions = np.ones(li_bg.N, dtype=int) * 2
init_actions[np.random.randint(li_bg.N, size=2)] = 0
animation(li_bg, init_actions=init_actions, pos=erdos_reny['pos'],
          linewidth=0.2, node_colors=node_colors_3, interval=1000)

In [48]: