支援物資の分配計画をExcelで立案する

#TL;DR
ヒッチコック型輸送問題を現実のケースに当てはめて解いてみた知見共有
# 注意
焦りながら書き殴った文章のため読みにくいです。申し訳ありません。後で清書します。
# まえがき
2022年1月22日、九州地方で最大震度5強の地震が発生しました。

https://www3.nhk.or.jp/news/html/20220122/k10013443911000.html

https://weathernews.jp/s/topics/202201/220108quake/

報道されている限りでは、大きな被害は無さそうです。
しかし2016年の熊本地震で

- 本震だと思われていた揺れが実は前震
- 後から本震が来た

という体験をしている以上、これから被害が増えないとも限りません。

仮に避難所が開設されるレベルの災害になった場合、各地から支援物資が集まることでしょう。ありがたいことです。
支援物資は避難所の周辺に設置された集約拠点に集められ、避難所ごとに小分けして配送されます。
# 問題
すると、経験的に次のような問題が起きます。

- どの集約拠点からどの避難所まで何をどれだけ運べばいいのか誰も分からない
    - 例
        - 小麦アレルギーの人がいる避難所にパンしか届かない
        - 赤ちゃんのいる避難所に離乳食やオムツが届かない

他にも問題は山積みですが、ひとまず本記事では上記の問題を解決することを目指します。

原因をまとめると、

- 集約拠点が避難所の需要を把握できていない
- 避難所が集約拠点の在庫を把握できていない
- どの集約拠点からどの避難所に運ぶかの輸送計画が作られていない

ことにあるでしょうか。
# 単体法を用いた解決
## 概要
問題を「ヒッチコック型輸送問題」という形式に落とし込み、表計算ソフトを使用して解くことで解決します。
ヒッチコック型輸送問題を解く方法としては「単体法」が知られており、Excelのアドイン「ソルバー」を使用することで単体法を使えます。
同じ表計算ソフトでもGoogle Spreadsheetにはソルバーの機能がありません。Google Apps Script等を用いて自力でソルバーを構築することも可能ですが、今回は「災害対策で最も重要なのは初動スピード」という観点のもとでExcelを使用します。

ファイル構成は以下の通りです。

- 需要申請フォーム(避難所が需要情報を登録する)
    - 回答内容が記録されたExcelファイル
- 供給申請フォーム(集約拠点が供給情報を登録する)
    - 回答内容が記録されたExcelファイル
- 計算用のExcelファイル

## 需要と供給の把握
Microsoft Formsを用いてフォームを作成します。
FormsはMicrosoft365に含まれているアプリケーションのひとつで、今回はブラウザ上で操作します。
ブラウザでOne Driveにログインし、Formsを起動させ、新しいフォームを構築します。
### 需要申請フォーム
避難所の担当者が記入するフォームで、何がどれだけ必要なのかという需要情報を登録するためのフォームです。
「需要申請フォーム」と名付けたフォームを作成し、質問を追加します(全て必須回答)。

- 避難所名(選択肢)
    - どの避難所としての情報なのか
    - 例
        - OO学校
        - XX会館
- 分類(選択肢)
    - 何が必要なのか
    - 例
        - 食料
- 詳細(テキスト)
    - 必要な物の詳細
    - 例
        - 小麦アレルギー対応食
- 数量(テキスト※数値限定)
    - どれだけ必要なのか

### 供給申請フォーム
集約拠点の担当者が記入するフォームで、何がどれだけ出せるのかという供給情報を登録するためのフォームです。
「供給申請フォーム」と名付けたフォームを作成し、質問を追加します(全て必須回答)。

- 集約拠点名(選択肢)
    - どの集約拠点としての情報なのか
    - 例
        - OO広場
        - XXセンター
- 分類(選択肢)
    - 何の在庫があるのか
    - 例
        - 食料
- 詳細(テキスト)
    - 在庫の詳細
    - 例
        - 小麦アレルギー対応食
- 数量(テキスト※数値限定)
    - どれだけ必要なのか

### 計算用ファイル
各フォームの回答をExcelファイルとして「回答」タブからダウンロードします。このときフォーム名の後に(1-5)のようなものが付くので、消して「需要申請フォーム.xlsx」にします。
続いて、Excelの機能「クエリ」(使えるのはデスクトップ版のみ)を用いて回答内容ファイルの内容を計算用ファイルに反映させます。
新しく「需要申請フォーム」「供給申請フォーム」タブを作成し、クエリを設定します。
また、既に到着した分・既に発送した分は計算から除外するため、それぞれ右側に「到着済」「発送済」という項目も手動で作り、セルをチェックボックスにします。

例えば供給申請フォームタブは、以下のようになるはずです。

||A|B|C|D|E|F|G|H|I|J|
|---|---|---|---|---|---|---|---|---|---|---|
|1|ID|開始時刻|完了時刻|メール|名前|集約拠点名|分類|詳細|数量|発送済|
|2|1|(月)/(日)/(年) (時):(分):(秒)|(月)/(日)/(年) (時):(分):(秒)|anonymous|ID|〇〇|〇〇|〇〇|〇〇|(チェックボックス)|

「需要申請フォーム」「供給申請フォーム」に続き、種類別の計算シートを作ります。例えば「食料」は、以下の通りに。

||A|B|C|D|E|F|G|H|I|J|
|---|---|---|---|---|---|---|---|---|---|---|
|1|集約拠点|OO広場|XXセンター||||||総コスト|=SUM(J4:J7)
|2|供給上限|(*1)|(*1)|||
|3|供給量|I4+I5|I6+I7|||||輸送単価|輸送量|輸送コスト|
|4|||||OO広場|→|OO学校|0|0|=H4*J4|
|5|需要量|I4+I6|I5+I7||OO広場|→|XX会館|0|0|=H5*J5|
|6|需要下限|(*2)|(*2)||XXセンター|→|OO学校|0|0|=H6*J6|
|7|避難所|OO学校|XX会館||XXセンター|→|XX会館|0|0|=H7*J7|

(*1)には、以下の計算式を入力します。
> =SUMIFS(供給申請フォーム!I:I,供給申請フォーム!F:F,"(1個上にある集約拠点名)",供給申請フォーム!G:G,"食料",供給申請フォーム!J:J,FALSE)

(*2)には、以下の計算式を入力します。
> =SUMIFS(需要申請フォーム!I:I,需要申請フォーム!F:F,"(1個下にある避難所名)",供給申請フォーム!G:G,"食料",需要申請フォーム!J:J,FALSE)

輸送単価には、物資1個を配送するために必要なコストを入力します。距離が長い、道が危険など、運びにくい要素があればコストを高くします。

最後にソルバーを設定します。
J1を最小に、目的変数セルはI4:I7。制約条件は、供給量が供給上限以下、需要量が需要下限以上。エンジンはシンプレックスLPにします。
そして実行すると、どの集約拠点からどの避難所までいくら食料を輸送すればいいのか分かります。

# あとがき
本記事の解決策は、完璧なものではありません。現在、リアルタイムでの計算が可能な形式を研究しています。
また、この解決策により生じた利益および弊害の一切において、筆者は権利と責任を放棄します。本番で使用する際は自己責任でお願いします。