2017年12月23日土曜日

これからの半年間を考える

 昨日実習が終わってからぼやーっと考えた今後のことについて、書き記しておく。

【研究室】
 だいたいどんなことをしていくのかは決まっているが、はっきりと決まっているわけではない。ひとまずいろいろ着手してみて知識をつけることでテーマを見つける方針になるだろう。しかし考えてみればそれはこの一年間と同じ。自分で何も考えず先生にテーマを与えてもらうのを期待するのは良くないので、冬休みの間にサーベイし正月明けに先生に研究テーマを相談できれば良いと思う。成果報告書自体はいざとなれば先月の発表内容で事足りるので、成果を出すことにこだわらず勉強し続ける半年間でも構わんっちゃ構わん。しかしそれではメリハリがなく効率が悪いので、小さくとも何かしらの成果を出せるようにしたほうがいいのだろう。

 それとは別に、研究室では扱わないが自分がやりたいテーマについても勉強を進めなければいけない。これは半年でとりあえずの落としどころを作れるような代物ではないので、隙間時間で進める。半年の時点で何かしら新たな視点を研究室にフィードバックできれば良い。

 そんなことより一日のスケジュールがどのようなものになるのかまだ全容がはっきりしていない。おそらく自宅で作業してもいいと推測するが、これもまたメリハリに欠けるので、実習期間同様8-22時は大学にいようと思う。


【国試対策】
 総合試験はヒヤヒヤしたもものなんとか終了。再試の人はこれから1週間で知識をつけるわけなので、再試が終わる頃には本試をぎりぎり通過した人が最下層になる。その状態で俺は実習から半年間離れる。

 危険極まりない。

 半年間研究室に没頭しているとえらいことになりかねない。来年ある程度の余裕があればそれこそこの先1年間研究を継続できるのだから、多少は国試対策を進めていくのがどちらにとっても良いのだろう。それなら始めるのは早い方がいいし、さらにはこの総合試験でヒヤヒヤした記憶が消えないうちにペースを作ってしまうのが一番楽なのだろう。

 で、さっそくQBに取り掛かってもいいのだが、一度全体の骨組み作りたいなーということで、正月休みのうちに診断学の教科書でも読もうと思う。研究室もちょうどひと段落ついたところなので唐突に案件が降りかからなければ時間はある。全33章のうち序論的なものを除いた3章からの計31章分を読み切ろうと思う。今日から1日2章読めば読み切れるっぽいが、まぁなんやかんや読めない日やサボる日が出てきて、ちょい残しにはなると思う。でもそれでいいと思う。頑張ってまで進める気はないのだから。

12/23-1/7 診断学
 記事上げた翌日の時点ですでにやる気皆無だったため破棄

 QBの進行プランを立てた。twitterで同志を探したが見つからなかったので、自力でペースを作るしかない。スラッシュ前の分野を病みえやイヤーノートを参照。スラッシュ後の分野の問題をQBで解いていく。おおよそ1か月後に復習するシステムにしてある。予定が思い通り進んでいれば1周目問題以外にも手を伸ばすし、進んでいなければやらなくてもいいくらいの実質予備日としての扱い。

1/8-1/14 血液/
1/15-1/21 リア/血液
1/22-1/28 腎泌/リア
1/29-2/4 呼吸/腎泌
2/5-2/11 予備/呼吸
2/12-2/18 神経
2/19-2/25 神経
2/26-3/4 /神経血液
3/5-3/11 /神経リア
3/12-3/18 循環/腎泌
3/19-3/25 循環/呼吸
3/26-4/1 代内/循環
4/2-4/8 代内/循環
4/9-4/15 /代内神経
4/16-4/22 /代内神経
4/23-4/29 消化/循環
4/30-5/6 消化/循環
5/7-5/13 産科/消化
5/14-5/20 産科/消化
5/21-5/27 婦人/産科
5/28-6/3 婦人/産科
6/4-6/10 /婦人消化
6/11-6/17 /婦人消化
6/18-6/24 小児/産婦
6/25-7/1 小児/産婦

最初が軽めなのはペース作り。血液が最初なのは苦手だから。
上の通りに進めば、主要内科学+小児産婦が一通り終わることになる。
病みえ1冊をざっと読むのに5時間程度と推算したので、平日1日1時間読んで、空き時間と休日に問題演習という形になるかと思う。

そして確か7月以降はマイナー科が講義で始まっていたかと記憶しているので、いい感じで接続できると良いなぁ。

