見出し画像

富の分配シミュレーション with MATLAB

富の分配シミュレーション

 ツイッターで100人が所持金100万円からスタートして、他者にランダムでお金を1万円渡すのを繰り返すとガウスではなく、べきの分布になるという記事を見つけ(尚執筆時に探したが、どのTweetか見つけられませんでした。。。みつけた方や行った方がいましたらコメント下さい。)、不思議だなぁと感じ、ちょっとMATLABで実装してみようと思い実装に。
 このシミュレーションを作っている内に気になったこととして、富の分配の仕方に異方性を与えたら、どのように富が推移するのかという点が気になり、そこを中心に調べてみました。具体的に異方性とは、

1.高所得者から低所得者にお金を流す場合
2.低所得者から高所得者にお金を流す場合
3.所得に関係なくお金を回す場合

の3つのパターンが考えられます。今回は先に掲げた3条件において下記のプログラムの通り富の分配を行ってみました。

コードのスクショ(コードの最も可読性の高いnoteにおける表示方法が知りたい) 

%% お金の分配によってどのように所得分布が変化するのかを理解するためのシミュレーション

clear
InitialMoney=550;
PersonTotalNum=10000;
%StockedMoney=abs(randn(PersonTotalNum,1))*InitialMoney;
StockedMoney=ones(PersonTotalNum,1)*InitialMoney;
% dum=abs(randn(PersonTotalNum/2,1))*(InitialMoney)+800;
% StockedMoney=cat(1,StockedMoney,dum)
TotalTradingNum=1000000;

%動画出力するために Computure visionが必要
VPlayer=vision.VideoPlayer("Position",[0 0 [700 525]]);
MovieFileName=strcat("Results",datestr(datetime("now"),30));
GifFileName=strcat("Results",datestr(datetime("now"),30),".gif");
VData=VideoWriter(MovieFileName,"MPEG-4");
VData.FrameRate=10;
open(VData);
%ここまで動画作成準備

TradingMoney=55;
ShowInterval=TotalTradingNum/100;%毎回出力すると結構時間がかかるので短縮のため
InitialTotalMoney=sum(StockedMoney);
%分配をミスると初期金額が保存されなくなる。将来的には保存されないほうが良い?
%% 
% 下ごしらえが完了したので、実際にシミュレーションを回す。

DistributionMethod=2;
% DistributionMethod= 0:高所得者から低所得者側への分配のみを行う(異方分配)。
% 1:自由に分配する(等方分配)。
FramesNum=0;

for i=1:TotalTradingNum
   
   %次のコードは誰からお金をむしり取り、誰に渡すかを決める。
   GiveIndex=randi(PersonTotalNum,1);
   TakeIndex=randi(PersonTotalNum,1);
   
   %同じ人間からむしり取って、同じ人間に戻すのを禁じる。
   while GiveIndex==TakeIndex
       TakeIndex=randi(PersonTotalNum,1);
       GiveIndex=randi(PersonTotalNum,1);
   end

   %TradingMoney以上のお金を持っている人から金をむしり取れる場合
   if StockedMoney(GiveIndex)>=TradingMoney
       switch DistributionMethod
           
           %高所得者から低所得者の方向にのみ金を渡す。
           case 0
               
               if StockedMoney(GiveIndex)>=StockedMoney(TakeIndex)
                   
                   StockedMoney(GiveIndex)=StockedMoney(GiveIndex)-TradingMoney;
                   StockedMoney(TakeIndex)=StockedMoney(TakeIndex)+TradingMoney;
                   
               end

           %低所得者から高所得者の方向にのみ金を渡す。
           case 1
               
               if StockedMoney(GiveIndex)<=StockedMoney(TakeIndex)
                   
                   StockedMoney(GiveIndex)=StockedMoney(GiveIndex)-TradingMoney;
                   StockedMoney(TakeIndex)=StockedMoney(TakeIndex)+TradingMoney;
                   
               end
               
           %低所得者、高所得者関係なくむしり取り、自分以外の誰かに渡す。
           case 2

               StockedMoney(GiveIndex)=StockedMoney(GiveIndex)...
                   -TradingMoney;
               StockedMoney(TakeIndex)=StockedMoney(TakeIndex)...
                   +TradingMoney;
       end
   end
   
   %分布の描画と動画としての記録
   if mod(i,ShowInterval)==0  || i==1
       
       FramesNum=FramesNum+1;
       
       %紙幣を刷る行為
       %StockedMoney=StockedMoney+10;
       
       FigHist=histogram(StockedMoney,"BinWidth",TradingMoney,...
           "Normalization","probability","EdgeColor",'none');
       
       xlabel('Money');
       ylabel('Probability');
       
       switch DistributionMethod
           case 0
               annotation("textbox",[0.3 0.8 0.20 0.2],"String",...
                   strcat('異方分配 High to Low TCounts = '," ",num2str(i)),...
                   "FitBoxToText","on","FontSize",14,"EdgeColor","none");

           case 1
               annotation("textbox",[0.3 0.8 0.20 0.2],"String",...
                   strcat('異方分配 Low to High TCounts = '," ",num2str(i)),...
                   "FitBoxToText","on","FontSize",14,"EdgeColor","none");
           case 2
               annotation("textbox",[0.3 0.8 0.20 0.2],"String",...
                   strcat('等方分配 Low <=> High TCounts = '," ",num2str(i)),...
                   "FitBoxToText","on","FontSize",14,"EdgeColor","none");

       end
       set(gca,"FontSize",14);
       Image=getframe(gcf);
       [IMind,cm]=rgb2ind(Image.cdata,256);
       step(VPlayer,Image.cdata);        
       writeVideo(VData,Image.cdata);
       if FramesNum==1
           imwrite(IMind,cm,GifFileName,"gif","LoopCount",inf);
       else
           imwrite(IMind,cm,GifFileName,"gif","WriteMode","append","DelayTime",1/VData.FrameRate);
       end
   end
