ChatGPT(GPT-4)と数理最適化に関するヒアリングのロールプレイをしてみた

# はじめに

※私は数理最適化で某社内の課題解決に取り組んでいる者ですが、本稿の内容は私の所属している会社での仕事に関連するものではありません
※ChatGPTに会社の機密情報は尋ねないようにしましょう！

数理最適化ってデータ分析タスクと比べてコモディティ化が進んでいないので、専門家でないとまだまだ大変ですよね？
本稿ではChatGPTを用いて数理最適化プロジェクトのタスクの一部を補助してもらえないか、検討してみました。



## ヒアリングと定式化をChatGPTにお願いする

梅谷先生の著書「しっかり学ぶ数理最適化」では、課題解決の手順を４つのステップに分けています。

1. 現実問題を最適化問題に定式化する
1. アルゴリズムによって求解する
1. 計算結果を分析・検証する
1. 最適化問題とアルゴリズムを再検討する

一般的な実務を考えると、１つ目のステップは以下の3つに分解できると思います。
- 担当者へのヒアリング
- データ収集と事前の分析 
- 定式化

最初のヒアリングで抜け漏れが発生するとのちの手順で手戻りが多く発生します。定式化やアルゴリズムの開発も高度な専門性を要するところですが、ヒアリングも１つの重要なスキルだと思います。

これを誰でも一定の質でできるようになればいいなと思い、ChatGPTに補助してもらえないか試してみました。


# 前提

- 私が依頼者(物流担当者役)をやる
- ChatGPTに数理最適化の専門家役をお願いする
- エンジンにはGPT-4を用いる
- ChatGPTが気を利かせてくれないときは、依頼者側から踏み込む

前提条件の入力
```
あなたは数理最適化によって物流ネットワークを最適化したいエンジニアです。
私は物流担当者です。私にヒアリングして、定式化を行ってください。
```


# 結果

ChatGPT: 
```
物流担当者様、物流ネットワークの最適化を行うために、まずは現状のネットワークに関する情報を収集し、その上で数理最適化の定式化を行います。以下に、ヒアリングで必要な情報をリストアップしました。ご回答いただけると助かります。

1. 企業の物流ネットワークにおける、拠点（工場、倉庫、販売店など）の一覧とそれぞれの位置情報
2. 拠点間の輸送コスト（距離、時間、費用）
3. 各拠点の供給能力（製品の生産量や在庫量、取扱可能な品目数など）
4. 各拠点の需要量（顧客からの注文量、期間、品目など）
5. 各拠点でのリードタイム（製品の生産から出荷までの期間、輸送に要する時間など）
6. 制約条件（輸送手段、容量制約、時間制約、予算制約など）
7. 最適化の目的（輸送コストの削減、リードタイムの短縮、在庫コストの削減、顧客満足度向上など）
上記の情報をもとに、数理最適化の定式化を行い、物流ネットワークの最適化を目指します。よろしくお願いいたします。
```

私の回答:
```
1、3についてはその通りにデータが与えられたとします。
2については、複数の輸送手段があり、それぞれでコストが変わるとします。
4については品目は1種類だけです。拠点ごと、期間ごとの需要量のデータが与えられたとします。
5については2と同様、輸送手段ごとにも変化します。データが得られたとします。
6については、在庫を期間ごとに0以上に維持する必要があります。また、輸送の際には中継拠点を介してお客様に運びます。輸送力、生産力にも上限があります。
7については、輸送コストと生産コストの和を最小化したいです。
```

ChatGPT:

>ご提供いただいた情報をもとに、数理最適化の定式化を行います。ここでは、輸送コストと生産コストの和を最小化する目的で、物流ネットワークの最適化問題を定式化します。
>
>決定変数：
>
>- x_{ijkt}: 時間 t において、拠点 i から拠点 j へ輸送手段 k を用いて輸送する製品の量
>- y_{it}: 時間 t において、拠点 i で生産される製品の量
>- z_{ijt}: 時間 t において、拠点 i で保持される製品の在庫量
>
>目的関数：
>最小化: Σ_t Σ_i Σ_j Σ_k c_{ijk} * x_{ijkt} + Σ_t Σ_i p_i * y_{it}
>ここで、c_{ijk} は拠点 i から拠点 j へ輸送手段 k を用いた際の輸送コスト、p_i は拠点 i での生産コストを表します。
>
>制約条件：
>
>1. 供給拠点の生産量制約: y_{it} <= S_i ∀i, t (S_i は拠点 i の生産能力)
>2. 需要拠点の需要量制約: Σ_j x_{ijkt} = D_{jt} ∀j, t (D_{jt} は拠点 j での時間 t における需要量)
>3. 輸送容量制約: Σ_i x_{ijkt} <= Q_k ∀i, j, k, t (Q_k は輸送手段 k の輸送容量)
>4. 在庫量制約: z_{ijt} >= 0 ∀i, j, t
>5. 在庫更新制約: z_{ijt} = z_{ij(t-1)} + y_{it} - Σ_k x_{ijkt} ∀i, j, t
>6. リードタイム制約: Σ_k x_{ijkt} <= L_{ijk} ∀i, j, k, t (L_{ijk} は拠点 i から拠点 j へ輸送手段 k を用いた際のリードタイム)
>
>以上の定式化を用いて、物流ネットワークの最適化問題を解くことができます。最適化ソルバーを活用して解を求めることができ、その結果をもとに物流ネットワークを改善することができます。