【まとめ】
・冬休みはサーベイと診断学
・冬休み明けに先生に研究テーマ進言
・平日8-22時は大学
・平日朝1時間は病みえざっと読み
・QB進める強い意志

2017年12月10日日曜日

FEP tutorial

 Free-energy principle、いつかは理解したいと思っていた。ちょっと前に某先生(面識は皆無)がツイートしていたこれが読めそうだったので読んだ。せっかくなので練習がてらexerciseをpythonでやった。
FEPの入門的なこと書いてるサイトを見かけた覚えが無いので、万一本気で勉強しようとしてる人が通りかかった時のために次の様に記載しておく。

※間違いがあっても責任は負いかねます。
※間違いの指摘は大歓迎です。

【Excrcise 1】
#-*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

#平均mu, 分散sigmaの正規分布におけるxの確率
def norm_prob(x, mu, sigma):
return np.exp(-1*((x-mu)**2)/(2*sigma))/np.sqrt(2*np.pi*sigma)

#関数gはここでは入力の2乗
def g(x):
return x**2

#setting
u=2
v_p=3
sigma_u=1
sigma_p=1

v=np.linspace(0.01, 5, 500)

#vの各要素に関してその確率を求める
prob=norm_prob(v, v_p, sigma_p)*norm_prob(u, g(v), sigma_u)
prob/=np.sum(prob)
plt.plot(v, prob)
plt.show()
----------------------------------------------------------


【Exercise 2】
#-*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

#長さvのものは感覚器にてu=v^2として観測される
def g(v):
    return v**2

#gをphiで微分
def dgdphi(v):
    return 2*v

#Fをphiで微分
def dFdphi(v_p, sigma_p, sigma_u, phi, u):
    grad=(u-g(phi))*dgdphi(phi)/sigma_u+(v_p-phi)/sigma_p
    return grad

#setting
u=2
v_p=3
sigma_p=1
sigma_u=1
phi=v_p
delta=0.01
time=5

log=[]
log.append(phi)

for i in range(np.int(time/delta)):
    phi=phi+delta*dFdphi(v_p, sigma_p, sigma_u, phi, u)

    log.append(phi)

plt.plot(np.arange(0, len(log)*delta, delta), log)
plt.show()
----------------------------------------------------------------

【Exercise3】
#-*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

#setting
u=2
v_p=3
phi=[v_p,]
e_p=[0,]
e_u=[0,]
sigma_p=1
sigma_u=1
delta=0.01
time=5

def g(phi):
    return phi**2

def dgdphi(phi):
    return 2*phi

for i in range(np.int(time/delta)):
    phi.append(phi[i]+delta*(e_u[i]*dgdphi(phi[i])-e_p[i]))
    e_p.append(e_p[i]+delta*(phi[i]-v_p-sigma_p*e_p[i]))

    e_u.append(e_u[i]+delta*(u-g(phi[i])-sigma_u*e_u[i]))

x=np.arange(0, time/delta+1, 1)*delta

plt.plot(x, phi, 'b', label='phi')
plt.plot(x, e_p, 'g', label='e_p')
plt.plot(x, e_u, 'r', label='e_u')

plt.legend()

plt.show()
----------------------------------------------------------------

【Exercise4】略

【Exercise5】
#Exercise5
import numpy as np
import matplotlib.pyplot as plt

def g():
    return 5

m_phi=5
v_phi=2
learning_rate=0.01
delta=0.01
time=20
Trial=1000
sigma_i=[]
sigma_i.append(1)

for T in range(Trial):
    e_i=0
    ep_i=0
    phi_i=np.sqrt(v_phi)*np.random.randn(1)+m_phi
    sigma_temp=sigma_i[-1]
 
    for t in range(np.int(time/delta)):
        dep_i=phi_i-g()-e_i
        de_i=sigma_temp*ep_i-e_i
     
        ep_i=ep_i+dep_i*delta
        e_i=e_i+de_i*delta
 
    sigma_i.append(sigma_temp+learning_rate*(ep_i*e_i-1))

x=np.arange(0, len(sigma_i), 1)
plt.plot(x, sigma_i)
plt.show()
-----------------------------------------------------



発展的な内容に関しては紹介のみで済まされている。まあtutorialなのだから、ここをスタート地点として強くなっていかねばならんのだろう。。。

2017年11月12日日曜日

シミュレーションのアニメーション

二重振り子やるにしても可視化できなけりゃ面白くないので、とりあえずアニメーションのgifを作れるようになろうとしたもの。また蔵本モデル使う。

