J'ai essayé de créer un programme en Java qui résout le problème du voyageur de commerce avec un algorithme génétique

Je faisais des recherches pour résoudre avec un algorithme génétique, Je l'ai fait dans le sens d'augmenter le nombre d'étapes pour l'avenir.

Quel est le problème du voyageur de commerce?

C'est un problème de penser à l'ordre dans lequel vous pouvez passer le plus court si vous écrivez un trait à un certain point dans $ n $. Si le nombre de villes à écrire en un coup est $ n $, le nombre de combinaisons possibles est $ \ frac {(n-1)!} {2} $.

Qu'est-ce qu'un algorithme génétique?

C'est l'un des calculs d'évolution qui modélisent l'évolution des êtres vivants. La combinaison de solutions est considérée comme un chromosome, et la solution évolue en répétant des manipulations génétiques telles que le croisement et la mutation pour enfin trouver la meilleure solution.

Flux de classe

Puisque nous programmons en Java, nous examinerons chaque classe dans l'ordre. Le diagramme de classe est comme ci-dessous. Cliquez ici pour consulter la littérature référencée dans la conception [^ 1]

La classe de ce programme est la suivante. Class.jpg

Parmi eux, trois algorithmes génétiques sont utilisés: ** TourWithGA **, ** Chromosome ** et ** Individuals **.

En ce qui concerne la manipulation des gènes, la classe Chromosome met en œuvre des méthodes pour calculer la mutation et la compatibilité des gènes, et la classe Individual met en œuvre le croisement, la régénération / sélection de gènes et la conservation d'élite en tant que méthodes.

En tant que stratégie, il est créé en référence à la méthode de croisement d'échange de branche (EXX) proposée par Maekawa et al. [^ 2].

Comportement des algorithmes génétiques

Comme il y a beaucoup de code source, veuillez consulter le code source pour plus de détails. J'expliquerai les spécifications en me concentrant sur le fonctionnement dans l'algorithme génétique.

Données cartographiques

Entrez l'emplacement de la ville dans le problème du voyageur de commerce dans un fichier CSV. Le contenu du fichier CSV est

berlin52.csv


52,
565,575
25,185
345,750
945,685
845,655
880,660
25,230
・
・
・

Sur la première ligne, saisissez le nombre de villes lisibles. À partir de la deuxième ligne, entrez les coordonnées $ x $ et $ y $ de la ville.

La classe principale du programme est ** tspSample **. Lors de l'exécution en java

$ java tspSample <Fichier CSV à lire>

Veuillez exécuter comme ceci.

Si la lecture réussit,

city_num= 52
565.000	 575.000
25.0000	 185.000
345.000	 750.000
945.000	 685.000
845.000	 655.000
・
・
・

De cette manière, le nombre de villes lues et les données de ville sont sorties vers la console.

Génération individuelle initiale

Générer une population initiale qui manipule génétiquement les enfants de type Individus. Plus précisément, dans la classe des chromosomes, il est exprimé sous forme de séquence de villes sous forme de séquence génique. La classe Tour a une méthode appelée makeTour () qui génère un circuit de manière aléatoire. Après avoir généré le circuit, le circuit est copié dans la séquence du gène.

Calcul de conformité

Le degré de conformité est calculé sur la base de la mise à l'échelle de la loi de puissance. Le nombre de villes $ n $ peut être obtenu à partir de la classe Map, et la longueur du circuit $ l $ peut être obtenue à partir de la méthode getDistance () de la classe Tour.

\mathrm{Fitness} = \left(\frac{n}{l} \right)^3

Jouer / sélectionner

Dans le programme, nous utilisons deux classes individuelles. Effectuer une manipulation génétique avec ** les parents **. Dans la prochaine génération, ** les enfants ** survivront aux chromosomes de leurs parents en fonction du degré de compatibilité chromosomique. $ N_ {\ mathrm {p}} $ est stocké dans les parents, et $ N_ {\ mathrm {c}} $ est stocké dans les enfants. (Cependant, $ N_ {\ mathrm {p}} \ geq N_ {\ mathrm {c}} $)

Quant à la survie, les chromosomes $ N_ {\ mathrm {c}} $ supérieurs sont faits pour survivre dans l'ordre d'adaptabilité des chromosomes chez les parents. Cependant, comme les individus élites doivent toujours être inclus dans la population, si la compatibilité du chromosome le plus compatible de la population est supérieure à la compatibilité du chromosome élite, l'individu élite est le plus compatible de la population. Mettre à jour vers un chromosome supérieur. Sinon, remplacez le chromosome $ N_ {\ mathrm {c}} $ ème par un chromosome élite.

