Floydの問題を解くためにクヌースが考案したヒューリスティクスの概要をまとめる。
1〜50までの整数がある。これをA、Bの2つの組にわけ、それぞれ組においてルートをとって和をとる。この和がもっとも近くなるようにA、Bを決めよ。
すなわち、
U = \{1, 2, 3, , , 50\}
A \subset U
B = U - A
Sa = \sum _{a \in A} \sqrt{a}
Sb = \sum _{b \in B} \sqrt{b}
としたとき、
Sa - Sbが最小となるような集合Aを求めよ。
注)本当は10秒という制限がある。
まず、小数点以下を合わせ、その後に整数部分を考える。
クヌースのヒューリスティクスの評価回数は45056 + 2^26 + 2^8 ≒ 2^26≒6.7 * 10^7である。
<原典>
Are Toy Problems Useful?
Knuth
(in Selected Papers on Computer Science)
(Originally published in Popular Computing, Volume 5, Number 1 (January1977) and Volume 5, Number 2 (Feburary 1977).)
最適解の精度は10^-12。桁数は整数を含めて15桁。全探索で評価回数は2^49 = 5.6 *
10^14回。
最適解の一つは(もちろんこの精度を実現する組み合わせは複数ある)
A = {7, 8, 12, 13, 15, 16,
25, 27, 30, 31, 33, 36, 37, 38, 41, 43, 44, 45,46, 47, 48, 49}
Sa =
119.517900301760320754230296092
Sb = 119.517900301760463739810150134
(By
T.Y)
手法 精度 一致している桁数
(およそ)評価回数 実時間 CPUクロック クヌースの手法 1.42986*10^-13 15桁 6.7*10^7 18秒 N君のアルゴリズム N(A)=19 4.5*10^3 N(A)=20 2.7*10^7 N(A)=21 3.2*10^9 N(A)=22 1.42986*10^-13 15桁 7.1*10^10 N(A)=23 1.42986*10^-13 15桁 5.2*10^11 一点交叉GA 3.17086*10^-6 8桁 4.59*10^6 123秒 一様交叉GA 4.34532*10^-7 9桁 4.59*10^6 198秒 Messy GA 1.40172*10^-8 10桁 4.59*10^6 108秒 EDA
実時間についてはPentium4 3GHz WindoowsXP ハイパースレッディング(およそ1GHz) Cygwinコンパイラでの時間。N君のアルゴリズムについてはこちらを参照。GAの詳細についてはここを参照。
N君のアルゴリズムとは集合Aの要素数N(A)を固定した探索手法。基本的に全探索するが、探索の打ち切りをうまく使うため、N(A)が小さいときは評価回数を減らすことができる。これ以上深く探索しても絶対に良い解が得られないと分かっているときのみ、探索を打ち切りを行う。探索の打ち切りはプログラムの実行時にしか決まらず、どれくらい評価回数を減らすことができるかも事前には分からない。本来、N(A)=24、N(A)=25でも探索を行うべきであるが、計算時間がかかりすぎるため実行することができなかった。
N(A) 実際の評価回数 全探索をした場合の評価回数(50CN(A)) 実際に評価した割合 19 4.5 * 10^3 3.0 * 10^13 1.4 * 10^-10 20 2.7 * 10^7 4.7 * 10^13 5.7 * 10^-7 21 3.2 * 10^9 6.7 * 10^13 4.7 * 10^-5 22 7.1 * 10^10 8.8 * 10^13 8.0 * 10^-4 23 5.2 * 10^11 1.0 * 10^14 4.8 * 10^-3