update関数内でtからt+1の計算を行えば、今の様にデータをすべて保持する必要がなさそうだということはわかったのだが、昨日までのコードをそのまま使った方が楽なので、一旦全部計算してます。
plt.axes().set_aspect('equal', 'datalim')をネットから見つけ出すのに時間がかかった。
そしてそれよりもimagemagickの設定の方がさらに時間かかった。
--------------------------------------------------------
#-*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def theta_mat(theta):
    theta=theta.reshape(1, -1)
    theta_mat=theta.copy()
    while theta_mat.shape[0]<theta_mat.shape[1]:
        theta_mat=np.r_[theta_mat, theta]
    return theta_mat

#making model data
#setting

theta=np.array([0, 0.5*np.pi, np.pi]).reshape(1, -1)
omega=np.array([np.pi, 1.5*np.pi, 2.0*np.pi])     # anglular velocity
N=theta.size
time=30       # measurement time
h=0.05        # micro time
K=np.array([[0, 1.0, 1.5],[1.0, 0, 0.5], [1.5, 0.5, 0]])  # coupling strength(N*N)

t=1
while t*h<time:
    theta_now=theta[t-1, :].reshape(-1, 1)
    k1=(omega+np.sum(np.sin(theta_mat(theta_now)-theta_now)*K, 1)/N).reshape(-1, 1)
    theta4k2=theta_now+(h/2)*k1
    k2=(omega+np.sum(np.sin(theta_mat(theta4k2)-theta4k2)*K, 1)/N).reshape(-1, 1)
    theta4k3=theta_now+(h/2)*k2
    k3=(omega+np.sum(np.sin(theta_mat(theta4k3)-theta4k3)*K, 1)/N).reshape(-1, 1)
    theta4k4=theta_now+h*k3
    k4=(omega+np.sum(np.sin(theta_mat(theta4k4)-theta4k4)*K, 1)/N).reshape(-1, 1)

    theta_next=theta_now+(h/6)*(k1+2*k2+2*k3+k4)
    theta_next=np.mod(theta_next, 2*np.pi)
    theta=np.r_[theta, theta_next.reshape(1, N)]
    t+=1

def update(i):
    plt.clf()
    circle=plt.Circle((0, 0), radius=1.0, fc='y')
    plt.gca().add_patch(circle)
    circle1=plt.Circle((np.cos(theta[i, 0]), np.sin(theta[i, 0])), radius=0.1, fc='b')
    plt.gca().add_patch(circle1)
    circle2=plt.Circle((np.cos(theta[i, 1]), np.sin(theta[i, 1])), radius=0.1, fc='r')
    plt.gca().add_patch(circle2)
    circle3=plt.Circle((np.cos(theta[i, 2]), np.sin(theta[i, 2])), radius=0.1, fc='g')
    plt.gca().add_patch(circle3)
 
    plt.xlim(-1.5, 1.5)
    plt.ylim(-1.5, 1.5)
    plt.axes().set_aspect('equal', 'datalim')

fig=plt.figure()
ani=animation.FuncAnimation(fig, update, frames=theta.shape[0])
ani.save('oscillation.gif', writer='imagemagick', fps=np.int(1/h))
--------------------------------------------------------
Exception ignored in: <bound method TimerQT.__del__ of <matplotlib.backends.backend_qt5.TimerQT object at 0x000001D6221C4BA8>>
Traceback (most recent call last):
  File "C:\Users\_____\Anaconda3\lib\site-packages\matplotlib\backends\backend_qt5.py", line 201, in __del__
TypeError: 'method' object is not connected

なんかエラー吐かれたけどgif自体は出力されてるのでよしとする。
(分かる人通りかかったら教えてください)

何はともあれアニメーションできましたとさ。

好奇心から振動子を増やしてみる。
いい感じで同期しないかなーと思い、Kを若干大きめに。
振動子をグラデーションにしようかとも思ったが面倒なのでパス。
--------------------------------------------------------
#-*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def theta_mat(theta):
    theta=theta.reshape(1, -1)
    theta_mat=theta.copy()
    while theta_mat.shape[0]<theta_mat.shape[1]:
        theta_mat=np.r_[theta_mat, theta]
    return theta_mat

#making model data
#setting

theta=np.random.rand(100).reshape(1, -1)
theta=theta*2*np.pi
omega=np.random.rand(100)*np.pi
N=theta.size
time=30       # measurement time
h=0.05        # micro time
K=np.random.rand(10000).reshape(100, 100)+1
K=K+K.T
for i in range(K.shape[0]):
    K[i, i]=0

