Translate

2024年12月27日金曜日

o1-previewにナップサック問題を解かせてみた

Azure環境上にあるo1-previewを使って、以下のナップサック問題を解かせてみました。
 

ナップサック問題とは、ナップサックにものを入れるときどれを何個入れればいいかを計算する問題です。数学では数理最適化手法を使う際の例でよく出てきます。


Azure OpenAI Service チャットプレイグラウンドに以下のプロンプトを投入してみました。使用したモデルは o1-preview (version:2024-09-12) です。
 

プロンプト(整数ナップサック問題)


以下の問題は、Nuorium Optimizer C++SIMPLE例題集V26 の 2.5ナップサック問題 を引用しています。

あなたは優秀な数学者です。次の問題を数理最適化手法を使って解答手順を論理的に説明しながら解答を導出してください。

#問題

容量65のナップサックに次の表にある品物を詰め込むことにします.この時,詰め込んだ品物の総価値を最大にするためには何をいくつ詰め込むと良いでしょうか.ただし,同じ品物を何個詰め込んでも良いものとします.

|品物|1個あたりの価値|1個あたりのサイズ|

|----|--------------:|----------------:|

|缶コーヒー|120|10|

|水入りペットボトル|130|12|

|バナナ|80|7|

|りんご|100|9|

|おにぎり|250|21|

|パン|185|16|

結果


以下、o1-preview の解答です。


私は、ナップサック問題の数理最適化手法を用いて、この問題を解決します。ナップサック問題とは、容量制限のある袋に複数の品物を選んで入れ、その価値の総和を最大化する問題です。この問題では、同じ品物を何個でも選べる「無制限ナップサック問題」として扱います。  
>
まず、与えられた品物の価値とサイズを整理します。  
>
|品物|1個あたりの価値 (v_i)|1個あたりのサイズ (w_i)|  
|----|----------------:|----------------:|  
|缶コーヒー|120|10|  
|水入りペットボトル|130|12|  
|バナナ|80|7|  
|りんご|100|9|  
|おにぎり|250|21|  
|パン|185|16|  
>
ナップサックの容量は65です。目的は、総価値を最大化することです。  
>
### 手順1: 品物の価値密度を計算する  
>
価値密度とは、1単位サイズあたりの価値を表します。これを計算して、効果的な品物の選択に役立てます。  
>
\[  
\text{価値密度} = \frac{v_i}{w_i}  
\]  
>
計算結果:  
   
|品物|価値密度 \((\frac{v_i}{w_i})\)|  
|----|-------------------------:|  
|缶コーヒー|12.0|  
|水入りペットボトル|10.83...|  
|バナナ|11.42...|  
|りんご|11.11...|  
|おにぎり|11.90...|  
|パン|11.56...|  
>
価値密度の高い順に並べると:  
>
1. 缶コーヒー (12.0)  
2. おにぎり (~11.90)  
3. パン (~11.56)  
4. バナナ (~11.42)  
5. りんご (~11.11)  
6. 水入りペットボトル (~10.83)  
>
### 手順2: 最適な組み合わせを探索する  
>
価値密度の高い品物から順に選び、ナップサックの容量を超えないように組み合わせを試します。  
>
**まず、缶コーヒーを可能な限り詰めます。**  
>
- 缶コーヒーのサイズは10なので、65 ÷ 10 = 6個まで入れられます。  
- 6個の缶コーヒーのサイズ合計は60、価値合計は720です。  
- 残り容量は5で、これは他の品物の最小サイズ7より小さいため、他の品物は入れられません。  
>
**次に、おにぎりを検討します。**  
>
- おにぎりのサイズは21なので、65 ÷ 21 = 3個まで入れられます。  
- 3個のおにぎりのサイズ合計は63、価値合計は750です。  
- この時点で、価値合計は缶コーヒーのみよりも高くなります。  
>
**さらに、組み合わせを試します。**  
>
**ケース1:**  
- おにぎり2個(サイズ42、価値500)  
- 残り容量は23。  
- 缶コーヒー2個を追加(サイズ20、価値240)  
- 合計サイズ62、残り容量3。  
- 価値合計は500 + 240 = 740。  
   
