Algoritmo genetico commesso viaggiatore

di il
1 risposte

Algoritmo genetico commesso viaggiatore

Salve, era da realizzare un programma che facesse ciò:

Implementare in modo semplice in python un algoritmo che risolva il problema del commesso viaggiatore utilizzando per trovare la soluzione un algoritmo di ottimizzazione genetico:
è data una griglia bidimensionale di passo fissato. Posizionate 20 punti in 20 nodi della griglia scelti in modo random (città) il problema è quello di visitare tutte e 20 le città senza mai passare per due volte nella stessa città e minimizzando il cammino fatto.
Suggerimento: codificate il problema con un vettore soluzione di dimensione 20 che contiene l'indice di ciascuna città nell'ordine in cui le visitate e con il vincolo che non ci possono essere due elementi del vettore con eguale valore.
Partite da una soluzione random e eseguite mutazioni che conservano il vincolo (SWAP (esempio: (1,2,3) --> (1,3,2)) e CROSS-OVER ORDINATO (esempio: (1,2,3,4,5) e (3,5,1,4,2) --> (1,4,3,2,5))
evolvete solo le mutazioni positive (che minimizzano la distanza percorsa) mentre lasciate estinguere le soluzioni negative

Graficate poi la soluzione ogni N epoche

Ho fatto ciò utilizzando i suggerimenti dati da questo pdf http://phd.fisica.unimi.it/assets/Comp_Phys-esercizio4.pdf e questo è il risultato finale:
#ALGORITMO DEL COMMESSO VIAGGIATORE#
#PER SEMPLICITA' IL RETICOLO SARA' QUADRATO E CI SI MUOVERA' A PASSI DI 1#

import random
import numpy as np
import scipy.linalg
import matplotlib.pyplot as plt
%matplotlib inline

##################################################################################################

def random_swap(a): #Scambia a caso due indici adiacenti
  l = len(a)
  i = random.randint(0,l-1)
  if i != l-1 :
    a[i],a[i+1] = a[i+1], a[i]
  else:
    a[i],a[0] = a[0],a[i]

def xandy(lenght,point): #converte x+y*L in (x,y)#
  y = int(point/lenght)
  x = point - y*lenght
  return(x,y)

def euclidean_distance(x_a,y_a,x_b,y_b): #distanza euclidea#
  return np.sqrt((x_a - x_b)**2 + (y_a - y_b)**2)

def tot_dist(a): #Calcola la distanza totale percorsa in un cammino
  dist = 0
  x_c,y_c = 0,0
  for j in range(0,L):
    x,y = xandy(L,a[j])
    dist += euclidean_distance(x_c,y_c,x,y)
    x_c,y_c=x,y
  return dist

def crossover(x,y,r): #fa il crossover (a metà)#
  for i in range(r,L):
    for j in range(0,i):
      if x[j] != y[i]:
        x[i]=y[i]


###################################################################################################

L = 30
V = L*L 
cromosomi = [random.sample(range(0, V), L) for _ in range(V)]  #lista di liste contenenti i cammini#

fitness=[]
for i in range(0,V): #calcolo la distanza totale percorsa in ciascun cammino e riordino cromosomi con cammini da distanza minore a maggiore#
  distanza = tot_dist(cromosomi[i])
  fitness.append(distanza)

fitness, cromosomi = zip(*sorted(zip(fitness, cromosomi)))

for i in range(0,int(V/2)): 
  fitness = []
  best_genes = cromosomi[0].copy() #cammino più breve

  c = random.randint(0, L)  #faccio crossover tra i cammini a e b dall'elemento c in poi#
  a,b = random.sample(range(0,V),2)
  cromosomi_a = cromosomi[a].copy()
  crossover(cromosomi[a],cromosomi[b],c)
  crossover(cromosomi[b],cromosomi_a,c)

  c_a = cromosomi[a].copy()
  c_b = cromosomi[b].copy()
  random_swap(cromosomi[a]) #faccio lo swap di elementi adiacenti#
  random_swap(cromosomi[b])
 
  d_a_o = tot_dist(c_a)
  d_b_o = tot_dist(c_b)
  d_a = tot_dist(cromosomi[a])
  d_b = tot_dist(cromosomi[b])
  
  if d_a_o <= d_a: #accetto lo swap solamente se minimizza la distanza percorsa#
    for k in range(0,L):
     cromosomi[a][k] = c_a[k]
 
  if d_b_o <= d_b:
    for k in range(0,L):
     cromosomi[b][k] = c_b[k]

  for k in range(0,L):
    cromosomi[V-1][k] = best_genes[k]
  
  d = 0
  for i in range(0,V): #riordinamento
    d = tot_dist(cromosomi[i])
    fitness.append(d)
  fitness, cromosomi = zip(*sorted(zip(fitness, cromosomi)))
Ora, dato che vengo dal C, e questo è il primo anno che programmo in python seriamente, il mio modo di programmare è molto basato sul C, mi piacerebbe che mi deste qualche consiglio per rendere il programma migliore e segnalarmi eventuali errori, grazie.
Inoltre non saprei come graficare i vettori, pensavo con un grafo che unisce i punti sul reticolo, come potrei fare?

1 Risposte

Devi accedere o registrarti per scrivere nel forum
1 risposte