mit einem Klick
opt-improve
ボトルネックに合わせた改善策を設計・実行・検証する
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Menü
ボトルネックに合わせた改善策を設計・実行・検証する
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Basierend auf der SOC-Berufsklassifikation
受け取ったデータから最適化問題の構造を把握し、仮説を立てる。最も重要なスキル。
実行可能性(feasibility)を確認する。問題の複雑度に応じて一発解きor段階的解法を選ぶ
最適化モデルの運用設計。自動化・監視・フォールバックを定義する
最適化結果を非技術者にも伝わる改善提案書にまとめる
追加データの依頼書を生成する。何がなぜ必要かを非技術者向けに説明
| name | opt-improve |
| description | ボトルネックに合わせた改善策を設計・実行・検証する |
| user_invocable | true |
/opt-improve [data_path] で実行。
ベースラインのエラー分析結果に基づき、改善策を設計して検証する。
run_in_background=true で同時投入。Before/After 表を一気に作る(探索の局所最適化を避ける)subagent_type=Plan で骨格設計してから実装詳細は reference/opus47_collaboration.md。
改善には3つのレイヤーがある。上のレイヤーほど効果が大きい。 下のレイヤーで頭打ちになったとき、同じレイヤーで粘るのではなく、一つ上に戻れ。
レイヤー1: 問題を変える(解の空間そのものを広げる/変える)
├── 暗黙の前提を疑う(「これは本当に動かせないのか?」)
├── 入力データの使い方を変える(同じデータから別の解釈を引き出す)
└── 運用ルールの変更を提案する(制約を緩和ではなく、現実を変える)
レイヤー2: モデルを変える(同じ問題を別の定式化で解く)
├── 制約のハード/ソフトの切り分けを見直す
├── 変数の粒度を変える(1人単位→チーム単位、1日単位→時間帯単位)
└── 分解の軸を変える(時間/空間/段階)
レイヤー3: パラメータを変える(同じモデルの中で調整する)
├── 目的関数の重みチューニング
├── ソルバーのパラメータ調整
└── ヒューリスティクスの設計改善
レイヤー1の思考法:
「ソルバーが OPTIMAL を返してこれが精一杯」は「このモデルの中での最適」でしかない。 ソルバーの外側に目を向けるために、以下を自問する:
Q1. 「固定」として扱っているものの中に、実は動かせるものはないか?
- リソースの割当状態(既にアサイン済みだが、入れ替えてよいかもしれない)
- リソースの利用可否(使えないとされているが、条件次第で使えるかもしれない)
- 需要の形(分割・統合・延期・委譲ができるかもしれない)
Q2. 制約として扱っているものの中に、実はコストで扱えるものはないか?
- 「できない」のか「やりたくない」のか
- 「不可能」なのか「高くつく」のか
Q3. モデルに含めていない資源や選択肢はないか?
- 使っていないがアクセス可能なリソース
- 現在の計画期間の外にあるが、前倒し/後ろ倒しで使える時間
- 問題のスコープ外だが、協力を依頼できる主体
判定フロー:
改善の余地があるか?
│
├── 解の品質が悪い → レイヤー3(パラメータ調整)から試す
│ └── 頭打ち → レイヤー2へ
│
├── 割当件数/カバレッジが頭打ち → まずレイヤー1を疑う
│ 「容量が足りない」「リソースがない」は結論ではなく出発点。
│ 容量を増やす打ち手、リソースを捻出する方法を3つ以上列挙してから
│ 「本当に不可能」と判断する。
│
└── 制約違反が解消しない → レイヤー2で定式化を見直す
└── それでも無理 → レイヤー1で制約の前提を疑う
レイヤー1の改善は、レイヤー3の10倍以上効くことがある。 目的関数の重みを延々チューニングする前に、5分で「問題の外側」を見渡せ。
エラー類型A: 特定の制約に違反が集中
まず違反の中身を深く分析する。「何が違反しているか」だけでなく「なぜ違反するか」を掘る。 分割の観点は最初から決め打ちできない。実験と分析を繰り返して見つけるもの。
分析の手順:
1. 違反の内訳を集計する
「31件の違反が全てHC6」→ HC6に集中
2. 「なぜその制約が破れるか」を調べる
「AM便の荷物がPMまで車内に滞留して2時間を超える」
→ 原因: AM便とPM便の混載
3. 原因から分割の観点が見える
「AMとPMを分ければ混載がなくなる」
→ 時間で分割すればよいとわかる
4. 試す → 結果を確認 → 効果があれば採用
AM/PM分割 → 違反31件→0件 → 採用
※ 最初から「時間で分割」が正解だとは限らない
※ 空間で分割、段階で分割も候補として試す
※ 間違った分割は逆効果になる(下記参照)
分割の候補と選び方:
○ 時間で分割(時間制約がきつい場合)
→ 違反の原因が「異なる時間帯の混在」なら有効
○ 空間で分割(地理的制約がきつい場合)
→ 違反の原因が「遠い場所の組合せ」なら有効
○ 段階で分割(複数の決定が絡んでいる場合)
→ まず大きな決定(割当)→ 次に小さな決定(順序)
× 分割してはいけない方向もある
→ 「いつ」と「何を」を分離 → スキル制約を破壊して69違反の大失敗例あり
判断基準: 「違反の原因を解消する方向で分割する」
対策2: ボトルネック制約に特化したムーブを設計する
例: 訓練ペアリングが壁 → 熟練者を先に配置する構築法
例: 時間枠制約が壁 → 時間帯ごとに分離してルート構築
エラー類型B: 何をやっても解けない(feasibility未達)
→ 手法の構造的限界を疑う
判定基準: ソルバーで解けるか?
├── ソルバーで解ける → 貪欲法/ヒューリスティクスの限界
│ → ソルバーを使うか、グローバル推論を持つ手法に切替え
│
└── ソルバーでも解けない → 問題そのものが不可能かもしれない
→ 思考回路⑦(不可能性の証明)へ
feasible達成に必要な条件(実験で確認済み):
○ ソルバー(CP-SAT, OR-Tools)→ 制約伝播+バックトラッキング
○ SWO + IFS → 反復フィードバック+バックトラック(ソルバー不要)
○ SWO + Ejection Chain → 反復フィードバック+連鎖交換(ソルバー不要)
× 単純な貪欲法 → 900回試して0回feasible(地平線効果)
× SA/GA単体 → 局所探索だけでは制約の相互作用を解消できない
× FunSearch/EoH → スコアは上がるがfeasibilityには不向き
「ソルバーなしで解きたい」場合:
SWO(問題箇所の反復修正)+ IFS(バックトラック)の組合せが有効。
ドメイン知識を組み込むとさらに効果的。
(例: 訓練ペアリング制約 → 熟練者を先に配置するルール)
エラー類型C: 解けるがスコアが低い
→ 目的関数と評価関数のズレを疑う
1. 評価関数のコードを精読
2. ソルバーの目的関数と評価関数の差分を特定
3. 目的関数を評価関数に精密一致させる
→ これだけで+15-27%改善した実績あり
エラー類型D: 解けるが一部が極端に悪い
→ 悪い部分を特定して局所的に再最適化
1. 解の品質分布を可視化(ルートごと/日ごと/人ごと)
2. 最悪の部分を特定
3. その部分だけ固定解除して再最適化
- 改善策をコードに落とす
- ベースラインと同じ評価器で測定
- Before/After比較テーブルを生成
ソルバーで解けてfeasibleだが、もっとスコアを上げたい場合に使う。
Step 1: 目的関数の精密一致(最優先、これだけで+15-27%)
評価関数のコードを精読 → ソルバーの目的関数との差分を特定
→ 目的関数を評価関数と完全に一致させる
→ これだけで大幅改善する。他の手法より先にやること。
Step 2: LLMにカスタムヒューリスティクスを進化させる
ソルバーの解をベースに、LLMがスコア関数やムーブを自動設計する。
RoCo方式: 4つの役割(探索者/改良者/批評者/統合者)で協調設計
→ 多様なアイデアが出やすい
EoH方式: 複数の戦略を同時に進化させ、最良を選択
→ 「どの順序で埋めるか」等の戦略レベルの改善に有効
ReEvo方式: 実行→失敗分析→改善を3ラウンド繰り返す
→ 「なぜダメだったか」の反省が的確な改善を生む
FunSearch方式: スコア関数の集団を生成→評価→選択→進化
→ スコア関数の微調整に向いている
使い分け:
├── スコア関数を改善したい → FunSearch / RoCo
├── 割当の戦略そのものを変えたい → EoH
└── 何が悪いか分析してから直したい → ReEvo
注意:
- ソフト制約のスコア改善には強い
- Hard制約のfeasibility達成には不向き(ソルバーを使うべき)
- 最も効果的な使い方: ソルバーの解をベースにLLMが微調整
ソフト制約の重み配分を変えた複数のバリエーションを生成し、数値スコアで比較する。 顧客に「どの方針で行くか」を選んでもらうための材料。
手順:
1. ソフト制約ごとに「重視するバリエーション」を作る
例: A=バランス型、B=公平性重視、C=夜勤制限重視、D=最低時間確保重視
2. 各バリエーションを同じソルバーで解く(HC は共通、SC の重みだけ変える)
3. 全ソフト制約を 0-100 のスコアで評価する
- 100 = 完全遵守
- スコアの計算方法は問題に応じて定義(遵守率、標準偏差ベース等)
4. 比較テーブルを出力する
| バリエーション | 充足率 | 公平性 | 夜勤制限 | 最低時間 | 総合 |
|--------------|--------|--------|---------|---------|------|
| A バランス型 | 95.8 | 69.6 | 100.0 | 100.0 | 92.7 |
| B 公平性重視 | 95.8 | 82.1 | 80.0 | 90.0 | 89.3 |
| C 夜勤制限重視 | 95.8 | 55.0 | 100.0 | 100.0 | 90.1 |
5. トレードオフを説明する
「公平性を上げると夜勤制限が犠牲になる」等
注意:
- 問題が小さい/制約がきつい場合、全バリエーションが同じ解になることがある
→ これ自体が発見:「トレードオフの余地がないほど余裕がない」
- バリエーションは 3-5 個が適切。多すぎると選べない
- 総合スコアの重みは顧客と合意して決める
出力ファイル: scripts/variants.py + results/variant_results.json
改善策を試した結果:
├── 解けた → /opt-report で報告書作成
├── 改善したがまだ不十分 → もう1周回す
└── 行き詰まった → 追加データが必要
│
何が足りないか:
├── 制約の詳細(「本当にこの制約は必須?緩和可能?」)
├── 実績データ(「実際にどれくらい時間かかってる?」)
├── 優先度(「どの指標が一番大事?」)
└── ドメイン知識(「現場の人はどうやってる?」)
→ 追加依頼の文面を生成
改善の過程で制約や仮定に変更があった場合、必ずバージョンフォルダ内の spec.md を更新すること。
spec.md を更新したら、必ずこのチェックを実行すること。 仕様変更がコードに反映されていないと、結果が仕様と矛盾する。
ソルバーの FEASIBLE フラグを信じてはいけない。
ソフト化した制約(penalty 化や 5→4 緩和など)を入れると、ソルバーは「緩和後のモデルで解を見つけた」を FEASIBLE と報告するが、元の spec.md の HC を満たしているとは限らない。
必ず以下の独立検証器を実装すること:
def verify_hard_constraints(solver, vars_d, data):
"""Re-check HC1..HCN independently from the raw assignment.
Does NOT rely on the model's internal satisfiability.
Reads solver.Value(x[...]) and checks each HC from scratch.
"""
violations = {f"HC{i}": [] for i in range(1, N+1)}
# ... HC1: demand met? HC2: max hours? ... HCn: pair constraints?
return {
"all_satisfied": all(len(v) == 0 for v in violations.values()),
"total_violations": sum(len(v) for v in violations.values()),
"by_constraint": {hc: len(lst) for hc, lst in violations.items()},
}
各シナリオの結果には必ず以下を記録する:
solver_status (ソルバーの内部ステータス)hc_all_satisfied (独立検証の結果)hc_total_violations (違反総数)hc_violations_by_constraint (HC別の違反内訳)レポートには hc_all_satisfied を主として表示し、「ソルバーが解を返した」と「元の HC を全て満たした」を区別すること。
ソフト化シナリオ(HC1 soft, HC8 soft など)は、原則として hc_all_satisfied = false になる(緩和した HC が違反する)。
■ チェック1: ハード制約の完全一致
spec.md の「ハード制約」テーブルの全項目が、ソルバーコードに制約として実装されているか?
手順:
1. spec.md から HC1, HC2, ... を列挙する
2. scripts/ 内の全 .py ファイルを検索し、各 HC が model.Add() で実装されているか確認
3. コードにあるが spec にない制約がないか(逆方向チェック)
よくあるミス:
- spec で HC→SC に変更したのに、コードがまだ model.Add() のまま(ペナルティになっていない)
- 新しい HC を spec に追加したのに、コードに未反映
■ チェック2: ソフト制約と目的関数の対応
spec.md の「ソフト制約」テーブルの全項目が、目的関数のペナルティ項に含まれているか?
手順:
1. spec.md から SC1, SC2, ... を列挙する
2. model.Minimize() の中身を確認し、各 SC に対応するペナルティ項があるか
3. 重みの大小関係が spec の「重み」列と矛盾していないか
よくあるミス:
- SC を追加したのに目的関数に項がない
- 「重み: 高」なのに実際の係数が小さい
■ チェック3: 仮定の値の一致
spec.md の「仮定」テーブルの値が、コード内の定数と一致しているか?
手順:
1. spec.md から仮定(A1, A2, ...)の値を列挙する
2. コード内の対応する定数・パラメータと突合する
よくあるミス:
- spec で移動速度を 30→22 km/h に更新したのに、コードが 30 のまま
- 作業時間の仮定を変えたのに評価関数の定数が古い
■ チェック4: 評価関数と目的関数の一致
evaluate() 関数が計算するスコアと、ソルバーの目的関数が最適化する対象が一致しているか?
手順:
1. evaluate() が使う項目を列挙
2. model.Minimize() が使う項目を列挙
3. 差分がないか確認
よくあるミス:
- evaluate() に新しい SC を追加したのに、ソルバー側に未反映(逆も同様)
- ペナルティの計算式が evaluate() と model で異なる
■ チェック5: 仕様書内の矛盾検出 spec.md 内で制約同士が矛盾していないか?情報源が古くなっていないか?
手順: 1. ハード制約同士の矛盾: HC-A と HC-B が同時に満たせない場合がないか 例: 「全員週40h以上」と「1日1シフトのみ」が10人×21シフトで矛盾 2. ハード制約とソフト制約の矛盾: HC が SC を無意味にしていないか 例: HC「夜勤禁止」と SC「夜勤週2回以下」が共存(SCが不要) 3. 仮定と制約の矛盾: 仮定の値が制約と整合しているか 例: 「作業時間10分」の仮定なのに「1件30分」の制約がある 4. 情報源の鮮度: Ref の取得日が古い項目はないか 例: 3ヶ月前のヒアリング結果を根拠にした制約が、その後変わっていないか
矛盾や古い情報が見つかった場合: → 確認型質問書(/opt-request 形式)を生成して依頼者に確認する → 「R3(2026-04-01 ヒアリング)で『夜勤2名必須』とありましたが、 R5(2026-04-03 メール)では『1名でも可』と読めます。 現在の正はどちらですか? A) 2名必須(R3 が正) B) 1名でも可(R5 が正) C) 条件による(___)」
**チェック結果は `reports/improve_report.md` の QA セクションに記録すること。**
**矛盾や確認が必要な項目があれば、確認型質問書を `reports/data_request.md` に追記すること。**
### 6. 出力
**以下のMarkdownをバージョンフォルダ内の `reports/improve_report.md` に保存すること。** 改善スクリプトは `scripts/` に、数値結果は `results/` に保存する。
```markdown
## 改善結果
| 手法 | Feasible | 違反数 | スコア | vs ベースライン |
|------|----------|--------|--------|----------------|
| ベースライン(ソルバー) | ... | ... | ... | 基準 |
| 改善策A | ... | ... | ... | +XX% |
| 改善策B | ... | ... | ... | +XX% |
## 何が効いたか
- [最も効果的だった改善と、なぜ効いたかの説明]
## ソフト制約バリエーション比較
| バリエーション | 充足率 | SC1 | SC2 | SC3 | SC4 | SC5 | 総合 |
|--------------|--------|-----|-----|-----|-----|-----|------|
| A バランス型 | ... | ... | ... | ... | ... | ... | ... |
| B ○○重視 | ... | ... | ... | ... | ... | ... | ... |
| C ○○重視 | ... | ... | ... | ... | ... | ... | ... |
(各スコアは 0-100。100 = 完全遵守)
### トレードオフの説明
- [「公平性を上げると夜勤制限が犠牲になる」等]
- [全バリエーションが同じ場合: 「トレードオフの余地がないほど制約がきつい」]
## まだ解決していない課題
- [残っている違反/スコア不足の原因]
## 追加で必要な情報
- [ ] [具体的に何が欲しいか]
## QA チェック結果
| チェック項目 | 結果 | 備考 |
|-------------|------|------|
| HC の spec↔コード一致 | ✓ / ✗ | [不一致があれば詳細] |
| SC の spec↔目的関数一致 | ✓ / ✗ | |
| 仮定値の spec↔コード一致 | ✓ / ✗ | |
| 評価関数↔目的関数一致 | ✓ / ✗ | |
| 仕様書内の矛盾 | ✓ / ✗ | [矛盾があれば詳細] |
| 情報源の鮮度 | ✓ / ✗ | [古い Ref があれば詳細] |
## 次のステップ
→ もう1周改善する or /opt-report で報告書
.opt_state.yaml の baseline セクションを読み込む.opt_state.yaml の improve セクションを書き込むreference/state_schema.md を参照原因と対策:
├── 目的関数と評価関数のズレ → パターン1(最優先で確認)
│ evaluator のコードを精読し、ソルバー目的関数との差分を特定
├── ボトルネックの特定が間違っている → /opt-baseline に戻って再分析
├── 問題の分解方向が間違っている
│ → 悪い分解の例: 「いつ」と「何を」を分離してスキル制約を破壊
│ → 違反の原因を分析して、原因を解消する方向で分解する
└── 下界に近い → 思考回路⑥で改善余地を確認。余地がなければこれが限界
原因と対策:
├── 目的関数にハード制約のペナルティが不足
│ → ハード制約違反のペナルティを10倍にする
├── ソフト制約の改善がハード制約を破壊している
│ → パターン6: まず feasibility だけ追求 → 次に品質改善
└── 制約間の相互作用が複雑
→ SWO+IFS(パターン4)やソルバー修復(パターン5)を検討
原因と対策:
├── 評価関数にノイズがある → 同じ入力で複数回評価して平均を取る
├── 探索空間が広すぎる → 1つのパラメータだけ変えて効果を確認
├── 進化の方向がランダム → ReEvo方式で「なぜダメだったか」の分析を挟む
└── そもそもLLM進化が向かないケース
→ feasibility問題にはソルバーを使う(LLM進化はソフト制約向き)
原因と対策:
├── 問題規模が大きい → 分解する(パターン3: Cluster+ソルバー)
├── 制約が多すぎる → 不要な制約を削減(本当に必要か再確認)
├── 対称性がある → 対称性除去制約を追加(ソルバーの探索を効率化)
└── 時間制限内に良い解が欲しい
→ add_hint() で初期解を与える(warm start)
→ まず短時間で feasible を見つけ、残り時間で改善