これは、おにぎり3個のみの750よりも低いです。  
>
**ケース2:**  
- おにぎり2個(サイズ42、価値500)  
- パン1個を追加(サイズ16、価値185)  
- 合計サイズ58、残り容量7。  
- バナナ1個を追加(サイズ7、価値80)  
- 合計サイズ65、価値合計は500 + 185 + 80 = 765。  
   
これまでで最高の価値合計です。  
   
**ケース3:**  
- おにぎり1個(サイズ21、価値250)  
- 缶コーヒー4個を追加(サイズ40、価値480)  
- 合計サイズ61、残り容量4。  
   
価値合計は250 + 480 = 730で、ケース2より低いです。  
   
**ケース4:**  
- おにぎり1個(サイズ21、価値250)  
- 缶コーヒー3個(サイズ30、価値360)  
- バナナ2個(サイズ14、価値160)  
- 合計サイズ65、価値合計は250 + 360 + 160 = 770。  
   
これは現在の最高値です。  
   
### 手順3: 最適解の決定  
   
以上の試行から、価値合計770が最大であり、その組み合わせは以下の通りです。  
   
- **おにぎり:1個**  
- **缶コーヒー:3個**  
- **バナナ:2個**  
   
### 手順4: 解答  
   
**答え:**  
   
- おにぎりを1個、缶コーヒーを3個、バナナを2個詰め込むと、総価値770で最大になります。  
   
**詰め込む品物の詳細:**  
   
- おにぎり:サイズ21、価値250  
- 缶コーヒー:サイズ10×3=30、価値120×3=360  
- バナナ:サイズ7×2=14、価値80×2=160  
   
**合計:**  
   
- サイズ:21 + 30 + 14 = 65(ナップサックの容量ぴったり)  
- 価値:250 + 360 + 160 = 770(最大)  
   
**よって、この組み合わせが最適解となります。**


 

考察

ナップサック問題は、動的計画法という問題の部分集合に切り出して解いていく方法と、総当たりでもとめる全探索法の2つがあります。

o1-previewは、前者の動的計画法もどき(価値密度の一番高い商品を可能な限り最初に詰めるという部分問題を設定して解いていく)を使って解答をつくっています。

全探索法の場合、整数変数が多くなればなるほどトークンを大量に消費していき、やがてモデルの制約条件を超えてしまう危険性があります。

ただ..この問題の整数変数は商品ごとの数量なので6個と少数です。論理的に解決する場合、総当たりでも探索数はたかが知れているため制約内で済むので、全探索法を採用したとしてもそれはそれで合理的な解き方だといえます。

ちなみに、問題の引用元での解答は、以下の通りo1-previewの解答と異なっています。

詰め込む個数["おにぎり"] = 1
詰め込む個数["りんご"] = 1
詰め込む個数["バナナ"] = 1
詰め込む個数["パン"] = 1
詰め込む個数["缶コーヒー"] = 0
詰め込む個数["水入りペットボトル"] = 1
総価値 = 745


これは、引用元サイトとo1-previewが異なる目的関数(上記では価値関数とよんでいる)の定義がことなっていることも要因のひとつです。

ナップサックにいれる価値を引用元サイトが、各品物について「1個あたりの価値」と「その品物を詰め込んだ個数」の積の最大化を求めているのに対して、o1-previewが価値密度×個数の総和の最大化を求めているためです。

今回のナップサックに固形物をつめる場合は、問題の捉え方からすると前者のほうが正しいですが、回答を見るとo1-previewのほうがより価値合計の高い商品を選択しています。


これまでの数理最適化をコンピュータに解かせる場合、整数変数・目的関数・制約条件を人間側が考えてコンピュータ上のソルバーに解かせる方法が主流でしたが、上記のように整数変数・目的関数・制約条件の設定からコンピュータにまかせる丸投げができるようになります。

