Le problème du voyageur de commerce en Java

1. Introduction

Dans ce didacticiel, nous étudierons l’algorithme de recuit simulé et montrerons l’exemple d’implémentation basé sur le problème du voyageur de commerce.

2. Recuit simulé

L’algorithme de recuit simulé est une heuristique permettant de résoudre les problèmes liés à un espace de recherche étendu.

L’Inspiration et le nom sont issus du recuit en métallurgie; c’est une technique qui implique le chauffage et le refroidissement contrôlé d’un matériau.

En général, le recuit simulé réduit la probabilité d’accepter des solutions pires lorsqu’il explore l’espace de solutions et abaisse la température du système. Le lien suivant https://commons.wikimedia.org/wiki/File:Hill Climbing with Simulated Annealing.gif[animation]montre le mécanisme permettant de trouver la meilleure solution avec l’algorithme d’Annelage simulé:

Comme on peut le constater, l’algorithme utilise une gamme de solutions plus large avec une température élevée du système, en recherchant l’optimum global. Tout en abaissant la température, la plage de recherche devient plus petite, jusqu’à ce qu’elle trouve l’optimum global.

L’algorithme a quelques paramètres avec lesquels travailler:

  • nombre d’itérations - condition d’arrêt pour les simulations

  • température initiale - l’énergie de démarrage du système

  • paramètre de vitesse de refroidissement - le pourcentage par lequel nous réduisons la

température du système ** température minimale - condition d’arrêt optionnelle

  • temps de simulation - condition d’arrêt optionnelle

Les valeurs de ces paramètres doivent être soigneusement sélectionnées car elles peuvent avoir une influence significative sur les performances du processus.

3. Problème de voyageur voyageur

Le problème du vendeur itinérant (TSP) est le problème d’optimisation informatique le plus connu du monde moderne.

En termes simples, il s’agit de trouver le chemin optimal entre les nœuds du graphe. La distance totale parcourue peut être l’un des critères d’optimisation. Pour plus de détails sur le TSP, consultez https://simple.wikipedia.org/wiki/Travelling salesman problem[here].

4. Modèle Java

Afin de résoudre le problème du TSP, nous aurons besoin de deux classes de modèle, à savoir City et Travel . Dans le premier, nous allons stocker les coordonnées des nœuds dans le graphique:

@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));
    }

}

Le constructeur de City class nous permet de créer des emplacements aléatoires des villes. La logique distanceToCity (..) est responsable des calculs relatifs à la distance entre les villes.

Le code suivant est responsable de la modélisation d’une tournée de voyageur de commerce. Commençons par générer l’ordre initial des villes en voyage:

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

En plus de générer l’ordre initial, nous avons besoin des méthodes pour permuter les deux villes aléatoires dans l’ordre de déplacement. Nous allons l’utiliser pour rechercher les meilleures solutions au sein de l’algorithme de recuit simulé:

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);
}

De plus, nous avons besoin d’une méthode pour inverser la génération de swap à l’étape précédente, si la nouvelle solution ne sera pas acceptée par notre algorithme:

public void revertSwap() {
    travel = previousTravel;
}

La dernière méthode que nous souhaitons couvrir est le calcul de la distance totale parcourue, qui servira de critère d’optimisation:

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;
}

Passons maintenant à la partie principale, l’implémentation de l’algorithme de recuit simulé.

5. Mise en oeuvre du recuit simulé

Dans l’implémentation suivante du recuit simulé, nous allons résoudre le problème du TSP. Juste un rappel rapide, l’objectif est de trouver la distance la plus courte pour parcourir toutes les villes.

Pour démarrer le processus, nous devons fournir trois paramètres principaux, à savoir startingTemperature , numberOfIterations et coolingRate :

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

    Travel currentSolution = travel;
   //...
}

Avant le début de la simulation, nous générons un ordre initial (aléatoire) des villes et calculons la distance totale parcourue. Comme il s’agit de la première distance calculée, nous l’enregistrons dans la variable bestDistance , aux côtés de la currentSolution.

Dans l’étape suivante, nous commençons une boucle de simulation principale:

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

La boucle durera le nombre d’itérations que nous avons spécifié. De plus, nous avons ajouté une condition pour arrêter la simulation si la température est inférieure ou égale à 0,1. Cela nous permettra de gagner du temps lors des simulations car, avec les basses températures, les différences d’optimisation ne sont pratiquement pas visibles.

Examinons la logique principale de l’algorithme de recuit simulé:

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

À chaque étape de la simulation, nous échangeons de manière aléatoire deux villes dans l’ordre de déplacement.

De plus, nous calculons la currentDistance . Si le currentDistance nouvellement calculé est inférieur à bestDistance , nous le sauvegardons comme meilleur

Sinon, nous vérifions si la fonction de Boltzmann de la distribution de probabilité est inférieure à la valeur choisie aléatoirement dans une plage de 0 à 1. Si oui, nous inversons l’échange des villes. Sinon, nous conservons le nouvel ordre des villes, car cela peut nous aider à éviter les minima locaux.

Enfin, à chaque étape de la simulation, nous réduisons la température en fournissant coolingRate:

t ** = coolingRate;

Après la simulation, nous renvoyons la meilleure solution que nous avons trouvée en utilisant le recuit simulé.

  • Veuillez noter quelques conseils pour choisir les meilleurs paramètres de simulation: **

  • pour les petits espaces de solution, il est préférable d’abaisser le nombre de points de départ.

la température et augmenter le taux de refroidissement, car il réduira la temps de simulation, sans perte de qualité ** pour les plus grands espaces de solution, veuillez choisir le départ le plus élevé

température et faible vitesse de refroidissement, car il y aura plus de minima locaux ** Toujours prévoir suffisamment de temps pour simuler de haut en bas

température du système

N’oubliez pas de passer un peu de temps sur l’algorithme pour régler l’instance de problème la plus petite avant de commencer les simulations principales, afin d’améliorer les résultats finaux. L’ajustement de l’algorithme de recuit simulé a été présenté, par exemple, à l’adresse https://www.researchgate.net/publication/269268529 Simulated Annealing algorithm for optimization of elastic optical networks with unicast and anycast traffic ™ dans cet article].

6. Conclusion

Dans ce rapide didacticiel, nous avons pu en apprendre davantage sur l’algorithme de recuit simulé et nous avons résolu le problème du voyageur de commerce .

Cela, espérons-le, montre à quel point cet algorithme simple est pratique lorsqu’il est appliqué à certains types de problèmes d’optimisation.

La version complète de cet article est disponible à l’adresse over sur GitHub .