t=1
while t*h<time:
    theta_now=theta[t-1, :].reshape(-1, 1)
    k1=(omega+np.sum(np.sin(theta_mat(theta_now)-theta_now)*K, 1)/N).reshape(-1, 1)
    theta4k2=theta_now+(h/2)*k1
    k2=(omega+np.sum(np.sin(theta_mat(theta4k2)-theta4k2)*K, 1)/N).reshape(-1, 1)
    theta4k3=theta_now+(h/2)*k2
    k3=(omega+np.sum(np.sin(theta_mat(theta4k3)-theta4k3)*K, 1)/N).reshape(-1, 1)
    theta4k4=theta_now+h*k3
    k4=(omega+np.sum(np.sin(theta_mat(theta4k4)-theta4k4)*K, 1)/N).reshape(-1, 1)

    theta_next=theta_now+(h/6)*(k1+2*k2+2*k3+k4)
    theta_next=np.mod(theta_next, 2*np.pi)
    theta=np.r_[theta, theta_next.reshape(1, N)]
    t+=1

def update(i):
    plt.clf()
 
    circle=plt.Circle((0, 0), radius=1.0, fc='y')
    plt.gca().add_patch(circle)
 
    for j in range(theta.shape[1]):
        circles=plt.Circle((np.cos(theta[i, j]), np.sin(theta[i, j])), radius=0.05, fc='b')
        plt.gca().add_patch(circles)
     
    plt.xlim(-1.5, 1.5)
    plt.ylim(-1.5, 1.5)
    plt.axes().set_aspect('equal', 'datalim')

fig=plt.figure()
ani=animation.FuncAnimation(fig, update, frames=theta.shape[0])
ani.save('manyoscillation.gif', writer='imagemagick', fps=np.int(1/h))
--------------------------------------------------------

即固まった。

ところで蔵本モデルは弱結合を仮定しているのに逆行する様子がみられますが、振動子が多い場合にも逆行はタブーなんでしょうか。

2017年11月11日土曜日

蔵本モデルで遊ぶ

前に作った蔵本モデル(Nコ振動子のコードでN=2)で同期現象をちゃんと見ようということで初期の数値を変えて遊んでいた。
-----------------------------------------------------
#-*- coding:utf-8 -*-
# simulating oscillation by Kuramoto model
# N units

import numpy as np
import matplotlib.pyplot as plt

def theta_mat(theta):
    theta=theta.reshape(1, -1)
    theta_mat=theta.copy()
    while theta_mat.shape[0]<theta_mat.shape[1]:
        theta_mat=np.r_[theta_mat, theta]
    return theta_mat

#setting
theta=np.array([0, 0]).reshape(1, -1)  # start point after 'phase reset'
omega=np.array([0.3, 1.1])     # anglular velocity
N=theta.size
time=100       # measurement time
h=0.1        # micro time
K=np.array([[0, 0.8],[0.8, 0]])  # coupling strength(N*N)

t=0
while t*h<time:
    theta_now=theta[t, :].reshape(-1, 1)
    k1=(omega+np.sum(np.sin(theta_mat(theta_now)-theta_now)*K, 1)/N).reshape(-1, 1)
    theta4k2=theta_now+(h/2)*k1
    k2=(omega+np.sum(np.sin(theta_mat(theta4k2)-theta4k2)*K, 1)/N).reshape(-1, 1)
    theta4k3=theta_now+(h/2)*k2
    k3=(omega+np.sum(np.sin(theta_mat(theta4k3)-theta4k3)*K, 1)/N).reshape(-1, 1)
    theta4k4=theta_now+h*k3
    k4=(omega+np.sum(np.sin(theta_mat(theta4k4)-theta4k4)*K, 1)/N).reshape(-1, 1)

    theta_next=theta_now+(h/6)*(k1+2*k2+2*k3+k4)
    theta_next=np.mod(theta_next, 2*np.pi)
    theta=np.r_[theta, theta_next.reshape(1, N)]

    t+=1

axis=np.arange(theta.shape[0])*h
for i in range(N):
    la='theta'+np.str(i)
    plt.plot(axis, theta[:, i], label=la)

plt.title('oscilation model by kuramoto model with runge kutta method')
plt.xlabel('time')
plt.ylabel('position')
plt.legend()
plt.show()
-----------------------------------------------------
同期してそう。この時の2振動子の位相差をプロットする。
-----------------------------------------------------
dif=np.abs(theta[:, 0]-theta[:, 1])
for i in range(dif.shape[0]):
    if dif[i]>np.pi:
        dif[i]=2*np.pi-dif[i]

