1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

近似値クイズで、AIは「最適解」を見つけられるか?

Posted at

はじめに

GeminiとChatGPTの2つのAIに少し意地悪な最適化問題を解かせ、その実力を検証しました。
数理モデルで得られる「最適解」に対して、AIがどれだけ近い解を見つけられるかを見ていきます。

問題:近似値クイズ(数字の重複禁止)

AIにDeepResearchで解いてもらった問題は、以下の通りです。

下記の4つの問題の「#」に数字を埋めてください。

1. IPv4のビット数 = ##
2. ピアノの鍵盤の数 = ##
3. 北岳の標高 = 3###
4. 周期表の元素数 = ###

**ルール**
* 「#」は0から9のどれかを入れること
* 「#」に同じ数字を使わないこと
* 問題の解答と数字の差の和を最小化すること

正解とルールを満たす解答

本来の正解は次のとおりです。

  • IPv4のビット数 = 32
  • ピアノの鍵盤数 = 88
  • 北岳の標高(m) = (3)193
  • 元素の数 = 118

このままでは数字の「1」や「8」が重複しているため、ルールを満たせません。そこで、ルールを守りつつ、誤差の合計が最も小さくなる組み合わせを探すのがこの問題のゴールです。

数理最適化ソルバーで厳密解を求めたところ、最小誤差は44であることがわかりました。この最小誤差を達成する解の組み合わせは12通りあり、その一例がこちらです。

問題 解答例1 解答例2
IPv4のビット数 32 32
ピアノの鍵盤数 86 74
北岳の標高 (3)174 (3)186
周期表の元素数 95 95
誤差合計 44 44

※ 周期表の元素数(3桁)の解答が95のような2桁になる場合は、095と解釈します。

Gemini 2.5 Proの解答

Geminiは、やや決め打ちのような推論で、以下の解を導き出しました。

  • 解答
    • IPv4のビット数: 67
    • ピアノの鍵盤数: 89
    • 北岳の標高: (3)204
    • 周期表の元素数: 135
  • 使用数字: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 (重複なし)
  • 誤差の合計: 64
    • $|67-32| + |89-88| + |3204-3193| + |135-118| = 35 + 1 + 11 + 17 = 64$

最適解には及びませんでしたが、複雑な制約を理解して解を生成しました。

ChatGPTの解答

一方、ChatGPTは思考過程を示さなかったものの、次の解答を提示しました。

  • 解答
    • IPv4のビット数: 35
    • ピアノの鍵盤数: 89
    • 北岳の標高: (3)206
    • 周期表の元素数: 147
  • 使用数字: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 (重複なし)
  • 誤差の合計: 46
    • $|35-32| + |89-88| + |3206-3193| + |147-118| = 3 + 1 + 13 + 29 = 46$

誤差46は、最適解(44)にかなり近い値です。


まとめ(総評)

今回の検証結果をまとめます。

最適解 ChatGPT Gemini
誤差合計 44 46 64

両モデルとも、まずは各問題の本来の正解(32, 88, 3193, 118)を把握した上で、数字を重複させないという制約を満たすために、各数値を調整するアプローチをとっているようでした。

最適解を見つけることはできませんでしたが、ChatGPTの結果は最適解に近いです。これが偶然か工夫された推論かは不明ですが、このようなちょっと難しい最適化問題でも「それなりに良い解」が得られるのは興味深いです。

付録(数理最適化による解法)

以下のPythonコードを使えば、数理最適化で最小誤差の解を求められます。

import numpy as np
from mip import Model, minimize, xsum

m = Model()
nd = [2, 2, 3, 3]  # 桁数
ans = [32, 88, 193, 118]  # 正解

# 問題ごと・桁ごと・(1〜9の)数字ごとの0-1変数
xs = [
    m.add_var_tensor((nd[i], 9), f"x{i}", var_type="B")
    for i in range(4)
]
# 問題ごとの数字
ys = np.array([
    sum(xsum(xs[i][j] * range(1, 10)) * 10**j for j in range(nd[i]))
    for i in range(4)
])
# 問題ごとの誤差
zs = m.add_var_tensor((4,), "z")
# 全問題の桁ごと数字ごとの0-1変数
vs = np.vstack(xs)

m.objective = minimize(xsum(zs))  # 目的関数

for vx in vs:
    m += xsum(vx) <= 1  # 各桁は1つの数字をとる
for vw in vs.T:
    m += xsum(vw) == 1  # 各数字は一度しか使えない
for i in range(4):
    m += zs[i] >= ys[i] - ans[i]
    m += zs[i] >= ans[i] - ys[i]

m.optimize()
print(m.status, m.objective_value)
print(ys.astype(float))

結果

OptimizationStatus.OPTIMAL 44.0
[ 32.  86. 174.  95.]
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?