参加者間のネットワークについて、マルコフモデルで統一的にそのモデル化ができることが示されたが、一方でその確率の決め方に今回のモデルの独自性が生まれると考える。そこで、これまでと同じように、距離の概念を入れて状態から状態への遷移確率が決まるとして考えてみる。
(しかし、一般に言って、$i\rightarrow j$と$j\rightarrow i$の確率は同じである必要はなく、このような場合を考えるなら、それは"距離"としての定義を満たしていない。)
$i$と$j$の間の距離を$d_{ij}(=d_{ji})$とし、その重みを$d_{ij}$の関数として$w_{ij}=w(d_{ij})$とすると、遷移確率は $$p_{ij} = \frac{w_{ij}}{\sum_{j}{w_{ij}}}$$ のようになる。
以下には最初に考えたように各状態について位置の座標を定義して、その間のユークリッド距離のみで確率が決定するような場合を考える。
%matplotlib inline
from Tkinter import *
import numpy as np
from scipy.spatial.distance import euclidean as euc
class Main:
def __init__(self):
self.N = 6
self.app = Calc(self.N)
def run(self):
self.window = Window(self.N, main=self.app)
self.window.display()
class Calc:
def __init__(self, N):
self.members = dict()
self.N = N
def calc_P(self):
P = []
for key, v in self.members.items():
_P = []
for n in range(self.N):
d = euc(self.members[key].place, self.members[n].place)
w = self.g(d)
_P.append(w)
P += _P
P = np.array(P).reshape(self.N, self.N)
self.P = []
for _P in P:
s = np.sum(_P)
self.P.append(_P/s)
self.P = np.array(self.P)
def g(self, x):
# 発言者の物理的距離に対する関数
return np.exp(-x)
class Person(object):
def __init__(self, place=np.array([0., 0.])):
# 発言者の実際の位置が2次元の座標として表せる
self.place = place
class Window(object):
def __init__(self, N, main):
self.root = Tk()
self.main = main
self.width = 640
self.height = 480
canvas = Canvas(self.root, width=self.width, height=self.height)
self.var = StringVar()
self.oval(canvas, N)
canvas.bind('<Motion>', self.pointer)
canvas.pack()
label = Label(self.root, textvariable=self.var, font='Ubuntu 9')
label.pack(side='left')
b1 = Button(self.root, text='calc', command=self.b1_clicked)
b1.pack(side='right')
b2 = Button(self.root, text='save', command=self.b2_clicked)
b2.pack(side='right')
def oval(self, canvas, N=6):
self.members = dict()
deg = np.linspace(0., 360., N, endpoint=False)
radius = 20
self.r = int((min(self.height, self.width)/2-radius)*0.9)
self.centerx = int(self.width/2)
self.centery = int(self.height/2)
for n in range(N):
rad = np.radians(deg[n])
self.members[n] = Oval(canvas, n+1,
self.centerx+self.r*np.cos(rad),
self.centery+self.r*np.sin(rad),
radius, self.var)
def pointer(self, event):
self.var.set("(%d,%d)" % (event.x, event.y))
def b1_clicked(self):
for n in range(self.main.N):
x = (self.members[n].x-self.centerx)/float(self.r)
y = (self.members[n].y-self.centery)/float(self.r)
self.main.members[n] = Person(place=np.array([x, y]))
self.main.calc_P()
self.root.destroy()
def b2_clicked(self):
import tkFileDialog
import os
fTyp = [('eps file', '*.eps'), ('all files', '*')]
filename = tkFileDialog.asksaveasfilename(filetypes=fTyp,
initialdir=os.getcwd(),
initialfile='figure_1.eps')
if filename is None:
return
try:
self.canvas.postscript(file=filename)
except TclError:
print """
TclError: Cannot save the figure.
Canvas Window must be alive for save."""
return 1
def display(self):
self.root.mainloop()
class Oval:
def __init__(self, canvas, id, x, y, r, var):
self.c = canvas
self.x = x
self.y = y
self.var = var
self.tag = str(id)
self.c.create_oval(x-r, y-r, x+r, y+r, outline='', fill='#069', tags=self.tag)
self.c.tag_bind(self.tag, '<Button-1>', self.pressed)
self.c.tag_bind(self.tag, '<Button1-Motion>', self.dragging)
def pressed(self, event):
self.x = event.x
self.y = event.y
def dragging(self, event):
self.c.move(self.tag, event.x - self.x, event.y - self.y)
self.x = event.x
self.y = event.y
def cal_f(n, P, K):
f = np.identity(n) + P
if K == 1:
return f
for k in range(2, K+1):
_k = 2
tmp = P
while _k < k+1:
tmp = np.dot(tmp, P)
_k += 1
f += tmp
return f
from pandas import DataFrame
main = Main()
def g(x):
return 1./(1+x)
main.app.g = g
main.run()
DataFrame(main.app.P)
0 | 1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|---|
0 | 0.333575 | 0.161861 | 0.125993 | 0.111192 | 0.119210 | 0.148170 |
1 | 0.133705 | 0.275550 | 0.173149 | 0.135611 | 0.134642 | 0.147343 |
2 | 0.102755 | 0.170949 | 0.272049 | 0.174709 | 0.147433 | 0.132106 |
3 | 0.092117 | 0.136005 | 0.177471 | 0.276351 | 0.182568 | 0.135488 |
4 | 0.097598 | 0.133445 | 0.148002 | 0.180420 | 0.273100 | 0.167436 |
5 | 0.124496 | 0.149872 | 0.136102 | 0.137414 | 0.171837 | 0.280279 |
6 rows × 6 columns
K = 100
DataFrame(cal_f(6, main.app.P, K))
0 | 1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|---|
0 | 15.423693 | 17.151696 | 17.315426 | 17.024868 | 17.238498 | 16.845818 |
1 | 14.168166 | 18.278681 | 17.380701 | 17.064849 | 17.264082 | 16.843520 |
2 | 14.121725 | 17.159921 | 18.493416 | 17.117771 | 17.283518 | 16.823649 |
3 | 14.104293 | 17.114469 | 17.388423 | 18.234201 | 17.329755 | 16.828858 |
4 | 14.113258 | 17.110581 | 17.350238 | 17.125873 | 18.429867 | 16.870184 |
5 | 14.154327 | 17.132605 | 17.332561 | 17.068061 | 17.313669 | 17.998776 |
6 rows × 6 columns