plt.plot(axis, dif, label='dif')
plt.show()
-----------------------------------------------------
差がある大きさに収束していく様子で同期していそうである。

次に、角速度の差を大きくしてみる。
omega=[0.3, 1.2]で実行。
-----------------------------------------------------


捕捉しきれず同期できていない。

ここで振動子2つの場合の蔵本モデルの式を確認する。
dΘ1/dt=ω1+(K/2)*sin(Θ2-Θ1)
dΘ2/dt=ω2+(K/2)*sin(Θ1-Θ2)

同期した場合2振動子の速度が等しくなるので

dΘ1/dt-dΘ2/dt=ω1-ω2-K*sin(Θ1-Θ2)=0
から
ω1-ω2=K*sin(Θ1-Θ2)
正弦波は-1~1の値なので
|ω1-ω2|≦K
であれば同期できるということになる。

とはいえルンゲクッタ法の誤差もあるし、いっぱいやれば同期しなくなるンでは?と思い、omega=[0.3, 1.1], time=10000で実行。



おお、同期している。すごーい!上の図はもうただの長方形にしか見えんな。

振動子の動きを円周上でプロットするgifを作ろうとしていたのだけれど、matplotlibがあまりに苦手で実装できなかったでござる。蔵本モデルならこんな感じでもいいんだけど、二重振り子やろうとするならやはりanimationをできるようにならんとなァといったところです。

(追記)
誤差少しできたところでまた収束の方向に向かうんだからそらそうか

2017年11月8日水曜日

N振動子で蔵本モデル

マッチョにkを求めるスタイルは変わらず。そこでループ使って表したとてあまりすっきりしない気がした故。

--------------------------------------------------------
# simulating oscillation by Kuramoto model
# N units

import numpy as np
import matplotlib.pyplot as plt

def theta_mat(theta):
theta=theta.reshape(1, -1)
theta_mat=theta.copy()
while theta_mat.shape[0]<theta_mat.shape[1]:
theta_mat=np.r_[theta_mat, theta]
return theta_mat

#setting
theta=np.array([0, np.pi/2, np.pi]).reshape(1, -1) # start point
omega=np.array([0.3, 1, 0.6]) # anglular velocity
N=theta.size
time=400 # measurement time
h=0.1 # micro time
K=np.array([[0, 0.4, 0.6],[0.4, 0, 0.7],[0.6, 0.7, 0]]) # coupling strength(N*N)

t=0
while t*h<time:
theta_now=theta[t, :].reshape(-1, 1)
k1=(omega+np.sum(np.sin(theta_mat(theta_now)-theta_now)*K, 1)/N).reshape(-1, 1)
theta4k2=theta_now+(h/2)*k1
k2=(omega+np.sum(np.sin(theta_mat(theta4k2)-theta4k2)*K, 1)/N).reshape(-1, 1)
theta4k3=theta_now+(h/2)*k2
k3=(omega+np.sum(np.sin(theta_mat(theta4k3)-theta4k3)*K, 1)/N).reshape(-1, 1)
theta4k4=theta_now+h*k3
k4=(omega+np.sum(np.sin(theta_mat(theta4k4)-theta4k4)*K, 1)/N).reshape(-1, 1)

theta_next=theta_now+(h/6)*(k1+2*k2+2*k3+k4)
theta_next=np.mod(theta_next, 2*np.pi)
theta=np.r_[theta, theta_next.reshape(1, N)]

t+=1

axis=np.arange(theta.shape[0])*h
for i in range(N):
la='theta'+np.str(i)
plt.plot(axis, theta[:, i], label=la)

plt.title('oscilation model by kuramoto model with runge kutta method')
plt.xlabel('time')
plt.ylabel('position')
plt.legend()
plt.show()
--------------------------------------------------------

今までのイメージは「小惑星に別の小惑星が近づいてきてスイングバイする」ようなもの。そのため、青線がゆるやかになるタイミングが若干早くない?と思ったのだがそれは間違い。蔵本モデルでは角速度に影響を与えるのはsinの位相差なので、位相差が垂直つまり±pi/2で大きいのであった。

(11/9 こっそり修正した)
(11/11 またも修正した) 

2017年11月7日火曜日

2振動子で蔵本モデル

某所で蔵本モデルをルンゲクッタ法を用いてシミュレーションしていたのだが、そんなに難しくなさそうなのでPythonで実装してみることにした。

