2017年6月27日火曜日

働きたくないので働かないアリのシミュレーション(もどき)

突然ですが,働きたくないんです.ないんです働きたく.

働いている人なら大体共感していただけると思うのですが,「俺は仕事大好きでさ,もう生きがい!!」なんて人はそんなにはいないんじゃないかと思います.皆毎日行きたくない職場へ行って,したくない仕事をしている面が少なからずあると思います.でも,私の働きたくなさはそんなもんではありません.よく,人よりちょっと顔が大きい人や,大きなほくろが顔にある人,目が大きい人なんかがいますね.あんな感じで,私は人よりも「仕事をしたくない」という感情が強いようです.この事は働き出してから気が付いたことで,理由は分かりません.これは,今やっている業種に不満があるとか,そういうことに原因があるわけではありません.「仕事」という営みをしたくないんです.だから,例えば今の職場を退職して,もっと「自分に向いている!!天職だ!!」と思う職業に就いたとしても,同じように仕事をしたくないと思うのでしょう.

そんなことを職場のデスクで考えていたら,以前のNHK 教育テレビ「サイエンスZERO」で働きアリについての研究が取り上げられていたのを思い出しました.

働きアリの中に一部働かないアリが発生するのは何故なのか?

そう,あるアリの一族の働きアリの中に,全く働かない,怠け者のアリがいるのです.これ,シフト制で一部のアリが交代で休憩しているのかと思いきや,そうではない.必ず決まったアリが働いていないのです.更に,驚くべきは,この一族から働かないアリだけを取り除いた時,全てのアリが働くようになりそう(働かないアリはいなくなった訳だから)ですが,そうではない.それまで働きアリであったアリの中から,働かないアリが発生するのです.

この事はそこそこ昔から知られていたことでしたが,その理由がついに判明したという研究です.

働かないアリも集団維持に必要 北大研究者が興味深い研究成果

この研究結果の概要を簡単に書くと,以下のようになります.

働きアリが全員働くと,全ての働きアリが一斉に疲れてしまって,最終的に早くリソースが底をついてしまう.一方,一部の働かないアリがいると,働きアリが疲れた時や,想定外の新しい仕事が現れたときに,その働かないアリが働くことで,リソースを継続することが出来る.

働かないアリは怠けていたのではなく,緊急時に備えて待機していたのです.

私も働きたくない人間として,この精神を見習わなければなりません.そこで,上記の原理を計算機シミュレーションで作ってみます.上記研究でも計算機シミュレーションによって検証が行われたようですが,そのシミュレーションと本記事のシミュレーションとは全く関係ありません.私が雑念として考えたモデルなので,アルゴリズムが正しいかどうかも分かりません.尚,実際の働きアリの原理は上記よりももう少し多層的で,各アリに固有の閾値があり,これによって働き始めるタイミングが決まるようです.が,そういったことを全て実装すると大変なので,話をシンプルにして実装します.

以下のような条件を設定して,時間を進め,アリの集団で何が起こるかを観察します.

今回題材とするのは,上記研究でも取り上げていた,アリの卵掃除です.アリの卵は,非常に汚れに弱く,汚れが蓄積していくと卵自体が死んでしまいます.そこで,働きアリの唾液で卵を嘗め回し,常に卵を清潔に保つというのは,働きアリの重要な仕事のひとつです.

このタスクをアリの集団が行う状況は,以下の点を実装すれば良いでしょう.

①卵には,汚れた卵と汚れていない卵がある.
②アリには働きアリと働かないアリがいる
③卵は時間が経過するほど汚れている時間が蓄積していく
④汚れの蓄積時間がある一定を超えると卵は死んでしまう
⑤汚れの蓄積時間がある一定を超えると他の汚れていない卵も汚してしまう
⑥死んだ卵も汚れが蓄積していく
⑦働きアリは生きている卵のみ掃除する
⑧働きアリの「掃除」は,卵の汚れの蓄積時間を減らす働きをする
⑨働きアリの掃除のスピードはランダムに速かったり遅かったりする
⑩働きアリは掃除すればするほど疲れがたまっていく
⑪疲れきると働きアリは,全く働かなくなり,二度と復活しない(これは示唆に富んだ設定です.)
⑫疲れきった働きアリが出ると,入れ替わりに働かないアリが働き始める

これらを実装します.MATLABで実装すると以下のようになります.構造体やMATLAB特有の手法を使うことでもっとシンプルになる気がしますが,MATLABの構造体の定義が少し面倒なので,あまりそういった手法は使っていません.その代わり,配列の定義以外のところは,他の言語でも楽に移植できるコードになっていると思います.(移植する必要性が全くありませんが)

