クモの巣図法
指数的成長モデルとロジスティックモデル(2011/2/19)のつづき。
ロジスティックモデルはどの初期値から始めてもフィードバックループをまわすと最終的に0.5に引き込まれることがわかる。この引き込まれる軌道を視覚的にグラフ化したのがクモの巣図法。まず、指数モデルでクモの巣図法を描いてみた。
#coding:utf-8 import numpy as np from pylab import * import matplotlib.lines as lines """クモの巣図法を描画""" def drawGraph(func): """関数funcを描画""" xList = [] yList = [] for x in np.arange(-1.0, 1.0, 0.01): xList.append(x) yList.append(func(x)) plot(xList, yList) def drawCobweb(func, initial): """funcの軌道に対するクモの巣図法を描画""" vertices = [] # 初期座標 x = initial y = 0 vertices.append([x, y]) for n in range(1, 13): # 垂直方向 y = func(x) vertices.append([x, y]) # 水平方向 x = y vertices.append([x, y]) vertices = np.array(vertices) plot(vertices[:,0], vertices[:,1], '--') if __name__ == "__main__": # y = xを描画 drawGraph(lambda x: x) # y = 2xを描画 drawGraph(lambda x: 2 * x) # 初期値を変えてクモの巣図法を描画 drawCobweb(lambda x: 2 * x, 0.01) axis([-0.2, 1.0, -1.0, 1.0]) grid(True) show()
クモの巣図法では、対象の関数fを とともに描く。任意の初期値 x = 0.01 から初めてまず上に垂直線をひく、fと接したら にぶつかるまで水平に線を引く(これは、出力値f(x)をフィードバックさせて新たなxにすることを意味する)。これをずっと繰り返すだけ。指数モデルでは、どこにも引き込まれず発散してしまう様子がわかる。次にロジスティックモデル。
前回、書いたようにフィードバックループを繰り返すと0.0から1.0のどの初期値から初めても最終的に0.5に引き込まれる。これをクモの巣図法で描くと、
#coding:utf-8 import numpy as np from pylab import * import matplotlib.lines as lines """クモの巣図法を描画""" def drawGraph(func): """関数funcを描画""" xList = [] yList = [] for x in np.arange(-0.1, 1.0, 0.01): xList.append(x) yList.append(func(x)) plot(xList, yList) def drawCobweb(func, initial): """funcの軌道に対するクモの巣図法を描画""" vertices = [] # 初期座標 x = initial y = 0 vertices.append([x, y]) for n in range(1, 13): # 垂直方向 y = func(x) vertices.append([x, y]) # 水平方向 x = y vertices.append([x, y]) vertices = np.array(vertices) plot(vertices[:,0], vertices[:,1], '--') if __name__ == "__main__": # y = xを描画 drawGraph(lambda x: x) # y = 2x(1-x)を描画 drawGraph(lambda x: 2 * x * (1 - x)) # 初期値を変えてクモの巣図法を描画 for initial in np.arange(0.0, 1.0, 0.2): drawCobweb(lambda x: 2 * x * (1 - x), initial) axis([0.0, 1.0, 0.0, 0.6]) show()
どのxから初めても最終的に座標 (0.5, 0.5) に引き込まれることがわかる。この軌道には経験則があり、グラフが対角線 の上にあれば軌道は右に動き、対角線の下にあれば軌道は左に動く。f(p) = pのとき、点pは不動点と呼ばれる。不動点は、y = f(x) と y = xの連立方程式を解くことで求められる(つまり、関数f(x)と直線の交点)。上の場合、x = 0とx = 0.5が不動点(yの値はxと同じなので無視)。例1.3の も描いてみた。
#coding:utf-8 import numpy as np from pylab import * import matplotlib.lines as lines """クモの巣図法を描画""" def drawGraph(func): """関数funcを描画""" xList = [] yList = [] for x in np.arange(-2.0, 2.0, 0.01): xList.append(x) yList.append(func(x)) plot(xList, yList) def drawCobweb(func, initial): """funcの軌道に対するクモの巣図法を描画""" vertices = [] # 初期座標 x = initial y = 0 vertices.append([x, y]) for n in range(1, 13): # 垂直方向 y = func(x) vertices.append([x, y]) # 水平方向 x = y vertices.append([x, y]) vertices = np.array(vertices) plot(vertices[:,0], vertices[:,1], '--') if __name__ == "__main__": # y = xを描画 drawGraph(lambda x: x) # y = (3x-x^3)/2を描画 f = lambda x: (3 * x - x ** 3) / 2 drawGraph(f) # 初期値を変えてクモの巣図法を描画 drawCobweb(f, 1.6) drawCobweb(f, 1.8) axis([-2.0, 2.0, -2.0, 2.0]) grid(True) show()
不動点には、沈点(吸引的不動点)と源点(反発的不動点)の2種類がある。下の図では不動点は、-1.0, 0.0, 1.0の3個ある。-1.0と1.0に近い点(例では-1.2と0.9)は-1.0、1.0に吸引されるのに対し、0.0に近い点(例では-0.2と0.2)は0.0から離れていく。そんなわけで-1.0と1.0は沈点で0.0は源点と呼ばれる。沈点はボールが安定する谷底で源点はボールが不安定な山頂をイメージすればいい。