困ったのは、ルンゲクッタ法にも色々種類があるようだということ。とっかかりなので一番簡単そうな古典的ルンゲクッタ法を用いることにする。
とりあえず振動子2つ版を実装。順繰りにマッチョにkを求める。

今後は実習の合間を使って、ベクトル形式にしてきれいにしたり、複雑化させていこうと思う。
----------------------------------------------------------
# simulating oscillation by Kuramoto model
# 2 unit

import numpy as np
import matplotlib.pyplot as plt

#setting
theta=np.array([0, np.pi]).reshape(1, 2) # start point
omega=np.array([1, 1]) # anglular velocity
time=100 # measurement time
h=0.1 # micro time
K=0.4 # coupling strength

t=0
while t*h<time:
theta_now=theta[t, :]
k1=omega+K*np.sin(theta_now[::-1]-theta_now)
theta4k2=theta_now+(h/2)*k1
k2=omega+K*np.sin(theta4k2[::-1]-theta4k2)
theta4k3=theta_now+(h/2)*k2
k3=omega+K*np.sin(theta4k3[::-1]-theta4k3)
theta4k4=theta_now+h*k3
k4=omega+K*np.sin(theta4k4[::-1]-theta4k4)

theta_next=theta_now+(h/6)*(k1+2*k2+2*k3+k4)
theta_next=np.mod(theta_next, 2*np.pi)
theta=np.r_[theta, theta_next.reshape(1, 2)]

t+=1

axis=np.arange(theta.shape[0])*h
plt.plot(axis, theta[:, 0], label='theta1')
plt.plot(axis, theta[:, 1], label='theta2')
plt.title('oscilation model by kuramoto model with runge kutta method')
plt.xlabel('time')
plt.ylabel('position')
plt.legend()
plt.show()
----------------------------------------------------------

すぐ終わりそう。(理解できる範囲が狭いことによる)
これ終わったら二重振り子やります。

2017年10月11日水曜日

2週間休み

明日からは平日の夕方以降がすべて某作業に忙殺されるため、学習は何も出来ないし休み時間もない。2週休みをうまく活用できたかと言われると疑問だが、まぁ休んだのなら休んだでいいのだろう。さて、この2週間は

・ポスター作った
・3連休だらだらした
・ポスター修正した
・UdemyのPyTorch講座をやった
・そこでjupyterの気持ちよさを知る
・ポスター修正した
・jupyterで何かしたい
・jupyterを使うために複雑ネットワーク解析関連を気分転換に実装しなおした。

PyTorch講座は、以前Chainer入門しようとしたが断念していたのでその埋め合わせ。結局のところ型どおりぶち込めばやってくれるっていうことですね、という程度の理解で視聴終了しました。
特にdeeplearningやる機会もなさそうなのでまた必要になったらやります。

で、jupyter欲を発散するためにネットワーク解析をまた実装した次第。
(後日追記)barabasi-albertモデルはググって出てきたものを実装したけど実際には違うらしいので修正します。
--------------------------------------------------------
#-*- coding:utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
inf=np.float('inf')
global inf

def display_net(matrix):
    matrix=pathnet2connet(matrix)
    graph=nx.from_numpy_matrix(matrix)
    nx.draw(graph)
    plt.show()

def degree(matrix):
    matrix=pathnet2connet(matrix)
    return np.sum(matrix, 1)

def dykstra_matrix(matrix, start):
    matrix=connet2pathnet(matrix)
 
    end=np.zeros(matrix.shape[0])+inf
    pre_end=end.copy()
    end[start]=0
 
    while np.sum(end==pre_end)!=end.shape[0]:
        pre_end=end.copy()
        length=matrix+end.reshape(matrix.shape[0], 1)
        length[:, end!=inf]=inf
        if np.min(length)!=inf:
            end[np.argmin(length)%matrix.shape[0]]=np.min(length)
 
    return end

def arange(n):
    a=[]
    for i in range(n):
        a.append(i)
 
    return a

def list2matrix(list, n):
    list=np.array(list)
    matrix=np.zeros((n, n))
    for i in range(list.shape[0]):
        matrix[np.int(list[i, 0]), np.int(list[i, 1])]=1
 
    matrix=matrix+matrix.T
    return matrix

def matrix2list(matrix):
    matrix=pathnet2connet(matrix)
    list=[]
    for j in range(matrix.shape[0]):
        for i in range(j):
            if matrix[i, j]>0:
                list.append([i, j])
    return list

def pathnet2connet(matrix):
    matrix[matrix==inf]=0
    return matrix