最初の内容としては悪くない気がするが、ちょっと訂正してみる。
```
すみません、実は１回あたりの輸送量が輸送手段ごとに決まっていました。
```

ChatGPT
> 了解しました。輸送手段ごとに決まった輸送量がある場合、以下のように定式化を修正します。
>
>決定変数：
>
>- x_{ijkt}: 時間 t において、拠点 i から拠点 j へ輸送手段 k を用いて輸送する回数
>- y_{it}: 時間 t において、拠点 i で生産される製品の量
>- z_{ijt}: 時間 t において、拠点 i で保持される製品の在庫量
>
>目的関数：
>最小化: Σ_t Σ_i Σ_j Σ_k c_{ijk} * v_k * x_{ijkt} + Σ_t Σ_i p_i * y_{it}
>ここで、c_{ijk} は拠点 i から拠点 j へ輸送手段 k を用いた際の輸送コスト、v_k は輸送手段 k の1回あたりの輸送量、p_i は拠点 i での生産コストを表します。
>
>制約条件：
>
>1. 供給拠点の生産量制約: y_{it} <= S_i ∀i, t (S_i は拠点 i の生産能力)
>2. 需要拠点の需要量制約: Σ_j v_k * x_{ijkt} = D_{jt} ∀j, k, t (D_{jt} は拠点 j での時間 t における需要量)
>3. 輸送容量制約: Σ_i v_k * x_{ijkt} <= Q_k ∀i, j, k, t (Q_k は輸送手段 k の輸送容量)
>4. 在庫量制約: z_{ijt} >= 0 ∀i, j, t
>5. 在庫更新制約: z_{ijt} = z_{ij(t-1)} + y_{it} - Σ_k v_k * x_{ijkt} ∀i, j, t
>6. リードタイム制約: Σ_k v_k * x_{ijkt} <= L_{ijk} ∀i, j, k, t (L_{ijk} は拠点 i から拠点 j へ輸送手段 k を用いた際のリードタイム)
>
>この修正した定式化を用いて、物流ネットワークの最適化問題を解くことができます。最適化ソルバーを活用して解を求めることができ、その>結果をもとに物流ネットワークを改善することができます。

うーん、ちょっと結論が早いなぁ。もっと疑って色々聞いてほしいので、こちらから質問を促す。
```
開発側から何か質問ありますか？まだ何か足りないような気がします...
```

ChatGPT:
※文が途中で途切れたので繋いでいます。

> ご指摘いただきありがとうございます。いくつかの追加情報が必要かもしれません。以下の質問に回答いただけますと幸いです。
>
> 1. 輸送手段ごとの輸送コストの詳細: 輸送手段ごとに固定コストや変動コストがある場合、それらの詳細を教えていただけますか？
> 2. 各拠点の最大在庫量: 各拠点で保管できる最大在庫量がある場合、その制約を追加する必要があります。各拠点の最大在庫量に関する情> 報を提供いただけますか？
> 3. 生産リードタイム: 製品が生産されてから出荷されるまでにかかる時間について、情報があればお知らせください。
> 4. 輸送手段ごとの運用制約: 例えば、輸送手段の最大運用時間や運用可能日数など、輸送手段ごとの制約があればお知らせください。
>
> これらの情報を追加で取り入れることで、定式化をより正確に行い、物流ネットワーク最適化問題の解決に役立てられます。ご協力いただけますと幸いです。


お、結構大事なこと聞いてくれているんじゃないか？4の質問から派生して条件を追加してみる

```
1,2,3についてはそのままデータを提供できます。4について、そういえば上記の定式化では輸送媒体はどのような経路をとりえますか？
例えば１か所の拠点で集荷し、複数のお客様や中間拠点に連続で輸送することもあるのですが、そのような輸送経路を実現できますか？
```

