Javaの巡回セールスマン問題

1前書き

このチュートリアルでは、Simulated Annealingアルゴリズムについて学び、巡回セールスマン問題(TSP)に基づく実装例を紹介します。

2焼き鈍し法

シミュレーテッドアニーリングアルゴリズムは、大きな探索空間で問題を解決するための発見的手法です。

インスピレーションとその名は、冶金学における焼きなましから来ました。それは材料の加熱と制御された冷却を含む技術です。

一般に、シミュレーテッドアニーリングは、解空間を探索してシステムの温度を下げるので、より悪い解を受け入れる確率を下げます。次のhttps://commons.wikimedia.org/wiki/File:Hill Climbing with Simulated Annealing.gif[animation]は、Simulated Annealingアルゴリズムを使用して最適なソリューションを見つけるメカニズムを示しています。

リンク:/uploads/Hill Climbing with Simulated Annealing.gif[]

お分かりのように、このアルゴリズムはシステムの温度が高い場合はより広い解の範囲を使用し、大域的な最適条件を探します。温度を下げながら、検索範囲は、それが大域的最適条件を見つけるまで狭くなっています。

このアルゴリズムには、いくつかのパラメータがあります。

  • 反復回数 - シミュレーションの停止条件

  • 初期温度 - システムの起動エネルギー

  • 冷却速度パラメータ - 削減する割合

システムの温度 ** 最低温度 - オプションの停止条件

  • シミュレーション時間 - オプションの停止条件

これらのパラメータの値は慎重に選択する必要があります。これらの値はプロセスのパフォーマンスに大きな影響を与える可能性があるためです。

3巡回セールスマン問題

巡回セールスマン問題(TSP)は、現代世界で最もよく知られているコンピューター科学の最適化問題です。

簡単に言えば、グラフ内のノード間の最適経路を見つけることが問題です。総走行距離は、最適化基準の1つです。 TSPの詳細については、https://simple.wikipedia.org/wiki/Travelling salesman problem[ここ]をご覧ください。

4 Javaモデル

TSP問題を解決するためには、 City Travel の2つのモデルクラスが必要です。最初のものでは、グラフ内のノードの座標を格納します。

@Data
public class City {

    private int x;
    private int y;

    public City() {
        this.x = (int) (Math.random() **  500);
        this.y = (int) (Math.random() **  500);
    }

    public double distanceToCity(City city) {
        int x = Math.abs(getX() - city.getX());
        int y = Math.abs(getY() - city.getY());
        return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
    }

}

City クラスのコンストラクターを使用すると、都市の場所をランダムに作成できます。 distanceToCity(..) ロジックは、都市間の距離に関する計算を担当します。

次のコードは、巡回セールスマンツアーのモデリングを担当します。旅行中の都市の初期順序を生成することから始めましょう。

public void generateInitialTravel() {
    if (travel.isEmpty())
        new Travel(10);
    Collections.shuffle(travel);
}

最初の注文を生成することに加えて、我々は移動する注文においてランダムな2つの都市を交換するための方法が必要です。 Simulated Annealingアルゴリズムの中でより良い解決策を探すためにそれを使います。

public void swapCities() {
    int a = generateRandomIndex();
    int b = generateRandomIndex();
    previousTravel = travel;
    City x = travel.get(a);
    City y = travel.get(b);
    travel.set(a, y);
    travel.set(b, x);
}

さらに、新しい解が我々のアルゴリズムによって受け入れられないならば、前のステップで生成したスワップを元に戻す方法が必要です。

public void revertSwap() {
    travel = previousTravel;
}

最後に取り上げる方法は、総走行距離の計算です。これは最適化基準として使用されます。

public int getDistance() {
    int distance = 0;
    for (int index = 0; index < travel.size(); index++) {
        City starting = getCity(index);
        City destination;
        if (index + 1 < travel.size()) {
            destination = getCity(index + 1);
        } else {
            destination = getCity(0);
        }
            distance += starting.distanceToCity(destination);
    }
    return distance;
}

それでは、メイン部分であるSimulated Annealingアルゴリズムの実装に焦点を絞りましょう。

5シミュレーテッドアニーリングの実装

次のSimulated Annealingの実装では、TSP問題を解決します。ちょっと思い出してください、目的はすべての都市を旅行するための最短距離を見つけることです。

プロセスを開始するには、 startingTemperature numberOfIterations 、および coolingRate の3つの主なパラメータを指定する必要があります。

public double simulateAnnealing(double startingTemperature,
  int numberOfIterations, double coolingRate) {
    double t = startingTemperature;
    travel.generateInitialTravel();
    double bestDistance = travel.getDistance();

    Travel currentSolution = travel;
   //...
}

シミュレーションを開始する前に、最初の(ランダムな)都市の順序を生成し、移動のための合計距離を計算します。これが最初に計算された距離なので、 currentSolutionとともに bestDistance__変数の中に保存します。

次のステップで、メインシミュレーションループを始めます。

for (int i = 0; i < numberOfIterations; i++) {
    if (t > 0.1) {
       //...
    } else {
        continue;
    }
}

ループは指定した反復回数だけ続きます。さらに、温度が0.1以下になるとシミュレーションを停止する条件を追加しました。低温では最適化の違いがほとんど見えないので、シミュレーションの時間を節約することができます。

Simulated Annealingアルゴリズムの主な論理を見てみましょう。

currentSolution.swapCities();
double currentDistance = currentSolution.getDistance();
if (currentDistance < bestDistance) {
    bestDistance = currentDistance;
} else if (Math.exp((bestDistance - currentDistance)/t) < Math.random()) {
    currentSolution.revertSwap();
}

シミュレーションの各ステップで、移動順に2つの都市をランダムに入れ替えます。

さらに、currentDistanceを計算します。新しく計算された currentDistance bestDistance よりも小さい場合は、それを最良値として保存します。

そうでなければ、確率分布のボルツマン関数が0から1の範囲でランダムに選んだ値より低いかどうかをチェックします。そうだとすれば、私達は都市の交換を元に戻す。そうでない場合は、ローカルミニマムを回避するのに役立つので、都市の新しい順序を維持します。

最後に、シミュレーションの各ステップで、提供された__coolingRateによって温度を下げます。

t ** = coolingRate;

シミュレーションの後、Simulated Annealingを使って見つけた最良の解を返します。

  • 最良のシミュレーションパラメータを選択する方法に関するいくつかのヒントに注意してください。**

  • 小さなソリューションスペースの場合は、開始時間を短くすることをお勧めします。

温度を下げ、冷却速度を上げます。 品質を落とすことなくシミュレーション時間 ** より大きなソリューションスペースの場合は、より高い開始を選択してください

より局所的な極小値があるので、温度と小さい冷却速度 ** ハイからローへのシミュレーションに十分な時間を常に提供する

システムの温度

メインのシミュレーションを開始する前に、小さな問題のインスタンスを使ってアルゴリズムを調整することにある程度時間を費やすことを忘れないでください。シミュレーテッドアニーリングアルゴリズムの調整は、例えば、この記事ではhttps://www.researchgate.net/publication/269268529 Simulated Annealing algorithm for optimization of elastic optical networks with unicast and anycast traffic[]で示されました。

6. 結論

このクイックチュートリアルでは、Simulated Annealingアルゴリズムについて学ぶことができ、 巡回セールスマン問題を解決しました

これは、特定のタイプの最適化問題に適用したときに、この単純なアルゴリズムがどれほど便利であるかを示してくれることを願っています。

この記事の完全な実装はhttps://github.com/eugenp/tutorials/tree/master/algorithms-genetic[over on GitHub]で見つけることができます。