日向坂46の握手会を数理モデルを立てて分析してみた！

<h1>1.はじめに</h1>
COVID-19が猛威を振るう中、予断を許さない状況が続いています。そんな状況下で我々ドルオタにとって最も辛いのは握手会が開催できないことです。収束したら推しに会ってできるだけ長く話したいものです。そこで、数理モデルを立てて握手会を分析することで、握手会でファン一人に対して使える時間を計算してみました。私は日向坂46が好きなので、以下「握手会」は日向坂46の個別握手会を指します。なお、指摘したい点がございましたら、お気軽にコメントまたは<a href = "https://twitter.com/shima_shima_ss">twitter</a>にDMしてください。

<h1>2.握手会モデル</h1>
(結果だけ見たい方へ）
2章と3章は握手会モデルの説明で、4章はソースコードです。結果は5章にまとめてあります。<p>
簡単のため、一人一枚しか握手券を持っていないと考えます。このとき、一人のアイドルに対して、ファンの状態は以下の3パターン考えられます。

$ N_y=$ まだ握手をしておらず、列にも並んでいないファン
$ N_l=$ まだ握手をしていないが、列に並んでいるファン
$ N_f=$ もうアイドルと握手をしたファン

また、以下のように定義することでファンの総数を求めます($N_1$は後に利用します。)

$ N=$ 握手券が売れた枚数(=来るファンの総数の最大値)
$ N_0=$ やむを得ない事情等で来られないファンの人数
$ N_1=$ 開始前に列に並んでいるファンの人数

このとき、任意の時刻において以下の式が成り立ちます。

$$ N_y + N_l + N_f = N - N_0 = (const) $$

握手率$p$と握手時間$T$を定数として導入し、それぞれのファンの状態の時間変化を考えます。

<h2>N_yについて</h2>

握手もしておらず、列にも並んでいないファンの数は減少こそすれ増加はしないと考えられます。
また、その減少スピードは必ずしも一定ではなく、開始直後が最も大きく時間が経つにつれて緩やかになると予想可能です。
従って、握手率$p$を用いて、以下のような時間変化を考えるのが自然でしょう。

$$ \frac{dN_y}{dt} = -pN_y $$

<h2>N_lについて</h2>

列に並んでいないファンの時間変化の分だけ列の人数は増え、その定義から$T$秒に1人列から出て行きます。
従って以下のような式が立式できます。

$$ \frac{dN_l}{dt} = pN_y - \frac{1}{T} $$

<h2>N_fについて</h2>

握手し終わったファンの人数は、握手時間$T$の逆数に比例するので以下の式になります。

$$ \frac{dN_f}{dt} = \frac{1}{T} $$


これらが今回使う握手会のモデルです。

<h1>3.握手会モデルの計算</h1>
握手会が始まる瞬間の初期値は$N_y(0) = (N - N_0 - N_1)$、$N_l(0) = N_1$、$N_f(0) = 0$です。この初期値を利用して2章で出した微分方程式を解くと、以下のような結果が得られます。

$$ N_y(t) = (N-N_0-N_1)e^{-pt}$$
$$ N_l(t) = (N-N_0) - (N-N_0-N_1)e^{-pt} - \frac{t}{T} $$
$$ N_f(t) = \frac{t}{T} $$

日向坂の個別握手会は1部につき90分時間が設けられます。開始60分経つと列に並ぶことが不可能になります(1)。ファンは当然60分までに列に並ぼうとします。ここで$N_y(3600)$の式を$p$について変形すると
$$ p = -\frac{1}{3600}\ln(\frac{N_y(3600)}{N-N_0-N_1}) $$
$N_y$の初期値$(=N-N_0-N_1)$のおおよそ1%ほどが60分以内に列に並べないと仮定すると
$$ p = -\frac{1}{3600}\ln(0.01) = 1.65 \times 10^{-3} $$
以上により$p$を求めることができました。
一方、握手会の主催者側は90分後、つまり5400秒後にちょうど$N_l(5400) = 0$となるよう握手時間を定めるはずです。ここで$N_l(5400) = 0$を$T$について変形すると
$$ T = \frac{5400}{(N-N_0) - (N-N_0-N_1)e^{-5400p}} $$
以上により、握手時間$T$を定める関係式を導くことができました。
<h1>4.ソースコード</h1>

```python:model.py
#個別握手会の簡単なモデル
#一人一枚で重複なし
#　Nはその子の個握が買われた枚数に相当
#　N0は来ない人数に相当
#　N1はt=0でレーンに並んでいた人数に相当

from matplotlib import pyplot
from math import log,e
import numpy as np
def ln(x): return log(x)

N = int(input('N:'))
N0 = int(input('N0:'))
N1 = int(input('N1:'))

tf = 5400 #握手会終了時間
p = ln(0.01)/3600 #握手率
p *= -1
T = tf/((N-N0)-(N-N0-N1)*e**(-tf*p)) #握手時間
t = np.linspace(0,tf,1000000)
print('T is',str(T)) #握手時間Tの出力

y1 = -(N-N0-N1)*(e**(-p*t)) - (t/T) + (N-N0) #N_lのグラフ
y2 = (N-N0-N1)*e**(-p*t) #N_yのグラフ

pyplot.plot(t, y1 ,label="in line")  #描写
pyplot.plot(t,y2,label = "not yet")

pyplot.legend()
pyplot.title('The number of people') #グラフのタイトル

pyplot.xlabel('time(s)') #x軸
pyplot.ylabel('people') #y軸
pyplot.grid(True)

pyplot.show()
```

標準入力により,$N$,$N_0$,$N_1$の値を自由に設定できます。
また、今回は$N_f$はあまり重視しないので$N_y$と$N_l$の2つのみグラフに描写しています。

<h1>5.ファンの状態遷移と握手時間</h1>
握手会モデルと4のソースコードを用いてファンの状態と握手時間を計算します。
実は日向坂の個別握手会は、1部ごとの握手券の枚数がいくらなのかの正確な値は知られていません。しかしファンの間ではおおよそ500枚から600枚であると言われています。そこで今回は$N = 500$,$N=550$,$N=600$の3つの場合を調べます。全ての場合において$N_0 = 20$とし、$N_1 = 0$とします。

<h2>N=500のとき</h2>
![N500N020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475129/6d77eaa8-0ec0-3e5a-a26e-72874e4fe457.png)

$$ T = 11.26$$

<h2>N=550のとき</h2>
![N550N020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475129/1b96f616-30a8-c521-7a9b-d3ea04a92ad6.png)

$$ T = 10.20 $$
<h2>N=600のとき</h2>
![N600N020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475129/c413341c-f377-406a-e1ba-4949fa103db9.png)

$$ T = 9.32 $$

<h1>6.考察</h1>
$N$の値を動かしても、グラフの形に変化はほぼないようです。どのグラフにおいても$t=1400から1600$で$N_l$がピークを迎えていることがわかります。人混みを避けたいのであればピーク終わってから行く方が良いかもしれませんね。

実際の日向坂の個別握手会における握手時間はおおよそ8秒から10秒と言われています。握手以外に入退場する時間もあると考えると、実際に握手に割くことができる時間は理論値よりも短くなるでしょう。簡単なモデルの割には結果が実際の値と近くなったので十分意義のあるモデルだと考えられます。そもそも握手会において大切なのは時間じゃありません。推しへの愛。それだけです。推しへの愛があれば時間なんてどうでもいいのです。高本彩花さん。大好きです。

<h1>7.参考</h1>
<a href="https://fortunemusic.jp/hinatazaka46_201910/">(1)のソース</a>