clear;
close all;
numegg=100;%卵の数
egglife=1;%卵の寿命(汚れが蓄積すると死ぬ)
infecttime=1;%汚れ状態が伝染する時間
numant=100;%アリの数
workant=100;%働きアリ
tired=5;%アリが疲れて働かなくなる時間
egg_islife=ones(numegg,1);%卵が生きているかどうか(1:生 0:死)
egg_isdirty=zeros(numegg,1);%卵が汚れ状態かどうか (1:汚れ状態 0:汚れ状態でない)
egg_isdirty(1:30)=1;%汚れ状態は初期状態では30個
egg_dirtytime=zeros(numegg,1);%卵の汚れの蓄積時間
ant_life=ones(numant,1)*tired;%アリの疲労度(0になると疲れて働かなくなる)
ant_iswork=zeros(numant,1);%アリが働いているか(1:働いている 0:働いていない)
ant_lovework=zeros(numant,1);%働きアリかどうか(1:働きアリ 0:働かないアリ)
for k=1:workant,
    ant_lovework(k)=1;
    ant_iswork(k)=1;
end
delta=0.01;%刻み時間
tmax=4;
len=tmax/delta;
t=zeros(len,1);
answer=zeros(len,1);%汚れている卵の数
deadegg=zeros(len,1);%死んだ卵の数
liveant=zeros(len,1);%疲れていないアリの数(働きアリ・働かないアリ両方含む)
for k=1:len,
    deltat=tmax*delta;
    t(k)=k*delta;
    for n=1:numegg,
        if egg_isdirty(n)==1
            %汚れが蓄積する
            egg_dirtytime(n)=egg_dirtytime(n)+deltat;
            %汚れの蓄積時間が閾値を超えると,汚れていない卵に汚れが伝染する
            if egg_dirtytime(n)>=infecttime
                for m=1:numegg,
                    if egg_isdirty(m)==0
                        egg_isdirty(m)=1;
                        break;
                    end
                end
            end
       %汚れの蓄積時間が閾値を超えると卵は死ぬ
            if egg_dirtytime(n)>=egglife
                egg_islife(n)=0;
            end
        end
    end
    for n=1:numant,
        if ant_iswork(n)==1&&ant_life(n)>0
            ant_life(n)=ant_life(n)-deltat;
            for m=1:numegg,
                if (egg_isdirty(m)==1)&&(egg_islife(m)==1)
           %働きアリが卵を掃除する(掃除するスピードはランダムである)
                    egg_dirtytime(m)=egg_dirtytime(m)-deltat*rand(1,1)*0.1;
                    if egg_dirtytime(m)<=0
                        egg_isdirty(m)=0;
                        egg_dirtytime(m)=0;
                    end
                    break;
                end
            end
        end
    %疲れきった働きアリと入れ替わりに働かないアリが働き始める
        if ant_life(n)<0&&ant_lovework(n)==1
            for m=1:numant,
                if ant_life(m)>=0&&ant_lovework(m)~=1
                    ant_iswork(m)=1;
                end
            end
        end
    end
    for n=1:numegg,
        answer(k)=answer(k)+egg_isdirty(n);
        deadegg(k)=deadegg(k)+(1-egg_islife(n));
    end
    for n=1:numant,
        if ant_life(n)>0
            liveant(k)=liveant(k)+1;
        end
    end
end
hold on;
plot(t,answer);
plot(t,deadegg,'r');
plot(t,liveant,'g');
xlim([0 4]);
 legend('汚れている卵','死んだ卵','疲れていないアリ');

このシミュレーションの結果が以下のようになります.今回は,卵の数100個,そのうち初期状態で汚れている卵を30個,アリ全体を100匹でシミュレーションを行いました.

まず,全員が働きアリの場合.


横軸は時間tです.青が汚れた卵の数.赤が死んだ卵の数,緑がまだ働けるアリの数です.ここで注目したいのは,赤い線が,上限の100に達するタイミング.t=1.6あたりで,全ての卵が死んでしまいました.

次は,働かないアリを20匹にした場合.

卵が全滅するまでの時間がt=3まで延びました.雑なモデルと実装にしてはよくこんなに明白に差が出たもんだと自画自賛したいですね.

いかがでしょうか?この結果を見れば,働かないアリの必要性は議論の余地がないですね.働かないアリはいざというときの最後の砦として,自分の力を温存しているのです.そしてそれは,集団をより長く維持するのに貢献しています.

これは,人間社会でも同じではないでしょうか?今働いている人が疲れきってしまったとき,今働いている人だけでは手に負えない課題が発生した時.そんな時こそ働いていない人の出番です.人類が直面する未曾有の危機に,立ち向かう.そんな人間になりたいものです.

・・・というのは全て嘘です.とにかく働きたくありません.明日も客先の現場で仕事なので朝早く起きなければならず,とても憂鬱です.と書いて気が付きましたが,私がそんなにも仕事をしたくない理由は,朝決まった時間に起きなければならないからかもしれません.

0 件のコメント:

コメントを投稿