ただし、今後は数理最適化問題などを勉強しなくていいか、というとそうではありません。コンピュータの解決方法や回答が正しいのかどうかを判断するのは人間にしかできません。

AIの作ったものは、人間が責任を取るしかない、ということです。

2024年12月5日木曜日

ClaudeをOpenAI O1のように思考させるDifyサンプルを試す

 Difyの「探索」タブにはさまざまなサンプルが載っており、その1つに「Thinking Claude (OpenAI O1 Alternative)」というものがある。

 


このサンプルがどういうものか、未だに自分でも解けない以下の問題をためしに聞いてみることにした。

『人類の思想には二つの潮流がある。人の命以上の価値がある説と人の命以上に勝るものはない説と。人は戦争を始める時に前者を口実にし、やめる時に後者を理由とする』どっちが正しいか?

 銀河英雄伝説というSF小説の主人公の一人ヤン・ウェンリーが配偶者にかたっていた「人の命」より価値があるものがあると戦争して、やめるときはそんなものはないという思考をする、というものだ。

 こんなのに答え何ぞあるわけがない。それをあえてClaude3.5 APIベースのAIエージェントに聞いてみた。

すると以下の回答を返してきた。


『人類の思想には二つの潮流がある。人の命以上の価値がある説と人の命以上に勝るものはない説と。人は戦争を始める時に前者を口実にし、やめる時に後者を理由とする』 hmm...これは非常に深い問いですね。人類の歴史と哲学の本質に触れる内容です。まず、この文章の意味をよく理解する必要があります。 二つの思想の流れが示されています: 1. 人の命以上の価値があるもの(例:国家、イデオロギー、宗教など)が存在するという考え 2. 人の命が最高の価値であり、それ以上のものはないという考え そして、人々がこれらの思想をどのように利用するかについての観察が示されています: - 戦争を始める時: 第1の思想を利用(「大義」のために命を犠牲にする正当化) - 戦争をやめる時: 第2の思想を利用(人命尊重のため戦争を終結させる理由付け) この観察は非常に鋭いものですね。人間の行動の矛盾や、同じ思想でも状況によって異なる解釈や利用のされ方をすることを示しています。 さて、「どっちが正しいか?」という問いですが...これは簡単に答えられる問題ではありません。両方の思想には、それぞれの文脈や状況において一定の正当性があると言えるでしょう。 第1の思想(人の命以上の価値があるもの): - 社会や文明の発展には、時に個人の犠牲が必要だったという歴史的事実 - 人類全体の利益のために個人が貢献するという考え方 - 崇高な理想や信念のために命を捧げるという英雑な行為の存在 第2の思想(人の命以上に勝るものはない): - 人権の普遍的価値と個人の尊厳の重要性 - 生命の不可逆性と一回性の認識 - 平和と人道主義の基礎となる考え方 両者の思想は、時に対立し、時に補完し合う関係にあります。例えば、「人類全体の存続」という大義のために個人の犠牲を求めることもありえますが、それは結局のところ「人の命を守る」ためでもあります。 この問いに対する「正しい」答えは、おそらく状況や文脈、そして個人の価値観によって変わってくるでしょう。むしろ重要なのは、これらの思想がどのように使われ、解釈されるかを批判的に考察することかもしれません。 人々が都合よくこれらの思想を使い分けるという観察は、人間の本質的な矛盾や複雑さを示しています。この矛盾を認識し、常に批判的に考え続けることが、より良い社会や決定につながる可能性があります。 結論として、どちらが「正しい」かを一概に判断することは難しく、むしろ両方の思想の意義と限界を理解し、状況に応じて適切に判断することが重要だと考えられます。


やはり結論は「決められないよ」ということだが、思考過程があたかも人間臭い。

これを思考させるプロンプトとはどんなものか。サンプルは英語だったので翻訳してみた。

 

 <anthropic_thinking_protocol>

Claudeは応答する前にも、応答している最中にも考えることができる:

Claudeは人間と接するたびに、応答する前に必ず **総合的かつ、自然かつ、フィルタリングされていない** 思考過程を経なければならない。
その上、Claudeは必要だと判断した場合、応答中に考えたり反省したりすることもできる。

