In [1]:
# git による管理
# http://ni66ling.hatenadiary.jp/entry/2018/01/02/022905

from sympy import *
from sympy.plotting import plot
from IPython.display import display
init_printing(use_latex='mathjax')



X = Matrix([
    [Rational(3,1),0,0],
    [0,Rational(3,1),0],
    [0,0,Rational(3,1)]
])

Y = Matrix([
    [0,Rational(1,1),Rational(2,1)],
    [Rational(1,1),0,Rational(1,1)],
    [Rational(2,1),Rational(2,1),0]
])

'''
X = Matrix([
    [Rational(3,1),0,0,0],
    [0,Rational(3,1),0,0],
    [0,0,Rational(3,1),0],
    [0,0,0,Rational(3,1)],
])

Y = Matrix([
    [0,Rational(1,1),Rational(1,1),0],
    [Rational(2,1),0,Rational(2,1),2],
    [Rational(0,1),Rational(1,1),0,1],
    [Rational(1,1),Rational(1,1),Rational(0,1),0]
])
'''

print("供給行列")
display(X)
print("需要行列")
display(Y)

A=Y-X # Xp=Yp を解く
p1, p2, p3 = symbols('p1, p2, p3')
#p1, p2, p3,p4 = symbols('p1, p2, p3, p4')
p = Matrix([[p1],[p2],[p3]])
#p = Matrix([[p1],[p2],[p3],[p4]])
eqivprice = solve(A*p,p) 
ep = [eqivprice[p1]/p3,eqivprice[p2]/p3,p3/p3]
#ep = [eqivprice[p1]/p4,eqivprice[p2]/p4,eqivprice[p3]/p4,p4/p4]
print("各自の収入=支出となるような価格ベクトル =")
display((ep))
print("交換比率は、価格の逆数。\nリンネル{} <=> 上衣{} <=> 茶{},つまり...".format(1/ep[0],1/ep[1],1/ep[2]))
display((1,ep[0]/ep[1],ep[0]/ep[2]))
#display((1,ep[0]/ep[1],ep[0]/ep[2],ep[0]/ep[3]))


def exchange(w1,i,j,l,m):# (i,j)が、(l,m)から、m財をw1だけ取得
    xrate = ep[m]/ep[j]
    w2 = w1*xrate #(i,j) が交換で相手に与えるj財の量
    X[i,m] += w1 # i が需要する
    X[l,m] += -w1 #lが供給する
    X[i,j] += -w2 #iが供給
    X[l,j] += w2 #lが需要 
    man = ['A','B','C','D','E']
    ware = ['リンネル','上衣','茶','砂糖','鉄']
    print("{}{}:{}単位が、{}{}:{}単位と、1:{}の比率で交換される".format(man[i],ware[j],w2,man[l],ware[m],w1,xrate))
    display(X)

print("\n<<交換開始>>")

'''
交換のプロセスをプログラミング
    A,B,C,... と順に自分の需要をみたす
        - B->A という交換はなし B->C,D,...のみ
        - 自分の余剰の状態をチェックして、その財kを記憶する。
            --TODO:初期値では対角要素だが、交換のプロセスで別のように変わる可能性があるので注意
            --TODO:変わっても余剰財は1種類だと仮定してコーディングしてある。ここにバグの可能性?
            --TODO:対策 余剰財のリストをつくっておいて、A[i,k1]で足りなければA[i,k2].... 
            --TODO:とすればよいが面倒
        - 自分の不足分A[i,m]をA[0,m] から下に向かって探してゆき
        - この人l が見つかったら exchange 関数をよぶ。
        - exchange(A[i,m],i,k, l,m) :不足分A[i,m]を、(i,k)財を渡して、(l,m)財と得る
'''
(r,c) = Y.shape
for i in range(r-1): # A,B,C,.. の順に需要を満たしてゆく(最後は予定調和的に満たされる)
    A = Y - X # 過不足をしめす行列をreset
    for j in range(c):
        if A[i,j] < 0:# 余剰がある財(初期値では対角要素だが、ズレる可能性があるのでチェック。注意!)
            k =j
    for m in range(c): #リンネル、上衣、茶...... の順に みていって         
        if A[i,m] > 0:# もしm 財の交換が必要なら
            for l in range(r):# m財をもっている人たちの保有状態を順にあたってゆき
                if A[l,m] < 0 : #マイナスなら余剰をもっているということになるので、
                    exchange(A[i,m],i,k,l,m) #自分の余剰財(i,k) を、この人の余剰財 (l,m) と交換して、A[i,m]を手に入れる。
                        #A[i,k] ->A[l,k] and A[l,m] -> A[i,m]  というタテ方向の財の移動


           
'''
print("アプローチ:主体ベースで(行ごとに)需給調整を考える")
#Aがリンネルで上衣を手に入れる
w1 = Y[0,1] - X[0,1]
exchange(w1,0,0,1,1)
#Aがリンネルで茶を手に入れる
w1 = Y[0,2] - X[0,2]
exchange(w1,0,0,2,2)
#Bが上衣で、Cからリンネルを手に入れる
w1 = Y[1,0] - X[1,0]
exchange(w1,1,1,2,0)
#Bが砂糖を、Cから手に入れる
w1 = Y[1,2]-X[1,2]
exchange(w1,1,1, 2,2)
'''

print("<<完了>>")
供給行列
$$\left[\begin{matrix}3 & 0 & 0\\0 & 3 & 0\\0 & 0 & 3\end{matrix}\right]$$
需要行列
$$\left[\begin{matrix}0 & 1 & 2\\1 & 0 & 1\\2 & 2 & 0\end{matrix}\right]$$
各自の収入=支出となるような価格ベクトル =
$$\left [ \frac{7}{8}, \quad \frac{5}{8}, \quad 1\right ]$$
交換比率は、価格の逆数。
リンネル8/7 <=> 上衣8/5 <=> 茶1,つまり...
$$\left ( 1, \quad \frac{7}{5}, \quad \frac{7}{8}\right )$$
<<交換開始>>
Aのリンネル:5/7単位が、Bの上衣:1単位と、1:5/7の比率で交換される
$$\left[\begin{matrix}\frac{16}{7} & 1 & 0\\\frac{5}{7} & 2 & 0\\0 & 0 & 3\end{matrix}\right]$$
Aのリンネル:16/7単位が、Cの茶:2単位と、1:8/7の比率で交換される
$$\left[\begin{matrix}0 & 1 & 2\\\frac{5}{7} & 2 & 0\\\frac{16}{7} & 0 & 1\end{matrix}\right]$$
Bの上衣:2/5単位が、Cのリンネル:2/7単位と、1:7/5の比率で交換される
$$\left[\begin{matrix}0 & 1 & 2\\1 & \frac{8}{5} & 0\\2 & \frac{2}{5} & 1\end{matrix}\right]$$
Bの上衣:8/5単位が、Cの茶:1単位と、1:8/5の比率で交換される
$$\left[\begin{matrix}0 & 1 & 2\\1 & 0 & 1\\2 & 2 & 0\end{matrix}\right]$$
<<完了>>