La méthode de sélection du chromosome parent à manipuler génétiquement à partir des enfants survivants de la population consiste à calculer la valeur attendue de survie chez l'individu parent à partir de la formule suivante lorsque le degré de compatibilité du chromosome $ C_i $ chez les enfants est $ f_i $.

\mathrm{Experience} = \frac{N_{\mathrm{p}} \times f_i}{N_{\mathrm{c}} \times \overline{f}}

$ \ Overline {f} $ est l'ajustement moyen des chromosomes chez les enfants. Sélectionnez le chromosome parent par le nombre de valeurs attendues (arrondi après la virgule décimale) et copiez-le dans le parent. La partie après la virgule décimale est utilisée pour la sélection de la roulette.

Pour tous les chromosomes, si vous sélectionnez autant de parents que vous le souhaitez, les parents auront des chromosomes vides. Les autres parents sélectionnent leurs parents par sélection de roulette.

Afin d'éviter que le même chromosome ne soit sélectionné parmi les parents sélectionnés, deux sont choisis au hasard dans le chromosome parent afin qu'ils ne se chevauchent pas, et ils sont croisés.

Croisement / mutation

Le croisement est basé sur la probabilité de croisement et la mutation est basée sur la probabilité de mutation. Voir la référence [2] pour plus de détails.

Correction génétique

L'algorithme génétique a une forte capacité à trouver une solution optimale globale, mais a une faiblesse dans la capacité de recherche locale. Par conséquent, le gène est corrigé par la méthode 2-opt, qui est l'une des méthodes d'amélioration séquentielle dans le problème du voyageur de commerce, avant le calcul de l'aptitude.

Je l'ai essayé

$ N_ {\ mathrm {c}} = 100 $, $ N_ {\ mathrm {p}} = 150 $, nombre maximum de générations: 300, probabilité de croisement: 0,8, probabilité de mutation: 0,1, 52 problème de référence de la ville Berlin52 (valeur optimale) : 7544,366)). .. Pour l'itinéraire terminé, les données seront sorties dans le fichier result.csv dans le même répertoire.

city_num= 52
565.000  575.000
25.0000  185.000
345.000  750.000

(Omis)

595.000  360.000
1340.00  725.000
1740.00  245.000
start...
    0    7742.647
    1    7742.647
    2    7742.647
    3    7742.647
    4    7544.366
    5    7544.366
    6    7544.366

(Omis)

  294    7544.366
  295    7544.366
  296    7544.366
  297    7544.366
  298    7544.366
  299    7544.366
  300    7544.366
7544.366
stop.
Temps de traitement: 3157/ms

à la fin

Ce croisement d'échange de branches est considéré comme la deuxième meilleure méthode après la méthode de croisement d'assemblage de branches pour résoudre le problème d'ordonnancement cyclique avec un algorithme génétique. Actuellement, la méthode utilisant le croisement par assemblage de branches est considérée comme la meilleure méthode pour résoudre l'algorithme génétique du problème du voyageur de commerce. J'aimerais l'essayer un jour. Étant donné que j'étudie les problèmes de planification, j'aimerais créer un programme qui résout les problèmes de planification.

Code source

