もずくのブログ

読書とゲームと所感

建設を民需工場から軍需工場に切り替える最適なタイミングを微分方程式で導く[hoi4]

軍需工場の数を設定する日時までに最大化する方法を探ります。ちょっと長いので結果だけ知りたい方は目次から飛ばしてください。

はじめに

hoi4における建造速度は民需工場の数に比例すると考えることができる。それでは民需工場を立て続けた場合、その総数は経過時間に対して指数関数的に上昇するはずだ。
この前提に基づけば上昇度の傾きが十分である限り、はじめに民需工場を一定数たてた後、軍需工場などを建てることがもっとも効率が良くなると考えられる。
そこで軍需工場の総数を指定する日時までに最大化する関数を導いてみよう。もちろん軍需工場以外にも応用できる。

数理モデル

前提

軍需工場の総数を指定する日時bまでに最大化する関数を導く。関数の解として、民需工場の建造から軍需工場の建造に切り替える日時aを得る。以下、民需工場、軍需工場それぞれの個数をy,x、開始直後の日付を0とおき経過日数をt消費財の割合を\gammaとおくこととする。条件として開始直後に建設スロットに民需工場のキューを入れるものとし、建設スロットは常に埋められているものと考える。消費財についても考慮する。貿易による民需工場の増減は流動が激しいので無視する(初期条件として設定することはできる)。
なお解析的に導く都合上、若干関数を簡易化しているが実際は段のついた指数関数(イメージ)となるはず(建造途中の工場は出力に寄与しないから)。しかしこの方法でもそのことを考慮に入れた上で参考にするには十分な精度が出ます。(数学的証明は割愛❤)。

STEP1. 経過日数に対し民需工場数を与える関数の導出

wikiから建築速度に関する関係式を調べ、消費財として建設に使用されない工場分を加味した関数を立てる。

\begin{align}
\displaystyle f(y)=\frac{5(y-\gamma(x_0+y))(1 + \frac{bonus}{100})(1 + \frac{InfraBonus}{100})}{Construction Cost}
\end{align}

なお関数f(y)は一次関数で現在の民需工場数から工場数の上昇度への写像である。
前提より、経過日数tに対し総工場数を与える関数N(t)は関数f(y)に比例するから

\displaystyle \frac{dN(t)}{dt} = f(y)

両辺を dt積分

\displaystyle \int \frac{dN(t)}{dt}dt = \int f(y)dt

この微分方程式を解き

\displaystyle N(t)= \frac{C\exp(\frac{5(1+\frac{bonus}{100})(1+\frac{InfraBonus}{100})(1-\gamma)}{ConstructionCost}t)+\gamma x_0}{1-\gamma} ※ Cは積分定数

一般解N(t)を得る。ここで積分定数Cは初期条件を示す。Cについて解くと

\displaystyle C = y(1-\gamma)-\gamma x_0

試しに初期条件として民需工場が15、軍需工場が8建っているものとし、\gamma(消費財として使用される民需工場の総工場数に対する比率)を10%、建造するスロットのインフラレベルを8レベル、民需工場の建設速度ボーナスを10%とした場合を考えよう。
計算により
C = 12.7
条件とCをN(t)に代入することで特殊解が得られる。
特殊解をプロットすると

f:id:mozuku27:20190317141748p:plain
微分方程式を解いて得られる特殊解のグラフ 横軸は経過日数、縦軸は民需工場数を示す

これマジ?伸びが悪すぎるだろ。。。 概形を見る限り正しい

STEP2. 経過日数に対し軍需工場の総数を与える関数の導出

次に区間a,bを与えるとその間に建造される軍需工場数を返す関数M(t)を求めよう。民需工場数に比例し、かつ工場の増加に伴い消費財として使用される民需工場数が増加することを考慮すると以下の方程式が導かれる。

\displaystyle \frac{dM(t)}{dt} = \frac{5(y_a-\gamma(x+y_a))(1+\frac{bonus}{100})(1+\frac{Infra}{100})}{7200}

前節と同じように両辺を積分しこの微分方程式を解く。(変数分離系)
一般解は

\displaystyle M(t) =  -\frac{C\exp(-\frac{5\gamma(1+\frac{bonus}{100})(1+\frac{Infra}{100})}{7200}t)}{\gamma}+\frac{y_a}{\gamma}-y_a ※ Cは積分定数

Cについて解くと

\displaystyle C = y_a - \gamma(x + y_a)

試しに初期条件としてy_a=30x=8を与えた場合のグラフの概形を確認しよう。
計算により
C = 26.2
条件とCをM(t)に代入し特殊解を得る。
これをプロットすると

f:id:mozuku27:20190317190716p:plain
微妙な凹関数。消費財工場の計算式に照らし合わせると妥当と思われる。

徐々に単位時間毎の建設数が減っていることが確認できる。

求めた関数を合体

前節1,2で求めた関数y = N(t),x = M(t)を利用する。G(t,b) = M(N(t),b-t)の曲線が最大値を取るときのtの値が建設を切り替えるべきタイミングaである。

検証

例として開始時点からちょうど7年後(2555日後)にもっとも軍需工場が多くなるような建設切り替えのタイミングaを求める。
初期条件として、民需工場が25、軍需工場が19建っているものとし、\gamma(消費財として使用される民需工場の総工場数に対する比率)を30%、建造するスロットのインフラレベルを7レベル、民需工場の建設速度ボーナスを10%とした場合を設定する。 関数G(t,b)に代入しこれをプロットした。

f:id:mozuku27:20190317211348p:plain
最大値をとる点がもっとも効率の良い切り替えのタイミング

グラフからわかるようにゲーム開始から約1300日後(3.56年程度)に建設を民需工場から軍需工場に切り替えることで7年後に最大の数の軍需工場を得られることがわかる。

別のケースを考えてみる。初期条件は先程と同様のまま、3年後に最大の軍需工場を得る計算ではどうか。
f:id:mozuku27:20190317212022p:plain
3年後に最大の軍需工場を得るには...

グラフからわかるようにこのケースでは、ゲーム開始直後から軍需工場を建設したほうが良い。
期限日時と経過時間、軍需工場の総数の相関は次の3次元グラフで表される。
f:id:mozuku27:20190320103920p:plain
期限日時、経過時間、軍需工場をそれぞれ軸に割り当てた際の3Dプロット

なお、gamma(消費財比率)が10%である場合は次のようになる。
f:id:mozuku27:20190320104330p:plain
gammaを10%に設定した場合のプロット。消費財の比率はかなり結果に影響を与えることが伺える。

まとめ

結論

一般にすべての国において、民需工場を先に建て、後から軍需工場を建てることは、開始から4年以内に戦争を開始する通常のゲームプレイでは長期的な視点からみると意味をなさないことが言える。

感想

チカレタ...。そのうち研究などにより変化するバフを含めた計算ができるプログラム作ります。だが今日じゃない。