PC-9821専用・感染シミュレーション
まりも(DOSsoft)
2020年5月5日 作成
2020年、新型コロナウィルスが蔓延し、"StayHome" が叫ばれている中で、なにか作ってみようというのがきっかけです。感染の拡がりという現象を「なんとなくでもいいから数量的に理解できそうな」プログラムを作ってみようと考えました。
感染者の増減に関する数理モデルは既にいろいろあります。その基本的な考え方は、
コンピュータ上では、人と見なすことができる点を一定の空間内で動かすことで、上記を満たす数理モデルと同様のことをシミュレートできます。数学モデルと大きく異なるのは、人と人との接触確率を一つのパラメータ値として与えることがができない点です。それは局所的な分布状況によって変わり、具体的な値がよくわかりません。
ちなみにこのプログラムは、そもそも2020年4月1日のエイプリルフールに向けて作ったものです。しかしまったくのフェイクというわけでもありません。あえてMS-DOS上の、しかもPC-9821のグラフィクスのみで動作するプログラムとしています。これはたまたまPC-9821の256色グラフィクスの使用法を調べていたからでした。
PC-9821グラフィック画面(640×480,256色)が使用できる機種に限ります。相当なCPUパワーを要求するので、K6-III+ 533MHz、Pentium-II,III 500MHz以上くらいは必要だとお考え下さい。DOSの空きメモリが400KB程度は必要です。そして「30行計画」や「automate」などのテキスト30行ツールを先に実行しておくことを強く推奨します。そうすれば計算ステータスが最下行に表示され、グラフィック画面と被らなくなります。
なおCPUパワーが不足する機種でも、後で述べる"人口"を小さな値にすれば、さほど遅さのストレスはなく実行できると思います。
初期値としてデフォルトで人口2000人、計算エリアとして横160,縦160の範囲を与えてあります。その中にランダムに選んだ3人を感染者とし、残りの人は非感染で免疫のない人として開始します。一様(に近い)乱数を発生させて、人を東西南北(画面の上下左右)に動かします。
計算エリア上のある場所に感染者がいた場合、そこを通りかかった未感染者は、新たに感染者となります。ただし感染者は時間がたつと免疫ができ、他者に感染させなくなります(このプログラムでは均一に21日相当としている)。これをひたすら繰り返します。
いわゆるランダムウォークです。今いる場所から人はランダムな方向に向かうというものです。どちらかというとエサを見つけていないときの蟻の歩き方に近く、あまり現実的に見えませんが、ご近所内の買い物行動はこれに近いかもしれません。
決まったパターンの行動で生活する人が多いということを根拠として、予め一定の方向に動き続けるという運動をします。ただしその方向はランダムに割り振ります。行動域の外周にぶつかると反射するようにしています。行き帰りの往復と考えればよいですが、端から端までトリップを続けるというのは、やや現実的でない点でしょう。
現実的にはタイプ1と2の間くらいで人の行動が起こっていると考えられます。近所の買い物だけの人、小中学校に徒歩通学だけの人、長距離通勤の人、もっと長距離に旅行する人などがいて、域内だけでなく地方を跨いだ感染が起こっています。
あくまでコンピュータ内での事象ですから、時間スケールは相対的なものです。日数が表示はされますが、現実感のある値に適当に調整しているだけです。感染者が回復して他人に感染させなくなるまでの日数は21日固定値としてありますが、これも実際にはばらつきが大きいとされています。
まず人口の入力が求められますので、2000 前後の値で指定してください。 500〜5000の範囲以外は受け付けないようになっています。
人口を小さい値にすると人との接触確率が下がり、コンピュータ時間としては遅く進みます。物理時間的には処理が速く終わるので、速く感染が進んだようにみえますが、そうではありません。やってみるとわかりますが500人では人口密度が小さすぎて感染が拡がりません。
いっぽう大きい値にすると人口密度増大により接触確率が上がり、コンピュータ時間的に速く推移しますが、そもそもの処理が人口の二乗に比例する悪いアルゴリズム(*)のため、人口を多くしすぎると結果を得るのが困難なくらいに時間がかかります。
(*) そのぶん空間の占有状態を記憶する配列を使わないのでメモリ使用量が小さい
次に、
「行動制限をしない人の割合を、何人に1人かの数値(1は全員)で指定して下さい」
と尋ねられます。この値は大きくするほど行動してしまう人の割合は減ります。よく「8割の行動減を」と言われますが、その状態にするには5を与えます。1/5が行動し、4/5(8割)が行動自制する状態です。1を与えると1/1ということで、全員が行動してしまう最悪のパターンとなります。実際やってみますと、8割抑制(5指定)と7割5分抑制(4指定)では、最大感染者数がずいぶん異なることがわかります。
さらに、
「感染後に行動制限せず野放しにする:0 , 行動を制限する:1 どちらか選択」
という問いが出ます。感染者の行動を止める(隔離に近い)のが1です。感染者の行動を止めるだけで、そこに未感染者が通りかかると感染が発生してしまいますが、これは医療機関や家庭での経過観察で一定の感染が避けられないことと等価とみなしてもよいでしょう。
いっぽう感染者であろうが自由行動にさせてしまうのが0です。社会的にはいまのところ1に近い措置が取られてはいると思いますが、初期には野良感染者が拡散させたことは間違いないです。そのため初期値の感染者3人のみは行動制限がかからないようにしています。後述のキー操作をするとそれは変更されます。
最後に、
「感染発生時にクリック音を鳴らさない:0 , 鳴らす:1 どちらか選択」
という問いが出ます。1にすると、感染が発生した瞬間にはクリック音が鳴ります。
うるさいと思う方は予めスピーカボリウムを下げるか、0で答えておいてください。
256色モードが使用できる機種では画面がクリアされ、実行が開始されます、 画面上のドットは人を表しますが、以下のように属性が色で示されます。
なお画面表示は計算エリアの2倍としてあり、人は横2ドット縦1ドットの塊で表しています。縦も2ドットとしなかったのは、表示の高速化のためと、次で述べる感染者数グラフと重なった場合でも半透過で判読できるようにするためです。
画面下のほうの赤または黄色のグラフは、時間とともに変わるそのときの感染者数です。設定されている治癒時間(21日程度)を超えると緑色に変化します。時間が進んで右端まで行くと、グラフは左端にラップアラウンドします(1ドット下にもシフト)。「行動の制限」がかかっている時はグラフの下限が赤線となり、5以上に制限されているときはそれが太線になります。
スケールが予測できないので画面からはみ出たり、人の行動ドットのエリアに食い込んだりしますが、ご勘弁下さい。かっこいいスケーラブルなグラフにはなかなかできません。
行動の制限
制限厳
↑
隔離←■→解除
↓
制限緩
・ ↑を押すと、行動制限(StayHome)している割合が高くなります。1/整数値です。
・ ↓を押すと、行動制限している割合が低下し、1では全員動きます。
(ただし既に感染している者の行動については次の隔離設定が優先されます)
・ ←キーを押すと「感染者」の動きを止めます。隔離することに相当します。
・ →キーを押すとその隔離を解除、つまり自由に動けるようにします。
(ただし解除状態での感染者の行動については上の行動制限率が優先されます)
その他のキー操作としては以下のものがあります。
・ 実行中にESCを押すと強制中断します(人口が多いと操作遅延が起こります)。
・ INSキーを押すと人口が初期値の2%ぶん増えます。32000程度まで可能。
・ DELキーを押すと人口が初期値の2%ぶん減ります。ゼロにはできません。
・ テンキーの「/」を押すと計算領域が縦横20ドット減ります。ゼロにはできません。
・ テンキーの「*」を押すと計算領域が縦横20ドット拡大されます。安全な最大値は不明。
計算領域を急に変えると人(点)の分布がおかしくなるので、そのときは次の操作をおこなって下さい。
・ Rキーを押すとランダムに人を再配置します。
・ HOMECLRキーを押すとグラフィック画面をいったん全消去します。
(一度消去すると初期の枠は表示されません)
これらのほか、現実の感染症ではありえないイベントを起こす、謎のコマンドキーが2つありますが、現実を理解する上で意味はないので明記しません。
放っておくと、感染者数が1人まで減った時点で終わりとなり、続けることはできません。現実との対比では、ウィルスを封じ込めたことに相当します。
終了すると「経済的損失」という指標が表示されます。ここで経済的損失とは、(行動制限値−1)×時間 に比例する値としています。したがって1のままのときは損失は発生しません(感染者自身の経済損失のようなものは考えない)。行動制限(休業)による社会全体としての損失のようなものです。
この値が現実の何に対応するかはわかりません。あくまでもこのプログラムにおいて比較可能な架空の指標です。終了までの期間に行動制限の割合を変化させて、瞬間の感染者数が一定値を超えず、かつ行動制限の値を低く保つ期間も長くするということを両立し、なるべく低い値にするのがよいことは言うまでもありません。現実の政策もそれが求められているかと思います。
まず作者は感染症医学の専門家でもなく数理モデルの専門家でもないので、感染モデルがこのようなアルゴリズムで妥当かどうかはわかっていません。とはいっても、感染者との衝突により感染するというのは、2m程度内の飛沫感染や接触感染という意味では妥当でしょう。おそらく点の運動と現実社会における人の行動との対比が、最大に議論の余地があるところです。なお点は大きさをもたないと考えるので、当たり判定のような無駄な重い処理は取り入れていません。
プログラミングの専門家でもないので、モデルとして意図するとおりにコーディングが正しく行われているのかは確実ではありません。(それを検証できるようにソースは公開予定)
各パラメータはあくまでも架空のものです。実際とは異なりますし、きちんとした数量で今後の新型コロナ感染を予測するものでもありません。
とはいえ数学モデルとは違う発見もあります。最も単純なバージョンの数学モデルでは最終的に全員が感染して免疫獲得するのですが、ランダムな行動を間に入れると、意外なことに感染が全員には進まないことがわかります。免疫獲得者と未感染者とが住み分けた状態になり(とくにタイプ1では未感染者が多く残る)、感染者数が最終的にゼロになる点に落ち着きます。またタイプ1のランダムウォークモデルでは、初期の指数的感染爆発があまり顕著ではありません。タイプ2だと数学モデルに似た初期の指数爆発がみられます。
もっとも怪しいのは乱数で、MS-Cのライブラリ関数にある rand()関数の周期が、どうも非常に短いらしく、計算領域を大きめにすると、再現性のあるパターンが見えてきてしまいます。とくに乱数発生がその都度となるタイプ1で 顕著です。本格的シミュレーションにはライブラリ関数の乱数が使い物にならないことは間違いありませんが、許容していただければと思います。
終了したときにテキスト行数モードがおかしくなっていることがあります。そのときは[CTRL]+[F・6]のキーを二度叩いてください。そうしておかないと、STOPキーを押したときにテキスト画面が崩れることがあります。テキスト30行ツールを前もって実行していないときに起こり得ます。終了時にグラフィック画面が9821画面となっていて9801画面のソフトが使えなくなることがあります。そのような状態になり画面を消去したい場合は、付属の GCLS256.EXE を使用してください。
計算領域を拡大すると320以上(画面640ドット)で全画面をはみ出ますが、9821グラフィクスでは正しく描画できないだけで、とくにエラーとはならないようです。計算自体は正しく実行されます。しかしVRAMの大きさを超えるほどにするとシステムの動作に何らかの悪影響を及ぼし、システムがクラッシュする可能性はあります。
このプログラムは、2020年に世界中で蔓延している新コロナウィルス感染症のおおまかな数量的性質を体感したり、そこからどうすればいいかを考えることを目的として作ったものです。
まったくのフェイクでもありませんが、きちんとした現実予測でもありません。過度に信じておかしな行動を取らないようにしてください。そうした行動に対し、作者は一切の責任は負いません。
このプログラムの結果の当否に関わらず、人との接触を可能な限り減らすことが、感染のピークを抑えるということは変わりませんので、それに努めて頂きたいものです。