Le code source est ouvert au public. Le code est peut-être sale parce que j'étais dans un laboratoire qui n'utilise pas beaucoup Java ... (N'hésitez pas à me donner des conseils.) https://github.com/SHIMADONBEY/GAwithTSP.git

Les références

[^ 2]: Maekawa, Tamaki, Kita, Nishikawa: Une solution au problème du voyageur de commerce utilisant un algorithme génétique, Proceedings of the Society of Automatic Measurements, Vol. 31, No 5, pp. 598-605, 1995.

[^ 1]: Hatayama: modélisation orientée objet GA, Faculté d'ingénierie de l'Université d'Ibaraki, 2010.

Recommended Posts

J'ai essayé de créer un programme en Java qui résout le problème du voyageur de commerce avec un algorithme génétique
J'ai créé un programme de jugement des nombres premiers en Java
J'ai fait un jeu de problèmes de calcul simple en Java
[Débutant] J'ai créé un programme pour vendre des gâteaux en Java
Comment gérer le type auquel j'ai pensé en écrivant un programme Java pendant 2 ans
Exemple de programme qui renvoie la valeur de hachage d'un fichier en Java
J'ai écrit un programme de jugement des nombres premiers en Java
J'ai créé un jeu Janken en Java (CLI)
J'ai écrit un programme de factorisation prime en Java
J'ai créé un programme qui recherche la classe cible à partir du processus surchargé avec Java
J'ai créé un Wrapper qui appelle KNP depuis Java
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
Création du framework JAVA "numatrix" qui génère facilement des valeurs numériques uniques dans un environnement distribué et multi-thread
Un programme (Java) qui génère la somme des nombres pairs et impairs dans un tableau
J'ai fait une roulette à Java.
J'ai créé un MOD qui appelle instantanément un véhicule avec Minecraft
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3
J'ai fait un "Sunshine Ikezaki game" que j'ai vu sur Twitter en Java.
Je ne peux pas créer une classe Java avec un nom spécifique dans IntelliJ
J'ai récemment créé une application js dans le langage courant de Dart
[Java] Je veux effectuer distinctement avec la clé dans l'objet
J'ai créé un PDF avec Java.
J'ai créé une application shopify @java
J'ai créé une interface graphique avec Swing
J'ai fait une annotation en Java.
J'ai essayé de résoudre les 10 dernières questions qui devraient être résolues après m'être inscrit auprès d'AtCoder en Java
Une histoire qui résout le problème que REMOTE_ADDR ne peut pas être acquis dans un cluster construit avec Docker Swarm + Traefik (1.7).
J'ai essayé de créer un exemple de programme en utilisant le problème du spécialiste des bases de données dans la conception pilotée par domaine
Déclarez une méthode qui a une valeur de retour Java avec le type de données de valeur de retour
Dispatcher Pattern (un nouveau modèle de conception qui résout le problème d'expression du modèle de visiteur)
J'ai essayé d'apprendre Java avec une série que les débutants peuvent comprendre clairement
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3 (édition PowerMockito)
J'ai essayé de résoudre le problème de la séquence Tribonacci en Ruby, avec récurrence.
J'ai écrit une fonction Lambda en Java et l'ai déployée avec SAM
Je veux ForEach un tableau avec une expression Lambda en Java
J'ai créé une classe qui peut utiliser JUMAN et KNP de Java
[LINE BOT] J'ai créé un Ramen BOT avec Java (Maven) + Heroku + Spring Boot (1)
[Java] Implémenter une fonction qui utilise une classe implémentée dans le modèle Builder
J'ai créé un site qui résume les informations sur la restriction du sucre avec Vue.js
J'ai essayé un problème de calendrier avec Ruby
Après avoir vérifié le problème de Montyhall avec Ruby, c'était une histoire que je pouvais bien comprendre et que je ne comprenais pas bien
J'ai essayé le nouveau yuan à Java
J'ai fait une mort risquée avec Ruby
J'ai créé une application Janken avec kotlin
Diviser une chaîne avec ". (Dot)" en Java
Je ne peux pas utiliser SQS qui peut lire le questionnaire avec un scanner → Je pourrais l'utiliser après avoir changé le ver java
J'ai créé un nouvel outil de déploiement Java
J'ai créé une application Janken avec Android
Création d'un exemple de programme en utilisant le problème d'un spécialiste des bases de données dans DDD Improvement 2
Faisons une application de calculatrice avec Java ~ Créez une zone d'affichage dans la fenêtre
Même en Java, je veux sortir true avec un == 1 && a == 2 && a == 3 (deuxième décoction Javassist)
Jusqu'à ce que vous exécutiez un programme Java avec le SDK AWS local sur Windows
Création d'un exemple de programme en utilisant le problème d'un spécialiste des bases de données avec DDD Improvement 1
Je ne savais pas que les classes internes pouvaient être définies dans l'interface [Java]
Valider le jeton d'ID d'un utilisateur authentifié par AWS Cognito en Java
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3 (Black Magic)
Même en Java, je veux sortir vrai avec un == 1 && a == 2 && a == 3 (magie grise qui n'est pas tant que magie noire)
Même en Java, je veux sortir true avec un == 1 && a == 2 && a == 3 (Royal road edition qui n'est ni magique ni rien)
J'ai créé un outil Diff pour les fichiers Java