例3
simple3_123、simple3_45では、定性的な性質を述べるにとどまり、会議の"質"なるものがどのような量に対応するか、また、その質が人数との関係でどのように変化するのかについての理解に欠けていた。ここでは、ネットワークを特徴づける量を実際にいくつか測ってみた例を示すことにする。
%matplotlib inline
import numpy as np
from scipy.spatial.distance import euclidean as euc
import matplotlib.pyplot as plt
import mpld3
from mpld3 import plugins
from mpld3.utils import get_id
class Person:
def __init__(self, S, a, p=0.5):
self.S = S
self.a = a
self.p = p
def gather(self):
"""make person to participate the meeting.
"""
self.ideas = self.has_idea()
def has_idea(self):
"""a person has self.S ideas with self.a dimension.
"""
return list(np.random.rand(self.S, self.a))
def chose_idea(self, idea, idea2=None):
def nearness1(x, y, z):
"""calculate nearness of x for (y, z)
by calculating a linear combination.
"""
alpha = 1.
beta = 1.
return alpha*euc(x, y) + beta*euc(x, z)
def nearness2(x, y, z):
"""calculate nearness of x for (y, z)
by distance between x and the dividing point of (y, z) with t.
"""
# t > 0
# t <= 1: interior division
# t > 1: exterior division
t = 0.5
x, y, z = np.array(x), np.array(y), np.array(z)
return euc(t*(y-x) + (1.-t)*(z-x), (0., 0.))
if len(self.ideas) == 0:
return False
# return min(d) and its idea_id
if idea2 == None:
return min([(euc(vec, idea), idea_id) for idea_id, vec in enumerate(self.ideas)])
else:
return min([(nearness1(vec, idea, idea2), idea_id)
for idea_id, vec in enumerate(self.ideas)])
class Meeting:
"""Simulate a meeting with "simple3" situation.
Give keyword arguments:
K = 20 # Time limit
N = 6 # a number of participants
S = 10 # a number of ideas for each participants
a = 2 # the dimension of an idea
p = 0.5 # probability that a person speak
draw = True # draw image or don't
Output:
self.minutes: list of
( idea(which is vector with a dimension)
, who(person_id in the list "self.membes"))
self.k: stopped time (=len(self.minutes))
"""
def __init__(self, K=20, N=6, S=10, a=2, p=0.5, draw=True, case=2):
self.K = K
self.N = N
self.S = S
self.a = a
self.p = p
self.draw = draw
self.case = case # case in the above cell: 2, 3, 4 or 5
if not self.case in [2, 3, 4, 5]:
raise ValueError
self.members = []
self.minutes = [] # list of (idea, who)
self.k = 0
def gather_people(self):
"""gather people for the meeting.
You can edit what ideas they have in here.
"""
for n in range(self.N):
person = Person(self.S, self.a, self.p)
# person.has_idea = some_function()
# some_function: return list of self.S arrays with dim self.a.
person.gather()
self.members.append(person)
self.members = np.array(self.members)
def progress(self):
"""meeting progress
"""
self.init()
preidea = self.subject
prepreidea = None
self.k = 1
while self.k < self.K + 1:
# l: (distance, speaker, idea_id) list for who can speak
l = []
for person_id, person in enumerate(self.members):
# chosed: (distance, idea_id)
chosed = person.chose_idea(preidea, prepreidea)
if chosed:
l.append((chosed[0], person_id, chosed[1]))
# if no one can speak: meeting ends.
if len(l) == 0:
print "no one can speak."
break
i = np.array([(person_id, idea_id)
for distance, person_id, idea_id in sorted(l)])
for person_id, idea_id in i:
rn = np.random.rand()
if rn < self.members[person_id].p:
idea = self.members[person_id].ideas.pop(idea_id)
self.minutes.append((idea, person_id))
if self.case == 3:
preidea = idea
elif self.case == 4:
prepreidea = idea
elif self.case == 5:
prepreidea = preidea
preidea = idea
self.callback()
self.k += 1
break
else:
self.minutes.append((self.subject, self.N))
self.callback()
self.k += 1
self.after()
def init(self):
self.gather_people()
self.subject = np.random.rand(self.a)
self.minutes.append((self.subject, self.N))
if self.draw:
self.fig = plt.figure(figsize=(9, 9))
self.ax = self.fig.add_subplot(1, 1, 1)
self.labels = ['subject']
self.s1 = [self.ax.scatter(self.subject[0], self.subject[1],
c=next(self.ax._get_lines.color_cycle))]
self.ax.text(
self.subject[0], self.subject[1], '0', fontsize=5)
for i, member in enumerate(self.members):
x = [vec[0] for vec in member.ideas]
y = [vec[1] for vec in member.ideas]
s = self.ax.scatter(
x, y, c=next(self.ax._get_lines.color_cycle), alpha=0.2)
self.labels.append(str(i))
self.s1.append(s)
def callback(self):
if self.draw:
if self.minutes[-1][1] == self.N or self.minutes[-2][1] == self.N:
alpha = 0.2
else:
alpha = 1.0
ix = self.minutes[-2][0][0]
iy = self.minutes[-2][0][1]
jx = self.minutes[-1][0][0]
jy = self.minutes[-1][0][1]
l1 = self.ax.plot([ix, jx], [iy, jy], color='black', alpha=alpha)
self.ax.text(jx, jy, '%d' % self.k, color='blue', fontsize=12)
else:
pass
def after(self):
self.minutes = np.array(self.minutes)
if self.draw:
plugins.connect(
self.fig, plugins.InteractiveLegendPlugin(
self.s1, self.labels, ax=self.ax))
mpld3.enable_notebook()
else:
pass
meeting = Meeting(K=30, N=10, S=50, a=2, p=0.6, case=3)
meeting.progress()
meeting.minutes
[(array([ 0.08324018, 0.93690596]), 6), (array([ 0.06992465, 0.93973707]), 2), (array([ 0.10786115, 0.90576987]), 2), (array([ 0.18599665, 0.93927072]), 5), (array([ 0.04419443, 0.9905022 ]), 0), (array([ 0.08956063, 0.8273196 ]), 2), (array([ 0.11150302, 0.95045983]), 4), (array([ 0.23863643, 0.9425302 ]), 5), (array([ 0.16185867, 0.86186418]), 4), (array([ 0.09953485, 0.81640855]), 4), (array([ 0.1873709 , 0.81761815]), 2), (array([ 0.19859139, 0.80517725]), 0), (array([ 0.02976063, 0.82121825]), 0), (array([ 0.02871757, 0.77728415]), 0), (array([ 0.17511277, 0.74138403]), 2), (array([ 0.15091777, 0.77638516]), 1), (array([ 0.21101188, 0.77754993]), 4), (array([ 0.25497685, 0.89322296]), 5), (array([ 0.27662418, 0.95863525]), 1), (array([ 0.29101633, 0.88193178]), 5), (array([ 0.25158407, 0.97508714]), 3), (array([ 0.2243961 , 0.79163273]), 2), (array([ 0.11491681, 0.75486515]), 0), (array([ 0.16295869, 0.71022725]), 5), (array([ 0.13634484, 0.71249059]), 0), (array([ 0.06936424, 0.73643767]), 3), (array([ 0.03679796, 0.68104397]), 5), (array([ 0.09132376, 0.65127568]), 2), (array([ 0.04808356, 0.62269234]), 3), (array([ 0.08812181, 0.63701971]), 4), (array([ 0.10317545, 0.66957011]), 0)]
平均の頂点間距離
tmp = 0
for p0, p1 in zip(meeting.minutes[:-1], meeting.minutes[1:]):
tmp += euc(p0[0], p1[0])
ave_dist_btw_nodes = tmp/float(len(meeting.minutes)-1)
print ave_dist_btw_nodes
0.0597962055364
def myplot1(x, y, xfit=np.array([]), yfit=np.array([]), param=None,
scale=['linear', 'linear', 'log', 'log']):
"""my plot function
x: {'label_x', xdata}
y: {'label_y', ydata}
param: {'a': 10, 'b': 20}
"""
if param:
s = [r'$%s = %f$' % (k, v) for k, v in param.items()]
label = s[0]
for _s in s[1:]:
label += ", " + _s
label_x, xdata = x.items()[0]
label_y, ydata = y.items()[0]
fig = plt.figure(figsize=(10, 14))
ax1 = fig.add_subplot(211)
ax1.plot(xdata, ydata)
if len(xfit):
ax1.plot(xfit, yfit, label=label)
ax1.legend(loc='best')
ax1.set_xlabel(label_x)
ax1.set_ylabel(label_y)
ax1.set_xscale(scale[0])
ax1.set_yscale(scale[1])
ax2 = fig.add_subplot(212)
ax2.plot(xdata, ydata)
if len(xfit):
ax2.plot(xfit, yfit, label=label)
ax2.legend(loc='best')
ax2.set_xlabel(label_x)
ax2.set_ylabel(label_y)
ax2.set_xscale(scale[2])
ax2.set_yscale(scale[3])
plt.show()
def plot_N_phi(case=2, trial=100):
ave_dist_btw_nodes= []
N = range(1, 20)
for _N in N:
_tmp = 0
for t in range(trial):
meeting = Meeting(K=30, N=_N, S=50, a=2, p=0.6, draw=False, case=case)
meeting.progress()
tmp = 0
dist_btw_nodes= []
p0 = meeting.minutes[0][0]
for p1 in meeting.minutes[1:]:
if p1[1] != 0:
dist_btw_nodes.append(euc(p0[0], p1[0]))
p0 = p1
_tmp += np.average(dist_btw_nodes)
ave_dist_btw_nodes.append(_tmp/trial)
myplot1({r'$N$': N}, {r'$\phi$': ave_dist_btw_nodes})
print "case: %d" % case
plot_N_phi(2, 1)
case: 2
trial = 100
ave_dist_btw_nodes3= []
N = range(1, 20)
for _N in N:
_tmp = 0
for t in range(trial):
meeting = Meeting(K=30, N=_N, S=50, a=2, p=0.6, draw=False, case=3)
meeting.progress()
tmp = 0
for p0, p1 in zip(meeting.minutes[:-1], meeting.minutes[1:]):
tmp += euc(p0[0], p1[0])
_tmp += tmp/float(len(meeting.minutes)-1)
ave_dist_btw_nodes3.append(_tmp/trial)
myplot1({r'$N$': N}, {r'$\phi$': ave_dist_btw_nodes3})
trial = 100
ave_dist_btw_nodes4= []
N = range(1, 20)
for _N in N:
_tmp = 0
for t in range(trial):
meeting = Meeting(K=30, N=_N, S=50, a=2, p=0.6, draw=False, case=4)
meeting.progress()
tmp = 0
for p0, p1 in zip(meeting.minutes[:-1], meeting.minutes[1:]):
tmp += euc(p0[0], p1[0])
_tmp += tmp/float(len(meeting.minutes)-1)
ave_dist_btw_nodes4.append(_tmp/trial)
myplot1({r'$N$': N}, {r'$\phi$': ave_dist_btw_nodes4})
trial = 100
ave_dist_btw_nodes5= []
N = range(1, 20)
for _N in N:
_tmp = 0
for t in range(trial):
meeting = Meeting(K=30, N=_N, S=50, a=2, p=0.6, draw=False, case=5)
meeting.progress()
tmp = 0
for p0, p1 in zip(meeting.minutes[:-1], meeting.minutes[1:]):
tmp += euc(p0[0], p1[0])
_tmp += tmp/float(len(meeting.minutes)-1)
ave_dist_btw_nodes5.append(_tmp/trial)
myplot1({r'$N$': N}, {r'$\phi$': ave_dist_btw_nodes5})
trial = 20
ave_dist_btw_nodes2_S= []
S = range(10, 150, 10)
for _S in S:
_tmp = 0
for t in range(trial):
meeting = Meeting(K=30, N=6, S=_S, a=2, p=0.6, draw=False, case=2)
meeting.progress()
tmp = 0
for p0, p1 in zip(meeting.minutes[:-1], meeting.minutes[1:]):
tmp += euc(p0[0], p1[0])
_tmp += tmp/float(len(meeting.minutes)-1)
ave_dist_btw_nodes2_S.append(_tmp/trial)
myplot1(S, ave_dist_btw_nodes2_S)
def myplot1_1(x, y, xfit=np.array([]), yfit=np.array([]), param=None,
scale=['linear', 'linear', 'log', 'log'], case=[2, 3, 4, 5]):
"""my plot function
x: {'label_x', xdata}
xdata: numpy array of array
y: {'label_y', ydata}
ydata: numpy array of array
param: {'a': 10, 'b': 20}
"""
if param:
s = [r'$%s = %f$' % (k, v) for k, v in param.items()]
label = s[0]
for _s in s[1:]:
label += ", " + _s
label_x, xdata = x.items()[0]
label_y, ydata = y.items()[0]
if len(scale)%2 == 1:
raise ValueError("'scale' must be even number")
fignum = len(scale)/2
figsize_y = 7 * fignum
fig = plt.figure(figsize=(10, figsize_y))
ax = []
for num in range(fignum):
ax.append(fig.add_subplot(fignum, 1, num+1))
for i, data in enumerate(zip(xdata, ydata)):
ax[num].plot(data[0], data[1], label="case: %d" % case[i])
if len(xfit):
ax[num].plot(xfit, yfit, label=label)
ax[num].legend(loc='best')
ax[num].set_xlabel(label_x)
ax[num].set_ylabel(label_y)
ax[num].set_xscale(scale[2*(num)])
ax[num].set_yscale(scale[2*(num)+1])
plt.show()
IF YOU INTERRUPT MULTIPROSESSINNG PROCESS IN NOTEBOOK, THE JOBS WILL BE ZOMBIE
import time
stime = time.time()
import multiprocessing as mp
cpu = mp.cpu_count()
cp = cpu * 2
trial = 10
p = np.linspace(0.01, 1., 10)
pool = mp.Pool
def wrapper(arg):
return arg[0](arg[1], arg[2], arg[3])
def get_ave_dist_for_p(_p, case, trial):
_tmp = []
_meeting = Meeting
for t in range(trial):
meeting = _meeting(K=30, N=6, S=50, a=2, p=_p, draw=False, case=case)
meeting.progress()
tmp = []
for p0, p1 in zip(meeting.minutes[:-1], meeting.minutes[1:]):
tmp.append(euc(p0[0], p1[0]))
_tmp.append(np.average(np.array(tmp)))
del tmp
result = np.average(np.array(_tmp))
del _tmp
return result
def get_ave_dist_p(p, case, trial):
process = pool(cp)
jobs = [(get_ave_dist_for_p, _p, case, trial) for _p in p]
ave_dist_btw_nodes2_p = np.array(process.map(wrapper, jobs))
return ave_dist_btw_nodes2_p
ydata = np.array([get_ave_dist_p(p, c, trial) for c in [2, 3, 4, 5]])
atime = time.time()
print atime - stime
55.5856618881
ydata
array([[ 0.00794402, 0.0925033 , 0.13149265, 0.14578465, 0.14267179, 0.13971215, 0.15093776, 0.15804089, 0.13822624, 0.15222808], [ 0.01030824, 0.13906071, 0.10719815, 0.09556798, 0.07210218, 0.05809918, 0.04977034, 0.04395774, 0.04496211, 0.0388627 ], [ 0.00852743, 0.08996911, 0.09619545, 0.08688827, 0.07980701, 0.06653041, 0.0583692 , 0.05512152, 0.04850307, 0.04673804], [ 0.00970147, 0.11626175, 0.10510069, 0.08848408, 0.07935871, 0.06376078, 0.05654823, 0.05217771, 0.0472176 , 0.04085567]])
myplot1_1({r'$p$': np.array([p]*4)}, {r'$l$': ydata}, scale=['linear', 'linear', 'linear', 'log'])
compare: not pararelled
stime = time.time()
trial = 10
p = np.linspace(0.01, 1., 10)
ydata = []
for case in [2, 3, 4, 5]:
ave_dist_btw_nodes2_p = []
for _p in p:
_tmp = 0
for t in range(trial):
meeting = Meeting(K=30, N=6, S=50, a=2, p=_p, draw=False, case=case)
meeting.progress()
dist_btw_nodes2_p = []
p0 = meeting.minutes[0][0]
for p1 in meeting.minutes[1:]:
if p1[1] != 0:
dist_btw_nodes2_p.append(euc(p0[0], p1[0]))
p0 = p1
_tmp += np.average(dist_btw_nodes2_p)
ave_dist_btw_nodes2_p.append(_tmp/trial)
ydata.append(np.array(ave_dist_btw_nodes2_p))
ydata = np.array(ydata)
atime = time.time()
print atime- stime
116.609680891
trial pararelled
import time
stime = time.time()
import multiprocessing as mp
cpu = mp.cpu_count()
cp = cpu * 2
trial = 10
p = np.linspace(0.01, 1., 10)
pool = mp.Pool
def wrapper(arg):
return arg[0](arg[1], arg[2])
def get_ave_dist_for_trial(_p, case):
meeting = Meeting(K=30, N=6, S=50, a=2, p=_p, draw=False, case=case)
meeting.progress()
tmp = []
for p0, p1 in zip(meeting.minutes[:-1], meeting.minutes[1:]):
tmp.append(euc(p0[0], p1[0]))
return np.average(np.array(tmp))
def get_ave_dist_p(p, case, trial):
result = []
for _p in p:
process = pool(cp)
jobs = [(get_ave_dist_for_trial, _p, case) for t in range(trial)]
_tmp = []
result.append(np.average(np.array(process.map(wrapper, jobs))))
return result
ydata = np.array([get_ave_dist_p(p, c, trial) for c in [2, 3, 4, 5]])
atime = time.time()
print atime - stime
58.7189991474
ydata
array([ 0.15488623, 0.03742842, 0.05361312, 0.0457753 ])
myplot1({r'$p$': p}, {r'$\phi$': ave_dist_btw_nodes2_p}, scale=['linear', 'linear', 'linear', 'log'])
上の図で$p$が小さいときに平均距離が小さくなるのは、沈黙同士の距離(すなわち0)が多く現れるためにこのようなことになっている。沈黙の効果を無視して、選ばれた意見同士で考える場合には、以下のようにコードを変更する必要がある。
trial = 100
ave_dist_btw_nodes2_p= []
p = np.linspace(0.01, 1., 100)
for _p in p:
_tmp = 0
for t in range(trial):
meeting = Meeting(K=30, N=6, S=50, a=2, p=_p, draw=False, case=3)
meeting.progress()
dist_btw_nodes2_p = []
p0 = meeting.minutes[0][0]
for p1 in meeting.minutes[1:]:
if p1[1] != 0:
dist_btw_nodes2_p.append(euc(p0[0], p1[0]))
p0 = p1
_tmp += np.average(dist_btw_nodes2_p)
ave_dist_btw_nodes2_p.append(_tmp/trial)
myplot1({r'$p$': p}, {r'$\phi$': ave_dist_btw_nodes2_p}, scale=['linear', 'linear', 'linear', 'log'])