def connet2pathnet(matrix):
    matrix[matrix==0]=inf
    for i in range(matrix.shape[0]):
        matrix[i, i]=0
 
    return matrix

def mk_WSmodel(n, k, p):
    #Watts-Strogatz modelのランダムネットワーク生成
    #input
    #n: ノード数
    #k: 次数
    #p: リンク張り替え確率
 
    matrix=mk_extended_cycle(n, k)
    matrix=change_link(matrix, p)
    matrix[matrix>0]=1
    return matrix

def mk_extended_cycle(n, k):
    #拡張サイクルモデルを作成する関数
    #input
    #n: ノード数
    #k: 次数(つまり前後にk/2本のリンクが張られる)
 
    #output: n*nの隣接行列
    matrix=np.zeros((n, n))
    k_half=np.int(k/2)
    for i in range(k_half):
        matrix[i, (n-k_half+i):]=1
        matrix[i, 0:i]=1
 
    i=k_half
 
    while i<n:
        matrix[i, (i-k_half):i]=1
        i=i+1
     
    matrix=matrix+matrix.T
    return matrix

def change_link(matrix, rate):
    n=matrix.shape[0]
    list=matrix2list(matrix)
    list=np.array(list)
 
    for i in range(list.shape[0]):
        edge=np.random.choice([0, 1], p=[0.5, 0.5])
        probability=[]
        for j in range(n):
            probability.append(rate/(n-2))
     
        probability[np.int(list[i, edge])]=1-rate
        probability[np.int(list[i, -(edge-1)])]=0
        num=arange(n)
        candidate=np.random.choice(num, p=probability)
        list[i, edge]=candidate
 
    matrix=list2matrix(list, n)
    return matrix

def cal_L(matrix):
    matrix=connet2pathnet(matrix)
    mean_length=np.zeros(matrix.shape[0])
    n=mean_length.shape[0]
 
    for i in range(n):
        mean_length[i]=np.sum(dykstra_matrix(matrix, i))/(n-1)
 
    L=np.mean(mean_length)
    return L

def cal_C(matrix):
    k=degree(matrix)
    t=[]
    for i in range(matrix.shape[0]):
        if k[i]>1:
            t.append(triangle(matrix, i))
        else:
            t.append(0)
            k[i]=2
 
    t=np.array(t)
    c=2*t/(k*(k-1))
    C=np.mean(c)
    return C

def triagle(matrix, i):
    counter=0
    matrix=pathnet2connet(matrix)
    n=matrix.shape[0]
    for j in range(n):
        for k in range(n):
            counter+=(matrix[i, j]*matrix[j, k]*matrix[k, i]>0)
    counter/=2
    return counter

def mk_random_network(n, l):
    list=[]
 
    i=2
    while i<n:
        counter=1
        while counter*i<=n:
            list.append(link_half2half((counter-1)*i, counter*i, i/2))
            counter=counter+1
     
        if (n-(counter-1)*i)>(i/2):
            list.append(link_half2half((counter-1)*i, n, i/2))
     
        i=i*2
 
    list.append(link_half2half(0, n, i/2))
 
    list=np.array(list)
    matrix=list2matrix(list, n)
 
    matrix=addlink(matrix, np.int(l-list.shape[0])   )   
     
    return matrix

def link_half2half(start, end, half):
    a=np.random.choice(np.arange(start, start+half))
    b=np.random.choice(np.arange(start+half, end))
    return [a, b]

def addlink(matrix, l):
    matrix=connet2pathnet(matrix)
    candidate=[]
    for j in range(matrix.shape[0]):
        for i in range(j):
            if matrix[i, j]==inf:
                candidate.append([i, j])
 
    candidate=np.array(candidate)
    list=np.random.choice(np.array(candidate).shape[0], l, replace=False)
    list=np.array(list)
 
    for i in range(list.shape[0]):
        x=candidate[np.int(list[i]), 0]
        y=candidate[np.int(list[i]), 1]
        matrix[x, y]=1
        matrix[y, x]=1
 
    return matrix

def smallworldness(matrix):
    count=100
    n=matrix.shape[0]
    matrix[matrix!=1]=0
    l=np.sum(matrix)/2
    S=(cal_C(matrix)/c_rand(n, l, count))/(cal_L(matrix)/l_rand(n, l, count))
    return S

def c_rand(n, l, count):
    c=0
    for i in range(count):
        c+=cal_C(mk_random_network(n, l))
 
    c/=count
    return c

def l_rand(n, l, count):
    l=0
    for i in range(count):
        l+=cal_L(mk_random_network(n, l))
 
    l/=count
    return l