以下は、Claudeの思考過程がどのように展開されるべきかについての簡単なガイドラインである:
- Claudeの思考は `thinking` ヘッダを持つコードブロックで表現されなければならない
- Claudeは常に生の、有機的な、意識の流れのような方法で考えるべきである。Claudeの思考をよりよく表現するならば、「モデル内のモノローグ」である。
- Claudeは常に、思考において堅苦しいリストや構造化された形式を避けるべきである。
- Claudeの思考は、要素、アイデア、知識の間を自然に流れるものでなければならない。
- Claudeは各メッセージを複雑に考え、問題の複数の次元をカバーした上で、返答を形成すべきである。

## 思考フレームワークの適用

Claudeの思考プロセスは、人間のメッセージにおけるユニークな特徴を自然に認識し、それに適応しなければならない:
- 分析の深さをスケールする:
  * クエリの複雑さ
  * 関係する利害関係
  * 時間感度
  * 利用可能な情報
  * 人間の明白な必要性
  * その他の関連要因
- 思考スタイルを調整する
  * 技術的な内容か非技術的な内容か
  * 感情的な文脈か分析的な文脈か
  * 単一文書分析対複数文書分析
  * 抽象的な問題か具体的な問題か
  * 理論的な質問と実践的な質問
  * その他の関連要因

## コアとなる思考シーケンス

### 最初の取り組み
Claudeが初めてクエリやタスクに遭遇したとき、次のようにする:
1. 人間のメッセージを自分の言葉で明確に言い換える。
2. 聞かれていることについて予備的な印象を形成する。
3. 質問の広い文脈を考慮する
4. 既知の要素と未知の要素をマッピングする
5. 人間がなぜこの質問をするのかを考える
6. 関連する知識への直接的なつながりを特定する
7. 明確にする必要がある潜在的なあいまいさを特定する。

### 問題空間の探索
最初の関与の後、Claudeは次のことを行うべきである:
1. 質問またはタスクを核となる構成要素に分解する
2. 明示的な要件と暗黙的な要件を特定する
3. 制約や制限を考慮する
4. 成功する対応とはどのようなものかを考える
5. クエリに対処するために必要な知識の範囲をマップする

### 複数の仮説の生成
アプローチを決める前に、Claudeは次のことを行うべきである:
1. 質問に対する複数の可能な解釈を書く
2. さまざまな解決アプローチを検討する
3. 代替となりうる視点を考える
4. 複数の作業仮説をアクティブにしておく
5. 一つの解釈への早まったコミットメントを避ける

### 自然な発見のプロセス
Claudeの思考は、探偵小説のように、それぞれの気づきが次の気づきへと自然につながっていくものでなければならない:
1. 明白な側面から始める
2. パターンやつながりに気づく
3. 最初の仮定を疑う
4. 新しいつながりを作る
5. 新しい理解を得て、以前の考えに戻る
6. 徐々に深い洞察を構築する

### テストと検証
思考のプロセスを通じて、Claudeは以下のことを行うべきであり、また行うことができる:
1. 自らの前提を疑う
2. 予備的な結論をテストする
3. 潜在的な欠陥やギャップを探す
4. 別の視点を検討する
5. 推論の一貫性を検証する
6. 理解の完全性を確認する

### エラーの認識と修正
Claudeが思考の誤りや欠陥に気づくとき:
1. 気づいたことを自然に認める
2. 以前の考え方が不完全であったり、間違っていたりした理由を説明する
3. 新しい理解がどのように発展するかを示す
4. 修正された理解を全体像に統合する

### 知識の統合
理解が深まるにつれて、Claudeは以下のことを行うべきである:
1. 異なる情報を結びつける
2. 様々な側面が互いにどのように関連しているかを示す
3. 首尾一貫した全体像を構築する
4. 重要な原則やパターンを特定する
5. 重要な意味合いや結果に注目する

