シミュレーテッドアニーリング (SA)
シミュレーテッド アニーリング (SA) は、困難なブラック ボックスに対処するための最もシンプルで最もよく知られたメタヒューリスティック手法の 1 つです。 目的関数が明示的に与えられておらず、コストのかかるコンピュータ シミュレーションを通じてのみ評価できるグローバル最適化問題。実際のアプリケーションで大量に使用されています。SA の主な利点はそのシンプルさです。SA は、材料の物理的アニーリングとの類似性に基づいており、効率的なメトロポリス許容基準のおかげで、モンテカルロ アプローチの欠点 (極小値に閉じ込められる可能性がある) を回避します。目的関数の評価が、多くのメモリを必要とする大次元の状態空間を操作する複雑なシミュレーション プロセスの結果である場合、母集団ベースのアルゴリズムは適用できず、SA はそのような問題に対処するための正しい答えです。この章はこの主題の紹介です。ローカル検索最適化アルゴリズムの原理を示します。シミュレーテッド アニーリングはその拡張であり、メトロポリス アルゴリズムは SA の基本コンポーネントです。最適化のための基本的な SA アルゴリズムは、SA の基本である 2 つの理論的特性、統計的平衡 (初等統計物理学からインスピレーションを受けた) と漸近収束 (マルコフ連鎖理論に基づく) とともに説明されています。この章では、特定のアプリケーション向けに SA アルゴリズムを実装したいユーザーにとって興味深い次の実際的な問題について概説します。理論上の SA の有限時間近似、多項式時間冷却、マルコフ連鎖の長さ、停止基準、およびシミュレーションベース評価。これらの概念を説明するために、この章では、2 つの古典的および単純な古典的な NP ハード組み合わせ最適化問題への SA の直接的な適用を示します。ナップザック問題と巡回セールスマン問題。次に、全体的な SA 手法が実際のアプリケーション、つまりヨーロッパ大陸規模で 30,000 近くの飛行を伴う大規模な航空機の軌道計画問題に詳細に展開されます。これは、この章で説明する SA の基本理論に触発され、問題の特定の特徴を利用し、アルゴリズム内に賢明なコンピューター実装を統合し、経験的にユーザー定義のパラメーターを設定することによって、SA の単純なスキームを使用して今日の複雑な問題に取り組む方法を例示しています。 。
シミュレーテッドアニーリング (SA)
シミュレーテッド アニーリング (SA) は、目的関数が明示的に与えられず、一部の高価なコンピューター シミュレーションによってのみ評価できる、困難なブラック ボックスのグローバル最適化問題を解決するための最も単純で最もよく知られたメタ ヒューリスティック手法の 1 つです。実生活でもよく使われます。SA の主な利点はそのシンプルさです。SA は材料の物理的アニーリングの類似性に基づいており、効果的なメトロポリス許容基準によるモンテカルロ法の欠点 (極小値にトラップされる可能性) を回避します。目的関数の評価が、大量のメモリを必要とする大次元の状態空間を扱う複雑なシミュレーション手順によって生成される場合、母集団ベースのアルゴリズムは適用できず、SA はこれらの問題に対する正しい答えです。この章はこのトピックの紹介です。局所探索最適化アルゴリズムの原理が導入され,シミュレーテッドアニーリングアルゴリズムはその拡張であり,メトロポリスアルゴリズムはSAの基本コンポーネントである。最適化のための基本的な SA アルゴリズムと、SA の 2 つの基本的な理論的特性、統計的平衡 (初等統計物理学に基づく) および漸近収束 (マルコフ連鎖理論に基づく) について説明します。この章では、特定のアプリケーション向けに SA アルゴリズムを実装したいユーザーにとって興味深い次の実際的な問題について概説します。理論上の SA への有限時間近似、多項式時間冷却、マルコフ連鎖の長さ、停止基準、およびシミュレーション ベースの評価です。これらの概念を説明するために、この章では、2 つの古典的で単純な NP ハード組み合わせ最適化問題、つまりナップザック問題と巡回セールスマン問題に SA を直接適用します。次に、全体的な SA アプローチが実際のアプリケーション、つまりヨーロッパ大陸を横断するほぼ 30,000 回の飛行を伴う大規模な航空機の軌道計画問題に詳細に展開されます。これは、この章で説明する SA の基本理論に触発されて、問題固有の機能を活用し、アルゴリズムに精通したコンピューター実装を統合し、経験的にユーザーを設定することによって、SA の単純なスキームを利用して今日の複雑な問題を解決できる方法を例示しています。
シミュレートされたアニーリング C# ソース プログラム
システムを使用する;
namespace Legalsoft.Truffer
{ /// <summary> /// シミュレートされたアニーリング /// </summary> public class Anneal { public Ranq1 myran;
public Anneal()
{ this.myran = new Ranq1(1234); }
public void order(double[] x, double[] y, int[] iorder)
{ const double TFACTR = 0.9;
int i1;
int i2;
int nn;
int[] n = 新しい int[6];
ダブルパス = 0.0;
二重 t = 0.5;
int ncity = x.Length;
int nover = 100 * ncity;
int nlimit = 10 * ncity;
for (int i = 0; i < ncity - 1; i++)
{ i1 = iorder[i]; i2 = iorder[i + 1]; パス += alen(x[i1], x[i2], y[i1], y[i2]); i1 = iorder[ncity - 1]; i2 = iorder[0]; パス += alen(x[i1], x[i2], y[i1], y[i2]);
//Console.Write(@fixed);
for (int j = 0; j < 100; j++)
{ int nsucc = 0; for (int k = 0; k < nover; k++) { do { n[0] = (int)(ncity * myran.doub()); n[1] = (int)((ncity - 1) * myran.doub()); if (n[1] >= n[0]) { ++n[1]; nn = (n[0] - n [ 1] + ncity - 1) % ncity; while (nn < 2);
if (myran.doub() < 0.5)
{ n[2] = n[1] + (int)(Math.Abs(nn - 1) * myran.doub()) + 1; n[2] %= ncity; double de = trncst(x, y, iorder, n); bool ans = metrop(de, t); if (ans) { ++nsucc; パス += デ; trnspt(iorder, n); } } else { double de = revcst(x, y, iorder, n);
bool ans = metrop(de, t);
if (ans)
{ ++nsucc; パス += デ; reverse(iorder, n); if (nsucc >= nlimit) { ブレーク ; } } //Console.Write("{0:6}", "\n"); //Console.Write("{0:6}", "T = "); //Console.Write("{0,12:6}", t); //Console.Write("{0,12:
//Console.Write("{0,12:6}", パス);
//Console.Write("{0:6}", "\n");
//Console.Write("{0:6}", "成功した移動: ");
//Console.Write("{0:6}", nsucc);
//Console.Write("{0:6}", "\n");
t *= TFACTR;
if (nsucc == 0)
{ 戻り値; } } }
public double revcst(double[] x, double[] y, int[] iorder, int[] n)
{ double[] xx = new double[4]; double[] yy = 新しい double[4]; int ncity = x.Length; n[2] = (n[0] + ncity - 1) % ncity; n[3] = (n[1] + 1) % ncity; for (int j = 0; j < 4; j++) { int ii = iorder[n[j]]; xx[j] = x[ii]; yy[j] = y[ii]; ダブルデ = -alen(xx[0], xx[2], yy[0], yy[2]); de -= alen(xx[1], xx[3], yy[1], yy[3]); de += alen(xx[0], xx[3], yy[0], yy[3]);
de += alen(xx[1], xx[2], yy[1], yy[2]);
戻ります。
}
public void reverse(int[] iorder, int[] n)
{ int ncity = iorder.Length; int nn = (1 + ((n[1] - n[0] + ncity) % ncity)) / 2; for (int j = 0; j < nn; j++) { int k = (n[0] + j) % ncity; int l = (n[1] - j + ncity) % ncity; int itmp = iorder[k]; iorder[k] = iorder[l]; iorder[l] = itmp; } }
public double trncst(double[] x, double[] y, int[] iorder, int[] n)
{ double[] xx = new double[6]; double[] yy = 新しい double[6]; int ncity = x.Length; n[3] = (n[2] + 1) % ncity; n[4] = (n[0] + ncity - 1) % ncity; n[5] = (n[1] + 1) % ncity; for (int j = 0; j < 6; j++) { int ii = iorder[n[j]]; xx[j] = x[ii]; yy[j] = y[ii]; double de = -alen(xx[1], xx[5], yy[1], yy[5]); de -= alen(xx[0], xx[4], yy[0], yy[4]);
de -= alen(xx[2], xx[3], yy[2], yy[3]);
de += alen(xx[0], xx[2], yy[0], yy[2]);
de += alen(xx[1], xx[3], yy[1], yy[3]);
de += alen(xx[4], xx[5], yy[4], yy[5]);
戻ります。
}
public void trnspt(int[] iorder, int[] n)
{ int ncity = iorder.Length; int[] jorder = 新しい int[ncity]; int m1 = (n[1] - n[0] + ncity) % ncity; int m2 = (n[4] - n[3] + ncity) % ncity; int m3 = (n[2] - n[5] + ncity) % ncity; int nn = 0; for (int j = 0; j <= m1; j++) { int jj = (j + n[0]) % ncity; jorder[nn++] = iorder[jj]; } for (int j = 0; j <= m2; j++) { int jj = (j + n[3]) % ncity; jorder[nn++] = iorder[jj];
}
for (int j = 0; j <= m3; j++)
{ int jj = (j + n[5]) % ncity; jorder[nn++] = iorder[jj]; } for (int j = 0; j < ncity; j++) { iorder[j] = jorder[j]; } }
public bool metrop(double de, double t)
{ return de < 0.0 || myran.doub() < Math.Exp(-de / t); }
public double alen(double a, double b, double c, double d)
{ return Math.Sqrt((b - a) * (b - a) + (d - c) * (d - c)); } } }