デバイス間の推移確率が求められたので、次はこの推移確率から同値類とその同値類中の中心ノードを算出していきます。利用するファイルは以下のファイルです。transition_count_non0_rate.csv
このファイルを取り込んでいきます。
この推移確率行列から、デバイスを状態として、状態を同値類に分類していきます。同じ同値類であることは、相互到達可能であることを意味します。デバイス間で相互到達可能の集合がいくつあるかを調べていきます。次の関数を利用します。
getEquivalence4(th, roop, p)関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def getEquivalence4(th, roop, p):
reachable = np.zeros((len(p), len(p))) #全て0のpと同じ大きさの行列を用意
equivalence = [[] for i in range(len(p))] #同値類を最大数用意
list_number = 0
for ix in range(roop): #n乗まで実施
pn = np.linalg.matrix_power(p.copy(), ix+1) #累乗
for i in range(len(pn)):
for j in range(len(pn)):
if(pn[i][j] > th): #推移確率が閾値より大きいかチェック
reachable[i,j] = 1
# print('到達行列 = \n{0}'.format(reachable))
# communicate = np.zeros((len(p), len(p))) #全て0のpと同じ大きさの行列を用意
# for i in range(len(reachable)):
# for j in range(len(reachable)):
# if(reachable[i][j] == 1 and reachable[j][i] == 1):
for i in range(len(pn)):
for j in range(i+1, len(pn)):
if(reachable[i][j] == 1 and reachable[j][i] == 1):
# print('reachable {0} <-> {1}'.format(i, j))
find = 0 #iでfind -> 1, jでfind -> 2
idx = len(pn)
for k in range(len(pn)):
if i in equivalence[k]: #iが同値類k番目に存在している
find = 1 #iは同値類k番目に存在
idx = k
# print('{0} find in {1}'.format(i, equivalence[k]))
break
elif j in equivalence[k]:
find = 2
idx = k
# print('{0} find in {1}'.format(j, equivalence[k]))
break
if find == 1:
if j not in equivalence[idx]: #jは同値類kには存在しない (他のリストにもないことを確認する!!!他のリストにあった場合は移動がいい? -> communicateがずれないように最後に集合で演算する)
equivalence[idx].append(j) #jを追加
# print('{0}に{1}を追加'.format(equivalence[idx], j))
# print('リスト全体 {0}'.format(equivalence))
#break
elif find == 2:
if i not in equivalence[idx]: #(他のリストにもないことを確認する!!!)
equivalence[idx].append(i)
# print('{0}に{1}を追加'.format(equivalence[idx], i))
# print('リスト全体 {0}'.format(equivalence))
#break
elif(find == 0): #新規に追加
equivalence[list_number].append(i)
# print('{0}に{1}を追加'.format(equivalence[list_number], i))
# print('リスト全体 {0}'.format(equivalence))
if(i != j):
equivalence[list_number].append(j)
# print('{0}に{1}を追加'.format(equivalence[list_number], j))
# print('リスト全体 {0}'.format(equivalence))
list_number += 1
#4. Communicateにならないノードを登録
for i in range(len(pn)):
find = 0
for j in range(len(pn)):
if i in equivalence[j]:
find = 1
break
if find == 0:
equivalence[list_number].append(i)
# print('Non Communication node {0} add'.format(i))
# print('リスト全体 {0}'.format(equivalence))
list_number += 1
#5. エルゴード性の確認(class数が1のとき)
class_number = 0
for i in range(len(pn)):
if len(equivalence[i]) > 0:
# print('クラスの長さ : {0}, {1}'.format(len(equivalence[i]), equivalence[i]))
class_number += 1
for i in range(class_number):
for j in range(i+1, class_number):
s1 = set(equivalence[i])
s2 = set(equivalence[j])
if s1 & s2 :
# print('重複 {0} & {1}'.format(i, j))
# print('重複ノード {}'.format(s1 & s2))
equivalence[i] = equivalence[i] + equivalence[j]
equivalence[j].clear()
#print('修正クラス数 {0}'.format(modify_class_number))
for i in range(class_number):
# print(equivalence[i])
equivalence[i] =list(set(equivalence[i]))
#再度クラス数チェック
class_number = 0
for i in range(len(pn)):
if len(equivalence[i]) > 0:
class_number += 1
#再度リストを構成
modify_equivalence = [[] for i in range(class_number)] #同値類をクラス数用意
l_index = 0
for i in range(len(pn)):
if len(equivalence[i]) > 0:
modify_equivalence[l_index] = equivalence[i]
l_index += 1
return modify_equivalence, class_number, reachable
この関数は3つの引数(th, roop, p)を持ちますが、thは推移しているとみなすことができる閾値です。つまり、この値より推移確率が大きいとき、推移があると考えます。roopは何回で到達可能かを示す値です。pは推移確率行列です。戻り値はmodify_equivalence, class_number, reachableがあります。modify_equivalenceは同値類ごとにデバイスが分類されています。class_numberは同値類の数、reachableは状態間で推移が可能かどうかを{0,1}で表した接続行列です。
もう一つ関数を作っていきます。
getDegreeMax(equivalence, reachable)関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def getDegreeMax(equivalence, reachable):
degree_max_value = [] #クラスの中で最大次数のものをクラス0から順番に入れる
degree_max_index = []
reachable_sum = np.sum(reachable, axis=0) + np.sum(reachable, axis=1) #到達行列から行和と列和の和
for i in range(len(equivalence)): #クラス数だけ回す
deg_max = -1 #最大値の初期値
deg_max_index = -1 #最大値を持つノード番号
for j in equivalence[i]: #ノード番号を一つずつ取り出す
if deg_max < reachable_sum[j]:
deg_max = reachable_sum[j]
deg_index = j
degree_max_value.append(deg_max)
degree_max_index.append(deg_index)
return degree_max_index, degree_max_value
これは、同値類の中で中心性のノードがどれかを計算しています。次数中心性で求めています。
今回の計算結果では、
同値類数が6964個、
最大クラス数 : 18090、
最大クラスを持つindex : 0
最大クラスの最大次数を持つノード番号 : 6947、
デバイス名 : Comp186884
となりました。ここまでの結果で同値類数、同値類の中の中心性デバイスの情報がわかるようになりました。