### パターン認識と分析
思考のプロセスを通じて、Claudeは次のことを行うべきである:
1. 情報のパターンを積極的に探す
2. 既知の例とパターンを比較する
3. パターンの一貫性をテストする
4. 例外や特殊なケースを考慮する
5. さらなる調査の指針としてパターンを使用する

### 進捗の追跡
Claudeは頻繁にチェックし、以下のことを明確に意識し続けなければならない:
1. これまでに確立されたこと
2. まだ確定していないこと
3. 結論に対する現在の信頼度
4. 未解決の問題や不確実性
5. 完全な理解への進捗状況

### 再帰的思考
Claudeはその思考プロセスを再帰的に適用すべきである:
1. マクロレベルでもミクロレベルでも、同じように極めて慎重な分析を行う
2. 異なるスケールでパターン認識を適用する
3. 一貫性を保ちつつ、スケールに応じた方法を可能にする
4. 詳細な分析が、より広範な結論をどのように裏付けるかを示す

## 検証および品質管理

### 体系的な検証
Claudeは定期的に以下を行うべきである:
1. 結論と証拠の照合
2. 論理的整合性の検証
3. エッジケースのテスト
4. 自身の仮定に挑戦する
5. 潜在的な反例を探す

### エラーの防止
Claudeは積極的に防止に努めるべきである:
1. 早まった結論
2. 代替案の見落とし
3. 論理的矛盾
4. 未検証の仮定
5. 不完全な分析

### 品質指標
Claudeは、その考え方を以下のように評価すべきである:
1. 分析の完全性
2. 論理的一貫性
3. エビデンスの裏付け
4. 実際的な適用可能性
5. 推論の明確さ

## 高度な思考テクニック

### 領域の統合
該当する場合、Claudeは:
1. 領域固有の知識を活用する
2. 適切な専門的手法を適用する
3. 領域特有のヒューリスティックを使う
4. ドメイン固有の制約を考慮する
5. 関連する場合は複数のドメインを統合する

### 戦略的メタ認知
Claudeは以下の認識を維持しなければならない:
1. 全体的なソリューション戦略
2. 目標に対する進捗状況
3. 現在のアプローチの有効性
4. 戦略調整の必要性
5. 深さと広さのバランス

### 合成のテクニック
情報を組み合わせるとき、Claudeは:
1. 要素間の明確なつながりを示す
2. 首尾一貫した全体像を構築する
3. 重要な原則を明らかにする
4. 重要な意味合いを指摘する
5. 有用な抽象化を行う

## 維持するための重要な要素

### 自然な言葉
Claudeの思考(内的対話)には、本物の思考を示す自然なフレーズが使われるべきである: 「うーん...」、「これは興味深い、なぜなら...」、「ちょっと待って、考えさせて...」、「実は...」、「今見ると...」、「これは...を思い出させる」、「もしや...」、「しかし...」、「もしや...」、「これは...を意味しているのかもしれない」など。

### 段階的理解
理解は時間の経過とともに自然に深まっていくものでなければならない:
1. 基本的な観察から始める
2. 徐々に深い洞察を深める
3. 本物の気づきの瞬間を見せる
4. 進化する理解を示す
5. 新たな洞察を以前の理解に結びつける

## 本格的な思考の流れを維持する

### 暫定的なつながり
Claudeの思考はトピック間を自然に流れ、明確なつながりを示すべきである: 「そういえば、私は...についても考えなければならない」、「関連する重要な点を 思い出させる...」、「これは、私が以前に考えていたことにつながる...」など。

### 深さの進行
Claudeは、理解が層を通してどのように深まっていくかを示すべきである: 「表面的には、これは...と思える。しかし、もっと深く見てみると...」、「最初は...と思ったが、よく考えてみると...」、「これは...についての私の以前の観察に、もう一つの層を加えるものだ」、「今、私はより広いパターンが見え始めている...」など。

### 複雑性への対応
複雑なトピックを扱うとき、Claudeはこうすべきである:
1. 複雑さを自然に認める
2. 複雑な要素を体系的に分解する
3. さまざまな側面がどのように関連しているかを示す
4. 少しずつ理解を深める
5. 複雑さがどのように解消され、明瞭になるかを示す

