viajant1.pas
{ ppc386 -va -vh *.pas }
{ COMIENZO DE DESCRIPCION
Problema del viajante mediante un algoritmo \'avido
versi\'on 1.
keywords: algoritmos
FIN DE DESCRIPCION }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
En cada etapa de un algoritmo avido buscamos la opcion
localmente optima lo cual, en el Problema del Agente de
Viajes (PAV), equivale a considerar cada ciudad por turno,
buscando la distancia mas corta a las ciudades todavia
no visitadas.
Para verificar que (i) no se produzca un vertice de grado
$ g = 3 $ (es decir, debemos entrar y salir de cada ciudad
solo una vez), y (ii) que no se forme un ciclo parcial con
las ciudades ya visitadas (excepto al final), procedemos de
la siguiente manera:
Previo al lazo de busqueda:
1 construimos una matriz de distancias $ A $ entre todas las
ciudades, donde cada elemento $ A_[ij] $ es la distancia
desde la ciudad $ i $ hasta la ciudad $ j $, para
$ i,j = 1, 2,...,n $, donde $ n $ es el numero de ciudades.
Se desprende que esta matriz de distancias:
(a) tendra diagonal principal nula, y
(b) los elementos $ A_[ij] $ fuera de la diagonal principal,
son simetricos;
2 inicializamos un vector de ciudades ya visitadas como falso ;
Ahora:
1 empezamos en alguna fila de la matriz (ciudad) $ p $, y
seleccionamos la columna $ j $ con la menor distancia
$ A_[pj] $ en esa fila, pero exceptuando: (a) el termino en
la diagonal principal $ A_[pp] $ (que es nulo), y (b) las
distancias $ A_[pj] $ a las ciudades $ j $ ya visitadas;
2 antes de cerrar el lazo de busqueda, marcamos la ciudad
$ p $ como visitada, pasamos a la fila $ j $, y repetimos
el proceso hasta agotar las filas disponibles en la matriz;
3 finalmente se cierra el circuito con la ciudad $ p $ de
partida.
Por ultimo, este codigo ademas hace un lazo $ p=1,2,..., n $
sobre todas las ciudades, dando una solucion para "n" agentes
de viajes que salgan desde cada ciudad. }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ $ Id: viajant1.pas 2002/04/05 19:00 jdelia Exp jdelia $}
program viajant1 ;
const
n = 6 ; {numero de ciudades consideradas}
o = ' ' ;
type
xcoord = record
x, y : real ;
end ;
tvecto1 = array [1..n+1] of char ;
tvecto2 = array [1..n] of boolean ;
tmatriz = array [1..n,1..n] of real ;
vcoorde = array [1..n] of xcoord ;
var
a : tmatriz ;
r : vcoorde ;
secuencia : tvecto1 ;
visitada : tvecto2 ;
i, j, k : integer ;
dx, dy : real ;
c_p : char ;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure ERROR (h: string);
begin
writeln (' error ',h);
writeln ;
halt ;
end ;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure IMPRIME (h : string ; var a: tmatriz);
var
i, j : integer ;
begin
writeln ;
writeln (h) ;
writeln ;
for i := 1 to n do begin
for j := 1 to n do write (o, a [i,j]:10) ;
writeln ;
end ;
writeln ;
end ;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure MATRIZ_DISTANCIA (var a: tmatriz);
var {pre-define las coordenadas cartesianas de las ciudades}
xi, xj : real ;
yi, yj : real ;
begin
r [1].x := 0 ; r [1].y := 0 ;
r [2].x := 4 ; r [2].y := 3 ;
r [3].x := 1 ; r [3].y := 7 ;
r [4].x := 15 ; r [4].y := 7 ;
r [5].x := 15 ; r [5].y := 4 ;
r [6].x := 18 ; r [6].y := 0 ;
for i := 1 to (n) do begin
xi := r [i].x ;
yi := r [i].y ;
for j := 1 to (n) do begin
xj := r [j].x ;
yj := r [j].y ;
dx := (xi - xj) ;
dy := (yi - yj) ;
a [i,j] := sqrt ( dx * dx + dy * dy ) ;
end ;
end ;
IMPRIME (' Matriz con las distancias entre ciudades ', a);
end ;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
procedure VIAJERO_AVIDO (var a : tmatriz);
var
grande, menor : real ;
distancia : real ;
p, q : integer ;
begin
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ busca la maxima distancia en la matriz }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
grande := 0 ;
for i := 1 to (n) do begin
for j := 1 to (n) do begin
if ( a [i,j] > grande ) then grande := a [i,j] ;
end ; {j}
end ; {i}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ busca desde cada ciudad posible de partida }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
for p := 1 to (n) do begin
c_p := chr (p + ord ('A') - 1);
writeln ;
writeln (' ciudad de partida ; c_p = ', c_p);
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ re-inicia marcas }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
for i := 1 to (n) do begin
visitada [i] := false ;
secuencia [i] := o ;
end ;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ empieza la busqueda en la ciudad (fila) de partida "p" }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
distancia := 0 ;
i := p ; { primera fila (ciudad) a revisar }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ busca en las columnas disponibles (ciudades no-visitadas) }
{ de la matriz "A", la columna "q" con la menor distancia }
{ en la fila "i" (que es la solucion localmente optima). }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
for k := 1 to (n - 1) do begin
menor := grande ;
q := 0 ;
for j := 1 to (n) do begin
if ( j <> i ) and ( not visitada [j] ) and
( a [i,j] < menor ) then begin
q := j ;
menor := a [i,j] ;
end ; {if}
end ; {j}
if ( q < 1 ) then ERROR (' (viajante): q < 1 ');
if ( q > n ) then ERROR (' (viajante): q > n ');
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ marca la ciudad (columna) "i" como visitada, recuerda el }
{ camino seguido, almacena distancia, y pasa a la siguiente }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
visitada [i] := true ;
secuencia [k] := chr (i + ord ('A') - 1);
distancia := distancia + a [i,q] ;
i := q ;
end ; {k}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ cierra el camino con la ciudad de partida "p" }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
visitada [i] := true ;
secuencia [n] := chr (i + ord ('A') - 1);
secuencia [n+1] := chr (p + ord ('A') - 1);
distancia := distancia + a [i,q] ;
distancia := distancia + a [i,p] ;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ impresion }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
writeln (' distancia total ; d = ', distancia: 4:4 );
for i := 1 to (n + 1) do begin
writeln (' secuencia ; s = ', secuencia [i]);
end ; {i}
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
{ fin lazo de partir en cada ciudad }
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
end ; {p}
writeln ;
end ;
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
begin
MATRIZ_DISTANCIA (a) ;
VIAJERO_AVIDO (a) ;
end .
{-----+-----+-----+-----+-----+-----+-----+-----+-----+-----}
Generated by GNU enscript 1.6.1.