シチュエーション:
仮定:
評価関数について:
評価関数は参加者の人数$n$に対して
$L(n)$:結論までに張られたリンクの数
$T(n)$:結論までにかかった時間
として、
$$f(n) = f_L(n) - f_T(n)$$とできるだろう。$f_{L},f_{T}$は正値関数
発言が、それを特徴づけるパラメータ(発言者、思想、賛成反対、重要度など)$a$個で表現できるとした時、各離散時刻$t_{k}$(全体で$k$番目の発言の開始された時刻)になされる発言$x_{k}$は$R^{a}$上の有界集合$X\subset R^{a}$における1点とみなすことができる。
発言者の人数を$n$人とすると、$x$のパラメータの一つである発言者は、アルファベット$N = \{1, 2, \dots n\}$に、沈黙を意味する{0}を加えて表すことができる(これを$N'$とする)。
ここで、$i$の持っている意見すべての集合は$X_{i}$と表し、その要素数は$I_{i}$と表すことにする。
すなわち
$$X_{i} = \{\text{person}(x)=i | x \in X\}$$また、定義より
$$X_{i} \cap X_{j} = \emptyset,\ \ \,\ ^{\forall} i, j \in \{i\neq j | i, j \in N'\}$$$$ \bigcup_{i=0}^{n} X_{i} = X$$である。
次に、時刻$k$に$i$が発言した後、時刻$k+1$に$j$が発言する条件付き確率$P(x_{k+1}^{j}|x_{k}^{i})$は、以下のように書けるだろう。
$$P(x_{k+1}^{j}|x_{k}^{i}) = p_{i}(k,j)q(x_{k+1}^{j},X_{j}(k)),\ \ \ \ ^{\forall} i, j \in N'$$ここで、$p_{i}(k,j)$は発言者$i$のあとに$j$が発言する確率であり、$q(x_{k+1}^{j},X_{j}(k))$は、$j$の発言のうち、$k$番目までに出現していない発言を選ぶ確率である。条件付き確率の定義から、$X_{j}(k) = \emptyset$の時、$p_{i}(k,j)$は再定義される必要がある。$p$と$q$の具体的な形については後で述べることとする。
時間発展は以下のようなプロセスで進展する。
初期条件としての意見$x_{0}$は議題であり、このときの発言者は$0$であるとする。
時刻$t_{1}$で確率$P(x_{1}^{i}|x_{0}^{0})$のもと点$x_{1}^{i}$が選ばれ、このとき議題$x_{o}^{0}$との間の関係があれば(すなわち適当に定めた距離において、ある閾値$r$より小さければ)、この二つの要素の間にリンクを張ることにする。一度選ばれた点は、再び選ばれることはない。
以後同様に確率的に点を選んでいき、それまでに発言された点で距離が近い点はすべてリンクで結んでゆく。
シミュレーションの終了条件は、ある発言がなされた時、その発言がある閾値より大きいリンク数を持つような場合と、すべての参加者が発言し尽くしてしまった場合である。
$p$は、ある人$i$の発言が$j$に向けられることによる効果や、声の大きさ、立場、実際の物理的距離、親密度、関心などの要素を含んでいる。
一番簡単な定式化は、すべての人に関して等確率で話すことを促進するというものである。
$$p_{i}(k,j) = \frac{1}{m}$$ここで$m$は、時刻$t_{k}$の終わった時点で発言することのできる人(発言のストックがある人)の数+(沈黙)である。
次に現実的な定式化として、各参加者の実際の位置を用いて、その距離に応じて重みを付けるというものが考えられる。
すなわち、$i$から$j$の実際の物理的距離が$d_{ij}$で書けるとすると、
$$p_{i}(k,j) = \frac{g(d_{ij})}{\sum_{v \in N'} g(d_{iv})}$$のようにできる。このとき関数$g$は$[0, +\infty)$の領域で連続で有界な正値単調減少関数と考えていいだろう。また、この場合には$d_{i0}$には正の有界値を任意に与える必要があるだろう(他の値との相対的な大小は、声の大きさ、場所の声の通りやすさなどを表すことになる)。
ex1)$$ g(x) = \frac{1}{x+1}$$
ex2)$$\displaystyle g(x) = e^{-x}$$
$q$は、発言者が定まった上で、その中から一つ発言を選ぶ確率である。これも最も簡単な式としては
$$ q(x_{k+1}^{j}, X_{j}(k)) = \frac{1}{\#X_{j}(k)}$$が考えられる。ここで$\#$は集合内の要素数である。また、先程も述べたように$\#X_{j}(k)=0$のときはこれは定義できない。
次に考えられるのは、それまでの意見をできるだけ反映するように発言するような場合で、このとき、
$$\# \{d(x_{l}^{s}, x_{k+1}^{j}) < r \ |\ ^{\forall} l \le k, s \in N\}$$を最大にするような$x_{k+1}^{j}$が選ばれる。
もしくは、直前の意見のみに関連するように発言するとすれば、
$x_{k+1}^{j}$の選び方は、$d(x_{k}^{i}-x_{k+1}^{j})$を最小とするように選べば良い。
import matplotlib.pyplot as plt
import numpy as np
N = 6
radius = 3
def accumulate(iterable):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
total = next(it)
yield total
for element in it:
total += element
yield total
class Person(object):
def __init__(self, ideas_num=10, place=(0., 0.), **kwargs):
# 意見は0~1の間の値を一様に取りうる
self.ideas = list(np.random.random(ideas_num)
# 発言者の実際の位置が2次元の座標として表せる
self.place = place
# その他の特徴量
for (k, v) in kwargs.items():
setattr(self, k, v)
def distance(self, p):
# 人pと自分との間の距離(ユークリッド距離)
d = np.sqrt((self.place[0]-p.place[0])**2 + (self.place[1]-p.place[1])**2)
return d
class meeting(object):
def __init__(self):
# 意見の時系列(今の場合0〜1の乱数の値そのもの)
self.ideas = []
# 発言者の時系列
self.speaker = []
# 時刻
self.k = 0
# 張られたリンク(時刻, 時刻)のタプルで表現する
self.links = []
# はじめの意見(議題)
x0 = 0.
self.ideas.append(x0)
# 議題は沈黙の意見だとする
self.speaker.append(0)
# 会議のメンバーとして沈黙を加える
self.members = {0: Person(place=(0., 0.)),}
# 沈黙を中心とした円周上に等間隔で参加者が存在する
deg = np.linspace(0., 360., N, endpoint=False)
for n in range(1, N+1):
rad = np.radians(deg[n-1])
self.members[n] = Person(place=(radius*np.cos(rad), radius*np.sin(rad)))
def p(self, i):
# 発言者の物理的距離に対する関数
def g(x):
return 1./(1.+x)
# 参加者の中で話せる人のみを対象に
_N = []
for k, v in self.members.items():
if len(v.ideas):
_N.append(k)
# それらの人たちに対し、重み付けの確率を付与
w = []
for n in _N:
d = self.members[n].distance(i)
w.append(g(d))
w = np.array(w)
sum_ = np.sum(w)
_p = list(w/sum_)
p = accumulate(_p)
rn = np.random.rand()
nm = 0
while True:
if p[nm] > rn:
break
else:
nm += 1
# その確率で選ばれた人の名前を返す
return _N[nm]
def q(self, j):
# 発言者jが選ばれた時、持っている意見から等確率で意見を取り出す
x_j = self.members[j]
return x_j.ideas.pop()
def distance(self, x, y):
d = np.abs(x - y)
return d
def connect(self, idea):
for i, v in enumerate(self.ideas):
if self.distance(v, idea) < radius:
def progress(self):
j = self.p(self.members[self.speaker[-1]])
self.ideas.append(self.q(j))
def test_plot(self):
x = [0,]
y = [0,]
for n in range(N+1):
x.append(self.members[n].place[0])
y.append(self.members[n].place[1])
return x,y
File "<ipython-input-2-9d2759db38b2>", line 21 self.place = place ^ SyntaxError: invalid syntax
a = meeting()
a.progress()
print a.speaker
print a.ideas
[0] [0.0, 0.25575792014749998]
シミュレーションの実行と解析
他の現象(代謝ネットワーク等)との関連付け