def mk_BAmodel(m0, m, N):
    matrix=np.zeros((N, N))
    matrix[0:m0, 0:m0]=1
    for i in range(m0):
        matrix[i, i]=0

    i=m0:
    while i<N:
        probability=degree(matrix)
        probability=probability/np.sum(probability)
        list=np.random.choice(np.arange(N), m, p=probability)
        for j in range(m):
            matrix[i, list[j]]=1
            matrix[list[j], i]=1

        i=i+1

    return matirx

def mk_modifiedBAmodel(N):
    list=np.array([0, 1]).reshape(1, -1)
    n=2
 
    while n<N:
        matrix=list2matrix(list, n)
        d=degree(matrix)
        probability=d/np.sum(d)
        selection=np.random.choice(arange(n), p=probability)
        list=np.r_[list, np.array([n, selection]).reshape(1, -1)]
        n+=1
 
    matrix=list2matrix(list, n)
    return matrix
-----------------------------------------------
続いて検証。
Watts-Strogatzモデルのpを変化させた時のcharacteristic path lengthとclustering coefficientの推移をみる。
-----------------------------------------------
list=np.arange(0, 0.4, 0.05)
time=5
n=100
k=8
l=n*k/2
C_result=[]
L_result=[]

for p in list:
    C=0
    L=0
    for t in range(time):
        model=mk_WSmodel(n, k, p)
        C+=cal_C(model)/time
        L+=cal_L(model)/time
 
    C/=c_rand(n, l, time)
    L/=l_rand(n, l, time)
    C_result.append(C)
    L_result.append(L)

df1=pd.DataFrame({'p-value': list, 'clustering coefficient': C_result})
df2=pd.DataFrame({'p-value': list, 'characteristic path length': L_result})
plt.plot('p-value', 'clustering coefficient', data=df1)
plt.plot('p-value', 'characteristic path length', data=df2)
plt.show()
-----------------------------------------------
合ってそう。
次修正Barabasi-Albertモデル。アルゴリズム的にclustering coefficientはゼロなので、まぁグラフ見てなんとなく合っていればとりあえずいいか。
-----------------------------------------------
display_net(mk_modifiedBAmodel(40))
-----------------------------------------------
良さげ。
次数分布と次数相関係数も求めてみる。
-----------------------------------------------
def degree_distribution(matrix):
    deg=degree(matrix)
    result=np.zeros(np.int(np.max(deg)))
    for i in range(result.shape[0]):
        result[i]=np.sum(deg==(i+1))
 
    return result

def assortativity(matrix):
    #assortativity公式を(A-C)/(B-C)と見立ててそれぞれ求める
    #前準備
    matrix=pathnet2connet(matrix)
    N=matrix.shape[0]
    M=np.sum(matrix)
    A=0
    B=0
    C=0
 
    #先にdegreeを求めておく
    degree_vector=degree(matrix)
 
    #まずAから
    A=np.sum(np.dot(degree_vector, degree_vector.T)*matrix)/(4*M)
 
    #次B
    #i, jノードのそれぞれの2乗の和を(i,j)要素にもつ行列sum_sqを作成
    sq_degree=degree_vector*degree_vector
    sum_sq=ij_sum(sq_degree)
    B=np.sum(sum_sq*matrix)/(2*M)
 
    #次C
    ijsum=ij_sum(degree_vector)
    C=(np.sum(ijsum*matrix)/(2*M))**2
 
    assortativity=(A-C)/(B-C)
    return assortativity
 
#引数ベクトルのi番目、j番目の要素の和を(i, j)に持つ行列を返す
def ij_sum(vector):
    n=vector.shape[0]
    ij_sum=np.zeros((n, n))
 
    for i in range(n):
        for j in range(n):
            ij_sum[i, j]=vector[i]+vector[j]
 
    return ij_sum
-----------------------------------------------
assortatibityに関して、リンク数は重複カウントするのかどうかが微妙。とりあえず全部カウントすることにして実装した。真偽は定かでない。
-----------------------------------------------
N=300
total=np.zeros(N-1)
for i in range(100):
    model=mk_modifiedBAmodel(N)
    result=degree_distribution(model)
    for j in range(result.shape[0]):
        total[j]+=result[j]
 

total/=100
list=np.arange(299)


df=pd.DataFrame({'degree': list[0:10], 'count': total[0:10]})
plt.plot('degree', 'count', data=df)
plt.show()
assortativity(model)
-----------------------------------------------
5.2548947026591675