In [1]:
%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
In [2]:
meeting = Meeting(K=30, N=10, S=50, a=2, p=0.6, case=3)
meeting.progress()