Sei sulla pagina 1di 46

PRÁCTICA 3

Pablo Baeyens Antonio Checa Iñaki Madinabeitia José Manuel


Muñoz Darío Sierra
Algorítmica
ÍNDICE

Contenedores en un barco
Maximizar el número de contenedores cargados
Maximizar el número de toneladas cargadas

El problema del viajante de comercio


Algoritmos
Ejemplos

1 / 44
CONTENEDORES EN UN BARCO
PROBLEMA

Rellenar un buque con carga limitada (K) con un conjunto de


contenedores c1 , . . . , cn con pesos p1 , . . . , pn .

Entrada: Vector de pesos de los contenedores, p y capacidad


total K
Salida: Vector con los contenedores elegidos

3 / 44
ESTRUCTURA DE DATOS

struct Cont {
int id ;
peso_t peso ;

Cont ( int i , peso_t p ) {


id = i ;
peso = p ;
}
};

4 / 44
SOLUCIÓN MAXIMIZAR EL NÚMERO DE CONTENEDORES CARGADOS

• Basta coger los contenedores de menor peso hasta rellenar el buque


• Emparejamos cada elemento con su posición y ordenamos en
función de los pesos.
• Una vez ordenados, rellenamos hasta agotar la capacidad.
• Eficiencia: O(n log(n))

5 / 44
CÓDIGO MAXIMIZAR EL NÚMERO DE CONTENEDORES CARGADOS

vector < int > max_num_conts ( const vector < peso_t > p ,
peso_t K ) {
vector < Cont > conts = a_cont ( p ) ;

sort ( conts . begin () , conts . end () , menor ) ;

vector < int > elegidos ;

for ( int i = 0; i < conts . size () && conts [ i ]. peso <=


K ; i ++) {
elegidos . push_back ( conts [ i ]. id ) ;
K -= conts [ i ]. peso ;
}

return elegidos ;
}
6 / 44
OPTIMALIDAD MAXIMIZAR EL NÚMERO DE CONTENEDORES CARGADOS

Este criterio siempre halla la solución con un mayor número de


contenedores.
Vamos a razonar por reducción al absurdo.

7 / 44
OPTIMALIDAD MAXIMIZAR EL NÚMERO DE CONTENEDORES CARGADOS

Este criterio siempre halla la solución con un mayor número de


contenedores.
Vamos a razonar por reducción al absurdo.

Partimos de nuestra solución o1 , . . . , ok del algoritmo anterior. Estos


contenedores son los menores entre todos los posibles.
Suponemos otra solución, s1 , . . . , sm , una solución del problema, con
mayor número de contenedores. Es decir, m > k.

7 / 44
ESTRATEGIA MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

• Cogemos el contenedor de mayor peso que quepa en el buque.


• El algoritmo es muy similar al del apartado anterior.

8 / 44
CÓDIGO MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

vector < int > max_peso_greedy ( const vector < peso_t > p ,
peso_t capacidad ) {
vector < Cont > conts = a_cont ( p ) ;
sort ( conts . begin () , conts . end () , mayor ) ;
vector < int > elegidos ;

for ( int i = 0; i < conts . size () && capacidad > 0; i


++) {
if ( conts [ i ]. peso <= capacidad ) {
elegidos . push_back ( conts [ i ]. id ) ;
capacidad -= conts [ i ]. peso ;
}
}
return elegidos ;
}

9 / 44
PERSPECTIVA MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

Hemos querido comparar el algoritmo Greedy anterior (que coge en


cada momento el contenedor que más aumenta el peso total) con uno
que encuentra la mejor solución siempre.

De esta forma, podremos ver las ventajas que presenta enfocar las
soluciones de una forma simple.

10 / 44
OTRO ALGORITMO MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

A continuación colocamos el algoritmo que encuentra siempre el


óptimo:

• Está basado en la fuerza bruta


• Recorre todas las posibilidades y se queda con la mejor.
• Eficiencia: O(n!)

11 / 44
CÓDIGO MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