> 1,2,3についてデータを提供いただけるとのこと、ありがとうございます。4に関して、ご説明いただいたような複数のお客様や中間拠点への連続輸送が可能な経路を考慮するため、定式化を以下のように修正します。
>
>決定変数：
>
>- x_{ijkt}: 時間 t において、拠点 i から拠点 j へ輸送手段 k を用いて輸送する回数
>- y_{it}: 時間 t において、拠点 i で生産される製品の量
>- z_{ijt}: 時間 t において、拠点 i で保持される製品の在庫量
>
>目的関数：
>最小化: Σ_t Σ_i Σ_j Σ_k c_{ijk} * v_k * x_{ijkt} + Σ_t Σ_i p_i * y_{it}
>ここで、c_{ijk} は拠点 i から拠点 j へ輸送手段 k を用いた際の輸送コスト、v_k は輸送手段 k の1回あたりの輸送量、p_i は拠点 i での生産コストを表します。
>
>制約条件：
>1. 供給拠点の生産量制約: y_{it} <= S_i ∀i, t (S_i は拠点 i の生産能力)
>2. 需要拠点の需要量制約: Σ_j v_k * x_{ijkt} = D_{jt} ∀j, k, t (D_{jt} は拠点 j での時間 t における需要量)
>3. 輸送容量制約: Σ_i v_k * x_{ijkt} <= Q_k ∀i, j, k, t (Q_k は輸送手段 k の輸送容量)
>4. 在庫量制約: z_{ijt} >= 0 ∀i, j, t
>5. 在庫更新制約: z_{ijt} = z_{ij(t-1)} + y_{it} - Σ_k v_k * x_{ijkt} ∀i, j, t
>6. リードタイム制約: Σ_k v_k * x_{ijkt} <= L_{ijk} ∀i, j, k, t (L_{ijk} は拠点 i から拠点 j へ輸送手段 k を用いた際のリードタイム)
>7. 最大在庫量制約: z_{ijt} <= M_i ∀i, j, t (M_i は拠点 i の最大在庫量)
>
>追加の制約条件：
>8. 流量保存制約: Σ_k (v_k * x_{ijkt} - v_k * x_{jikt}) = 0 ∀i, j, t (拠点 i での製品の流入量と流出量が等しい)
>9. 中継拠点制約: Σ_k x_{ijkt} <= M_i ∀i, j, k, t (M_i は拠点 i の最大輸送回数)
>
>この修正された定式化を用いて、物流ネットワークの最適化問題を解くことができます

定数の文字(M_i)が被ってますが、面倒なので指摘しません。
時間tをどう決めるかがまだ決まっていないので、確認してみます。

```
ありがとうございます。データを用意したいのですが、データの期間についてはどのくらいの範囲と粒度が望ましいでしょうか？
```

ChatGPT
> データの期間と粒度に関しては、解析の目的や制約、利用可能なデータに応じて変わります。以下に、期間と粒度を決定する際の一般的な指針を示します。
>
>解析の目的: あなたが解決したい問題や最適化の目的によって、データの期間と粒度が変わります。短期的な最適化を目指す場合は、数週間から数ヶ月のデータを用いることが適切です。長期的な最適化や戦略的な意思決定を目指す場合は、数年分のデータを用いることが適切です。
>
>制約と変動要素: 輸送手段の利用可能性や生産能力、需要量などの変動要素が日単位、週単位、月単位などで大きく変わる場合は、それに応じた粒度でデータを用意することが望ましいです。
>
>利用可能なデータ: 解析に使用するデータの粒度は、利用可能なデータの範囲と精度にも依存します。例えば、日単位のデータが利用可能であれば、より詳細な最適化が可能になりますが、週単位や月単位のデータしか利用できない場合は、それに合わせた解析を行う必要があります。
>
>これらの要素を考慮し、目的に適した期間と粒度を選択してデータを用意してください。ただし、粒度が細かすぎると計算時間が増え、最適化問題の解決が難しくなることがありますので、適切なバランスを見つけることが重要です。

模範解答！

```
どのくらいの粒度なら解けるのかちょっと私にはわからないので、とりあえず１日ごとのデータを１年分でもよろしいでしょうか？
```

> 1日ごとのデータを1年分用意することは、計算上問題ありません。ただし、粒度が細かいデータを用いる場合、計算時間が増加し、最適化問題の解決が難しくなることがあります。また、データの粒度が高いほど、モデルのパラメータ数が増えるため、計算リソースが十分にあることを確認してください。
>
>1日ごとのデータを1年分用意する場合、365日分のデータが必要となります。最適化問題が大規模になることを考慮し、効率的な最適化アルゴリズムやソルバーを使用することが重要です。また、計算時間が非常に長くなる場合は、より粗い粒度のデータ（例えば、週単位や月単位）を検討するか、最適化問題の簡略化を検討することが望ましいです。
>
>最初に1日ごとのデータで1年分を試して、計算時間や解の品質を確認してください。その結果に基づいて、必要に応じてデータの粒度を調整することができます。

だいたい雰囲気をつかめたのでここで打ち切った。

# 結論

- 初回ヒアリングと定式化を完全にお任せするのはまだ難しいかも
    - 一度聞いた内容だけで結論を出そうとしてしまう
    - 一度に大量の質問を投げてくるので回答側は論点を絞りにくい
    - 実務はもっと複雑なので、問題の範囲をうまく限定したり、制約条件を妥協するなどの判断をしなければならない。
- Copilotとしてはそこそこ使えそう
    - 質問を促せば、ありがちな制約を想定して質問してくれる
- 未検証
    - 定式化の正確さ(追記予定)
    - スケジューリングなど、もっと複雑な課題だとどうなるか？
    - もっとヒアリングのやり方を事前に教えておくことで、もっとスムーズな質疑になるかも？
    - pulpやpython-mipなどでモデルを作るコードも生成できそう

# おわりに

大規模言語モデルによって、数理最適化も実務者レベルの仕事のやり方は変わってくるのではないかと思っています。

これから何が起こるのか、楽しみですね。