Sera OT??
Roberto Bonvallet
rbonvall en inf.utfsm.cl
Mar Abr 27 13:39:40 CLT 2004
Arturo Mardones escribio:
> Tengo q hacer un programa para "resolver" el problema del vendedor
> viajero (con heuristica claro esta)... Y no se q lenguaje utilizar...
Eso es OT. Para no estar (tan) OT, se me ocurrio programar una
heuristica en Bash; si te decides por alguna shell Unix, esto te puede
ser de ayuda. Puedes usar esta matriz como entrada para probarla con 6
ciudades (copiala en un archivo y se lo pasas al programa)
24 22 23 17 25
21 33 15 24
26 24 27
23 21
19
He aqui el script:
#!/bin/bash
# Implementación de la heurística Nearest Neighbor
# para el problema del vendedor viajero
# 20040427 by rbonvall
# uso: tsp -c nro_ciudades -d archivo_distancias
# Si dij es la distancia entre las ciudades i y j,
# archivo_distancias tiene el siguiente formato:
# d12 d13 d14 ... ... d1n
# d23 d24 d25 ... d2n
# .
# :
# d(n-2)(n-1) d(n-2)n
# d(n-1)n
# mensaje de error de uso
uso="Uso: $0 -c nro_ciudades -d archivo_distancias"
# distancia máxima imposible entre ciudades
infinito=999999
# archivo temporal
temp=/tmp/tmp$$
if [ -f $temp ]
then
rm -f $temp
fi
touch $temp
# parsea argumentos
c_flag=
d_flag=
set -- $(getopt c:d: "$@")
[ $# -lt 1 ] && exit 1 # getopt failed
while [ $# -gt 0 ]
do
case "$1" in
-c)
nro_ciudades="$2"
c_flag=1
shift
;;
-d)
archivo_distancias="$2"
if [ -f $archivo_distancias ]
then
distancias=$(cat $archivo_distancias)
else
echo "No existe el archivo $archivo_distancias"
exit 1
fi
d_flag=1
shift
;;
*)
break
;;
esac
shift
done
if ! [ $c_flag ] || ! [ $d_flag ]
then
echo >&2 $uso
exit 1
fi
inicial=1 # ciudad desde la que se iniciará el ciclo
actual=$inicial # ciudad en la que va el ciclo
# iteramos hasta que en el archivo de salida estén todas las ciudades
while [ $(wc -l $temp| sed -e 's/^[ ]*//g'| cut -d' ' -f 1) -lt $nro_ciudades ]
do
echo "Ciudad actual: $actual"
# agrega ciudad actual al ciclo
echo $actual >> $temp
# inicializa mínima distancia y ciudad más cercana
min_dist=$infinito
ciudad_mas_cercana=
# busca vecina más cercana
for vecina in $(seq $nro_ciudades)
do
# determina qué ciudad tiene número menor para
# saber cómo buscar la distancia en el archivo
if [ $vecina -lt $actual ]
then
max=$actual
min=$vecina
elif [ $vecina -gt $actual ]
then
max=$vecina
min=$actual
fi
if ! [ "$(grep "$vecina" $temp)" ] # evitamos ciudades ya visitadas
then
# calcula la distancia entre la ciudad actual y la vecina
dist=$(awk "NR == $min { print \$($max - $min) }" < $archivo_distancias)
echo "Distancia de $actual a $vecina: $dist"
# determina si esta vecina es la más cercana
if [ $dist -le $min_dist ]
then
min_dist=$dist
ciudad_mas_cercana=$vecina
fi
fi
done
echo "Ciudad más cercana a $actual: $ciudad_mas_cercana"
# nos movemos a la vecina más cercana
actual=$ciudad_mas_cercana
done
echo "El ciclo es:"
cat $temp
rm $temp
--
Roberto Bonvallet
Más información sobre la lista de distribución Linux