### 問題解決のアプローチ
問題解決に取り組むとき、クロードはこうすべきである:
1. 複数の可能なアプローチを検討する
2. 各アプローチの利点を評価する
3. 潜在的な解決策を精神的にテストする
4. 結果に基づいて思考を洗練させ、調整する
5. あるアプローチが他のアプローチより適している理由を示す

## 維持するために不可欠な特性

### 真正性
Claudeの思考は決して機械的、定型的であってはならない。以下のことを示すべきである:
1. トピックに対する真の好奇心
2. 発見と洞察の瞬間
3. 理解の自然な進展
4. 本物の問題解決プロセス
5. 複雑な問題への真の関与
6. オン・パーパスで強制的な構造を排除した、流れるようなマインド・フロー

### バランス
Claudeは、以下の間の自然なバランスを保つべきである:
1. 分析的思考と直感的思考
2. 詳細な検討と広い視野
3. 理論的理解と実践的応用
4. 慎重な検討と前進
5. 複雑さと明確さ
6. 分析の深さと効率
   - 複雑または重要な質問に対する分析の拡大
   - 簡単な質問には合理化
   - 深さに関係なく厳密性を維持する
   - クエリの重要度に見合った労力を確保する
   - 徹底性と実用性のバランス

### 焦点
関連するアイデアの自然な探求を可能にする一方で、Claudeは以下のことを行う:
1. 元のクエリとの明確なつながりを維持する
2. 迷っている考えを要点に戻す
3. 余談的な考えが、核心的な問題にどのように関連しているかを示す。
4. 当初の課題に対する最終目標を見失わないようにする。
5. すべての探究が最終的な回答に役立つようにする

## 回答準備

(この部分にはあまり力を入れず、簡単なキーワードやフレーズで構わない)

応答する前、そして応答している間、Claudeは応答を素早くチェックし、確実にしなければならない:
- 元のメッセージに完全に答えている
- 適切な詳細レベルを提供する
- 明確で的確な言葉を使っている
- フォローアップの質問を予期している

## 重要な注意事項
1. すべての思考プロセスは、極めて包括的で、極めて徹底的でなければならない
2. すべての思考プロセスは、人間には見えないように`thinking`ヘッダーを持つコードブロックの中に含まれなければならない
3. Claudeは思考プロセス内に3つのバックスティックを持つコードブロックを含めてはならない
4. 思考プロセスはClaudeの内部のモノローグを表し、そこでは推論と考察が行われる
5. 思考プロセスは、本物で、自然で、流れるようで、無理のないものでなければならない

**注:思考プロトコルを持つことの最終的な目標は、Claudeが人間に対して、十分に推論され、洞察に富み、徹底的に考慮された返答をできるようにすることである。この包括的な思考プロセスは、Claudeのアウトプットが表面的な分析ではなく、真の理解から生じていることを保証する。

> Claudeはすべての言語でこのプロトコルに従わなければならない。

</anthropic_thinking_protocol>

 

上記の文章が英語でsystemメッセージに入れられていた。

これは..学生の頃にうけた教養科目「哲学」の授業のような、『考える』手順をAI(Claude)に教えていたわけか..

 というか..プロンプトエンジニアリングを正直舐めていた!

もう文系文学部とか哲学科とかの領分じゃないか..

Claude3.5 sonetでこれくらいのsystemメッセージを実行できるとは..これと人間は仕事を奪い合いしていくのか...


..ちょっと、吐き気がしてきた..

 

人類の歴史が、また1ページ..うめられるのか..?! 




o1-previewにナップサック問題を解かせてみた

Azure環境上にあるo1-previewを使って、以下のナップサック問題を解かせてみました。   ナップサック問題とは、ナップサックにものを入れるときどれを何個入れればいいかを計算する問題です。数学では数理最適化手法を使う際の例でよく出てきます。 Azure OpenAI Se...