end

%%
FinalTotalMoney=sum(StockedMoney)
release(VPlayer);
close(VData);

結果2
低所得者から高所得者へのみ富を分配する場合

まず予想どおりだったものから提示。条件は低所得者から高所得者へ分配を行う場合をシミュレート。この場合は二極化どころか高所得者側は青天井でどんどん儲けを増やし、低所得者の割合が尋常じゃなく増えるような形となりました。(むしろ現実に近い?)もちろんこのため、このモデルでは最も格差が広がります。
以下は動画になります。

結果3
高所得者だろうが低所得者だろうが均等に分配

次に等方分配の場合、初期の予想では結局ガウス分布になるのでは?と予想していましたが実はそうなりません。この場合分配初期においては確かにガウスに近いですが、このピーク位置は必ず低所得者側にシフトしていきます。つまり、低所得者がどんどん増えるようになります。このため、このような等方分配法では格差は必ず増加するということが予想出来ます。この場合格差増加率は結果2より小さいものの、経時的に増えていくことがわかりました。また、このような分布となるのはある種0~TradingMoneyまでの所得しか持っていない人からはお金を受け取らないという境界条件により、生じていると思います。

結果1
高所得者側から低所得者側へのみ富を分配する場合

あえて最後にこの結果を持ってきました。正直この結果が一番不思議に感じました。これは常にお金を与える側は高所得者から低所得者という縛りを加えた状況でどのように分布が推移しているのかを観察した例です。この例では、高所得者は常に低所得者にお金を流すから、分布としては低所得者が高く、高所得者が少なくなっていくような分布になると予想していましたが、分布はガウスとなり高所得にも低所得にも等方的な分布となりました。

まとめ

一見このように、別け隔てなく分配を行う等方分配が最も平等な分配方法に感じますが、実はそうではないというシミュレーション結果が現れました。むしろ富の分布において格差をへらすのであれば、高所得者から低所得者への富の分配を行うことで格差が最も小さくなります。当たり前のように感じますが、ここまで分布が一定になるとは予想していませんでした。

今後やってみたいこと

今回のモデルは最初に持っている資産がすべて同じからスタートしています。それに対して、資産は皆一定ではないため、初期に複数の資産分布を持っている場合に上記の分配を行うとどのように富の分布が変化するかを調べてみたいです。また、今回は回るお金が一定という仮定を置きましたが、現実には紙幣の発行などがあり一定ではありません。それらの条件も加味してシミュレーションを行ってみたいです。



この記事が気に入ったらサポートをしてみませんか?