vector < Cont > bruto_sub ( const vector < Cont > p , peso_t K )
{
if ( p . empty () || K == 0)
return vector < Cont >() ;

peso_t max = 0;
vector < Cont > max_v ;
for ( vector < Cont >:: const_iterator it = p . cbegin () ; it
!= p . cend () && max < K ; ++ it ) {
vector < Cont >:: const_iterator next ( it ) ;
vector < Cont > orig_copy (++ next , p . cend () ) ; //
Copia todos los posteriores
vector < Cont > v_candidato ;
if ( it→peso > K )
v_candidato = bruto_sub ( orig_copy , K ) ;
else {
v_candidato = bruto_sub ( orig_copy , K - it→peso ) ;
v_candidato . push_back (* it ) ; // Si usamos
listas , mejor usar push_front
}
peso_t suma1 = suma ( v_candidato ) ;
if ( suma1 > max && suma1 <= K ) {
max = suma1 ;
max_v = v_candidato ;
}
}
return max_v ;
12 / 44
COMPARATIVA MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

Es fácil ver que el algoritmo greedy es más eficiente que el óptimo,


pero el óptimo tiene asegurada la mejor respuesta.
Para poder contrastar mejor, hemos hecho las gráficas de
comparación.

13 / 44
COMPARATIVA MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

Tiempos de ejecución de contenedores


0.6
Recursivo
Greedy
0.5
Tiempo de ejecución

0.4

0.3

0.2

0.1

0
0 5 10 15 20 25 30 35 40 45 50
Capacidad

14 / 44
COMPARATIVA MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

Distancia al óptimo de contenedores


2000
Recursivo
1800 Greedy
1600
1400
1200
Peso total

1000
800
600
400
200
0
0 5 10 15 20 25 30 35 40 45 50
Capacidad

15 / 44
CONCLUSIÓN MAXIMIZAR EL NÚMERO DE TONELADAS CARGADAS

Este es un ejemplo en el que es posible que nos interese trabajar con


algoritmos greedy si quisiéramos conseguir una solución rápida a un
problema grande.

16 / 44
EL PROBLEMA DEL VIAJANTE DE
COMERCIO
PROBLEMA

Hallar el recorrido con distancia mínima en un conjunto de ciudades


que pase por todas las ciudades y regrese al punto inicial.
62 59

80
02
60
08
76
95

57
51
50 14 93 55
27
67
54
77
78 92 75
61
22 10 88
29 35 53 52
94 68
28
72
56

91 89 70 90
41
44
49

45 21 25
37
85 58
39
18
36 71
79
86 01 74
03
69
87 23
16 42
17 73
63
38
19
24
33 43
15 07 05
26
46
47
12 48 04
40 82
84 06
30
32 81
31 34 13
64 83
65 11
09

66

18 / 44
ALGORITMOS

Entrada: Ficheros con ciudades indicadas como puntos en el


plano según sus coordenadas.
Salida: vector<int> con el orden en el que se recorren las
ciudades.

19 / 44
GRAFOS

Un grafo consta de:

• Una cantidad de nodos, almacenada en el atributo nodos.


• Una matriz de pesos, almacenada en el vector lados.

template < class T >


class Grafo {
unsigned int nodos ;
T * lados ;

20 / 44
CONSTRUCCIÓN DEL GRAFO

Construimos el grafo a partir de la distancia euclídea redondeada al


entero más próximo.
void p e s o s D e s d e Coor denad as ( double c [][2]) {
for ( int i = 0; i < nodos -1; i ++)
for ( int j = i +1; j < nodos ; j ++)
setPeso (i , j , dist ( c [ i ] , c [ j ]) ) ;
}

21 / 44
VECINO MÁS CERCANO ALGORITMOS

Tomamos la ciudad inicial y almacenamos en las ciudades no


visitadas:
vector < int > trayecto (1 , 0) ;
list < int > disponibles ;
for ( int i = g . numNodos () -1; i > 0; i - -)
disponibles . push_front ( i ) ;

Devolveremos trayecto.

22 / 44
VECINO MÁS CERCANO ALGORITMOS

Recorremos la lista buscando aquella ciudad con distancia mínima:


while (! disponibles . empty () ) {
list < int >:: iterator it = disponibles . begin () ,
cercano = it , fin = disponibles . end () ;
int actual = trayecto . back () ;
peso_t d_actual = g . peso ( actual , * cercano ) ;
for (++ it ; it != fin ; ++ it ) {
peso_t d_candidato = g . peso ( actual , * it ) ;
if ( d_candidato < d_actual ) {
cercano = it ;
d_actual = d_candidato ;
}
}

trayecto . push_back (* cercano ) ;


disponibles . erase ( cercano ) ;
} 23 / 44
INSERCIÓN ( ALGORITMO ) ALGORITMOS

• Toma como camino inicial los nodos más al norte, este y oeste
• Mientras haya nodos disponibles:
I Para cada nodo disponible, halla la posición entre dos nodos del camino
donde, de insertarse, se incrementaría menos la longitud del camino
I Inserta el nodo que aumente menos la longitud en la posición que se
calculó para ese nodo

24 / 44
INSERCIÓN ( CÓDIGO ) ALGORITMOS

while (! disponibles . empty () ) {


list < int >:: iterator minimo = disponibles . begin () ;
pair < int , list < int >:: iterator > PesoIndiceMin =
Pes oNuevo Circuito (* minimo , trayecto_l , g ) ;

for ( list < int >:: iterator it = ++ disponibles . begin ()


; it != disponibles . end () ; it ++) {
pair < int , list < int >:: iterator > PesoIndicetmp =
Pes oNuevoCircuito (* it , trayecto_l , g ) ;
if ( PesoIndiceMin . first > PesoIndicetmp . first ) {
minimo = it ;
PesoIndiceMin = PesoIndicetmp ;
}
}

trayecto_l . insert ( PesoIndiceMin . second ,* minimo ) ;


disponibles . erase ( minimo ) ;
} 25 / 44
COLONIA DE HORMIGAS ALGORITMOS

Este algoritmo se inspira en la comunicación por feromonas de una


colonia de hormigas para encontrar el camino mínimo hacia una
fuente de comida.

26 / 44
COLONIA ALGORITMOS

Una Colonia consta de:

• Grafo de distancias entre las ciudades.


• Grafo con las feromonas de cada camino, inicialmente arbitrarias.
• Constantes α, β, ρ, ξ, C, P, I.

27 / 44
CONSTANTES ALGORITMOS

α Peso que tienen las feromonas.


β Peso que tienen la distancias.
ρ Coeficiente de evaporación de las feromonas.
ξ Coeficiente de debilitamiento de las feromonas.
C Cuántas feromonas se añaden a un camino.
P Probabilidad de tomar el camino más atractivo.
I Cantidad de feromona inicial entre cada par de nodos.

28 / 44
COMPARATIVA DE LOS ALGORITMOS EJEMPLOS

A continuación ponemos tres ejemplos de ejecución de los algoritmos,


para poder verlos y compararlos de una forma más eficaz.
El tiempo de ejecución del algoritmo de colonia de hormigas es
arbitrario y puede ajustarse a voluntad. A mayor tiempo de
ejecución, mejor resultado ofrece. En general necesita más tiempo que
los otros dos algoritmos para dar un resultado igual o mejor.

29 / 44
COMPARATIVA DE LONGITUDES EJEMPLOS

Comparación en ulysses16 (Longitudes)


120
Vecino más cercano
Estrateg. inserción
100 Colonia de hormigas
Camino óptimo

80
Longitud

60

40

20

0
Algoritmos

30 / 44
SOLUCIÓN ÓPTIMA EJEMPLOS

Problema ulysses16
30
Camino óptimo
25

20

15

10
Y

-5

-10
33 34 35 36 37 38 39 40 41 42
X

31 / 44
SOLUCIÓN DE VECINO MÁS CERCANO EJEMPLOS

Problema ulysses16
30
Vecino más cercano
25

20

15

10
Y

-5

-10
33 34 35 36 37 38 39 40 41 42
X

32 / 44
SOLUCIÓN DE INSERCIÓN EJEMPLOS

Problema ulysses16
30
Estrategias de inserción
25

20

15

10
Y

-5

-10
33 34 35 36 37 38 39 40 41 42
X

33 / 44
SOLUCIÓN DE LA COLONIA DE HORMIGAS EJEMPLOS

Problema ulysses16
30
Colonia de hormigas
25

20

15

10
Y

-5

-10
33 34 35 36 37 38 39 40 41 42
X

34 / 44
COMPARATIVA DE LONGITUDES EJEMPLOS

Comparación en berlin52 (Longitudes)


9000
Vecino más cercano
8000 Estrateg. inserción
Colonia de hormigas
7000 Camino óptimo

6000
Longitud

5000

4000

3000

2000

1000

0
Algoritmos

35 / 44
SOLUCIÓN ÓPTIMA EJEMPLOS

Problema berlin52
1200
Camino óptimo

1000

800

600
Y

400

200

0
0 200 400 600 800 1000 1200 1400 1600 1800
X

36 / 44
SOLUCIÓN DE VECINO MÁS CERCANO EJEMPLOS

Problema berlin52
1200
Vecino más cercano

1000

800

600
Y

400

200

0
0 200 400 600 800 1000 1200 1400 1600 1800
X

37 / 44
SOLUCIÓN DE INSERCIÓN EJEMPLOS

Problema berlin52
1200
Estrategias de inserción

1000

800

600
Y

400

200

0
0 200 400 600 800 1000 1200 1400 1600 1800
X

38 / 44
SOLUCIÓN DE LA COLONIA DE HORMIGAS EJEMPLOS

Problema berlin52
1200
Colonia de hormigas

1000

800

600
Y

400

200

0
0 200 400 600 800 1000 1200 1400 1600 1800
X

39 / 44
COMPARATIVA DE LONGITUDES EJEMPLOS

Comparación en pr76 (Longitudes)


160000
Vecino más cercano
140000 Estrateg. inserción
Colonia de hormigas
Camino óptimo
120000

100000
Longitud

80000

60000

40000

20000

0
Algoritmos

40 / 44
SOLUCIÓN ÓPTIMA EJEMPLOS

Problema pr76
14000
Camino óptimo
12000

10000

8000
Y

6000

4000

2000

0
0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000
X

41 / 44
SOLUCIÓN DE VECINO MÁS CERCANO EJEMPLOS

Problema pr76
14000
Vecino más cercano
12000

10000

8000
Y

6000

4000

2000

0
0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000
X

42 / 44
SOLUCIÓN DE INSERCIÓN EJEMPLOS

Problema pr76
14000
Estrategias de inserción
12000

10000

8000
Y

6000

4000

2000

0
0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000
X

43 / 44
SOLUCIÓN DE LA COLONIA DE HORMIGAS EJEMPLOS

Problema pr76
14000
Colonia de hormigas
12000

10000

8000
Y

6000

4000

2000

0
0 2000 4000 6000 8000 10000 12000 14000 16000 18000 20000
X

44 / 44

Potrebbero piacerti anche