Mpinning Gyalg12(Analg)

64
1 Análisis de Algoritmos Observaciones: Las constantes son detalles “irrelevantes” Algunos términos “crecen” más rápido que otros a medida que el tamaño de la entrada aumenta. Consideremos: n 2 + 100n + 1000 ¿Cómo cambia a medida que n crece? ¿Es éste un “buen” tiempo de ejecución? Compare: (n 2 )/3 con 3n ¿Hacen alguna diferencia las constantes?

Transcript of Mpinning Gyalg12(Analg)

1

Análisis de Algoritmos• Observaciones:

– Las constantes son detalles “irrelevantes” – Algunos términos “crecen” más rápido que otros a

medida que el tamaño de la entrada aumenta.

• Consideremos:– n2 + 100n + 1000– ¿Cómo cambia a medida que n crece? – ¿Es éste un “buen” tiempo de ejecución?

• Compare:– (n2)/3 con 3n– ¿Hacen alguna diferencia las constantes?

2

Análisis de Algoritmos

• Idea:– Comparación de algoritmos:

• límites superiores

• límites inferiores• límites exactos

– Estamos interesados en la razón de crecimiento de un algoritmo: cómo cambia su tiempo de ejecución proporcionalmente al tamaño de la entrada.

3

Análisis de Algoritmos: O Grande

• Una función f(n) es O(g(n)) si existen constantes c, n0>0 tales que f(n) c·g(n) para todo n n0

• ¿Qué quiere decir esto?– c·g(n) es un límite superior de f(n) para n grande

• Ejemplos:– f(n) = 3n2+2n+1 es O(n2)– f(n) = 2n es O(n2) (también es O(n) )– f(n) = 1000n3 es O(n10)

4

Análisis de Algoritmos: Omega

• Una función f(n) es (g(n)) si existen constantes c, n0>0 tales que

f(n) c·g(n) para todo n n0

• ¿Qué significa esto?– c·g(n) es un límite inferior de f(n) para n grande

• Ejemplo:– f(n) = n2 es (n)

5

Análisis de Algoritmos: Theta

• Una función f(n) es (g(n)) si es O(g(n)) y (g(n)) , en otras palabras:– Existen constantes c1, c2, n > 0 tales que

0 c1 g(n) f(n) c2g(n) para todo n n0

• ¿Qué significa esto? – f(n) y g(n) tienen la misma razón de crecimiento

indica límite exacto.

• Ejemplo:– f(n) = 2n+1 es (n)

6

Un ejemplo sencillo: Búsqueda Binaria

begin

i 1; j n; q false;

repeat k (i+j) div 2;

if A[k] = x then q true

else if A[k] < x then i k+1

else j k-1

until q or (i > j)

end

7

❚ En esta búsqueda, después de cada comparación o la búsqueda termina con éxito o el tamaño del arreglo en lo que queda por buscar es aproximadamente la mitad del tamaño original.

❚ Entonces, después de k comparaciones, el tamaño del arreglo en que queda por buscar es a lo más n/2k

8

Supongamos un arreglo de 9 elementos:

-15 -6 0 7 9 23 54 82 101

1 2 3 4 5 6 7 8 9

Por ejemplo, si buscamos el valor 101i j k q

1 9 5 false

6 9 7 false

8 9 8 false

9 9 9 true Éxito en 4 comparaciones

9

Ejemplo (continuación)

Si buscamos el valor 14

i j k q

1 9 5 false

1 4 2 false

1 1 1 false

2 1 Fracaso: no se encontró con 4 comparaciones

10

Ejemplo (continuación)

Para x = 82

i j k q

1 9 5 false

6 9 7 false

8 9 8 true

Éxito en 3 comparaciones

11

Ejemplo (continuación)

El número de comparaciones (de elementos) necesarias para encontrar cada uno de los 9 elementos es:

A [1] [2] [3] [4] [5] [6] [7] [8] [9]

elemento -15 -6 0 7 9 23 54 82 101comparaciones 3 2 3 4 1 3 2 3 4

12

Ejemplo (continuación)

❚ Ningún elemento requiere más de cuatro comparaciones para ser encontrado. El promedio para una búsqueda exitosa es 25/9 o sea aproximadamente 2.77.

13

Ejemplo (continuación)

❚ Hay diez maneras posibles para que, dependiendo del valor de x, una búsqueda no exitosa termine.

❙ Si x < A[1], A[1] < x < A[2], A[2] < x < A[3], A[5] < x < A[6], A[6] < x < A[7], o A[7] < x < A[8], el algoritmo necesita tres comparaciones para determinar que x no está presente. Para las posibilidades restantes necesita cuatro comparaciones.

14

Ejemplo (continuación)

❚ Luego, el número promedio de comparaciones para una búsqueda sin éxito es (3+3+3+4+4+3+3+3+4+4)/10 = 3.4

❚ Si n está en el rango [2k-1,2k], entonces el algoritmo realiza a lo más k comparaciones para una búsqueda exitosa, y k-1 o k comparaciones para una búsqueda no exitosa.

15

Finalmente

❚ En otras palabras, el tiempo para una búsqueda exitosa es O(log2n).

16

Repaso: Inducción

• Suponga – S(k) es verdad para una constante k fijada

• A menudo k = 0

– S(n) ➠ S(n+1) para todo n >= k

• Entonces S(n) es verdad para todo n >= k

17

Prueba por Inducción

• A probar: S(n) es verdad para todo n k• Base Inductiva:

– Mostrar que la fórmula se cumple para n = k

• Hipótesis Inductiva:– Suponga que la fórmula es verdadera para un n arbitrario

• Paso de Inducción:– Muestre que la fórmula es entonces verdadera para n+1

18

Ejemplo de Inducción: Forma cerrada de Gauss

• Probar 1 + 2 + 3 + … + n = n(n+1) / 2– Base Inductiva:

• Si n = 0, entonces 0 = 0(0+1) / 2

– Hipótesis Inductiva:• suponga 1 + 2 + 3 + … + n = n(n+1) / 2

– Paso de Inducción (mostrar que es verdad para n+1):1 + 2 + … + n + n+1 = (1 + 2 + …+ n) + (n+1)

= n(n+1)/2 + n+1 = [n(n+1) + 2(n+1)]/2

= (n+1)(n+2)/2 = (n+1)(n+1 + 1) / 2

19

Ejemplo de Inducción:Forma Geométrica Cerrada

• Probar a0 + a1 + … + an = (an+1 - 1)/(a - 1) para todo a 1– Base Inductiva: mostrar que a0 = (a0+1 - 1)/(a - 1)

a0 = 1 = (a1 - 1)/(a - 1)

– Hipótesis Inductiva: • Suponga a0 + a1 + … + an = (an+1 - 1)/(a - 1)

– Paso de Inducción (muestre que es verdad para n+1):a0 + a1 + … + an+1 = a0 + a1 + … + an + an+1

= (an+1 - 1)/(a - 1) + an+1 = (an+1+1 - 1)/(a - 1)

20

Inducción

• Lo que hemos visto se llama Inducción débil• También existe la Inducción Fuerte

– Base Inductiva: muestre que S(0)– Hipótesis Inductiva: suponga S(k) para k n arbitrario– Paso de Inducción: muestre que S(n+1)

• Otra variante:– Base Inductiva: mostrar S(0), S(1)

– Hipótesis Inductiva: suponga S(n) y S(n+1) verdaderas– Paso de Inducción: muestre que S(n+2)

21

Repaso: Comportamiento Asintótico

• Comportamiento asintótico: ¿Cómo se comporta el algoritmo a medida que el problema crece?

• Tiempo de ejecución• Necesidades de Memoria/almacenamiento

– Usamos un modelo RAM:• Todos los accesos a memorias “cuestan” lo mismo• No hay operaciones concurrentes• Todas las instrucciones “razonables” toman tiempo unitario

– Excepto, por supuesto, llamadas a función

• Palabras de tamaño constante– A menos que estemos manipulando bits de manera explícita

22

Repaso: Tiempo de Ejecución

• Número de pasos primitivos que se ejecutan– Excepto cuando se ejecutan llamadas a función,

la mayoría de las instrucciones requiere aproximadamente la misma cantidad de tiempo

– Podemos ser más estrictos si es necesario

• Caso peor vs. caso promedio

23

Un Ejemplo: Sort por Inserción

SortInserción (A, n) {for i = 2 to n {

item = A[i];j = i - 1;while (j > 0) and (A[j] > item) {

A[j+1] = A[j]j = j - 1

}A[j+1] = item

}}

24

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

30 10 40 20

1 2 3 4

i = j = key = A[j] = A[j+1] =

25

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

30 10 40 20

1 2 3 4

i = 2 j = 1 key = 10A[j] = 30 A[j+1] = 10

26

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

30 30 40 20

1 2 3 4

i = 2 j = 1 key = 10A[j] = 30 A[j+1] = 30

27

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

30 30 40 20

1 2 3 4

i = 2 j = 1 key = 10A[j] = 30 A[j+1] = 30

28

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

30 30 40 20

1 2 3 4

i = 2 j = 0 key = 10A[j] = A[j+1] = 30

29

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

30 30 40 20

1 2 3 4

i = 2 j = 0 key = 10A[j] = A[j+1] = 30

30

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 2 j = 0 key = 10A[j] = A[j+1] = 10

31

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 3 j = 0 key = 10A[j] = A[j+1] = 10

32

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 3 j = 0 key = 40A[j] = A[j+1] = 10

33

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 3 j = 0 key = 40A[j] = A[j+1] = 10

34

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 3 j = 2 key = 40A[j] = 30 A[j+1] = 40

35

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 3 j = 2 key = 40A[j] = 30 A[j+1] = 40

36

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 3 j = 2 key = 40A[j] = 30 A[j+1] = 40

37

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 4 j = 2 key = 40A[j] = 30 A[j+1] = 40

38

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 4 j = 2 key = 20A[j] = 30 A[j+1] = 40

39

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 4 j = 2 key = 20A[j] = 30 A[j+1] = 40

40

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 4 j = 3 key = 20A[j] = 40 A[j+1] = 20

41

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 20

1 2 3 4

i = 4 j = 3 key = 20A[j] = 40 A[j+1] = 20

42

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 40

1 2 3 4

i = 4 j = 3 key = 20A[j] = 40 A[j+1] = 40

43

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 40

1 2 3 4

i = 4 j = 3 key = 20A[j] = 40 A[j+1] = 40

44

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 40

1 2 3 4

i = 4 j = 3 key = 20A[j] = 40 A[j+1] = 40

45

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 40

1 2 3 4

i = 4 j = 2 key = 20A[j] = 30 A[j+1] = 40

46

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 40 40

1 2 3 4

i = 4 j = 2 key = 20A[j] = 30 A[j+1] = 40

47

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 30 40

1 2 3 4

i = 4 j = 2 key = 20A[j] = 30 A[j+1] = 30

48

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 30 40

1 2 3 4

i = 4 j = 2 key = 20A[j] = 30 A[j+1] = 30

49

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 30 40

1 2 3 4

i = 4 j = 1 key = 20A[j] = 10 A[j+1] = 30

50

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 30 30 40

1 2 3 4

i = 4 j = 1 key = 20A[j] = 10 A[j+1] = 30

51

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 20 30 40

1 2 3 4

i = 4 j = 1 key = 20A[j] = 10 A[j+1] = 20

52

Un Ejemplo: Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

10 20 30 40

1 2 3 4

i = 4 j = 1 key = 20A[j] = 10 A[j+1] = 20

¡Listo!

53

Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}}

¿Cuál es la precondiciónpara este loop?

54

Sort por Inserción

SortInserción(A, n) {for i = 2 to n {

key = A[i]j = i - 1;while (j > 0) and (A[j] > key) {

A[j+1] = A[j]j = j - 1

}A[j+1] = key

}} ¿Cuántas veces se ejecuta

este loop?

55

Sort por InserciónInstrucción Esfuerzo

SortInserción(A, n) {

for i = 2 to n { c1n

key = A[i] c2(n-1)

j = i - 1; c3(n-1)

while (j > 0) and (A[j] > key) { c4T

A[j+1] = A[j] c5(T-(n-1))

j = j - 1 c6(T-(n-1))

} 0

A[j+1] = key c7(n-1)

} 0}

T = t2 + t3 + … + tn donde ti es el número de evaluaciones de la expresión while para la i-ésima iteración del loop

56

Análisis del Sort por Inserción

• T(n) = c1n + c2(n-1) + c3(n-1) + c4T + c5(T - (n-1)) + c6(T - (n-1)) + c7(n-1)

= c8T + c9n + c10

• ¿Qué puede ser T?– Caso mejor -- loop interno nunca se ejecuta

• ti = 1 T(n) es una función lineal

– Caso peor -- loop interno se ejecuta para todos los elementos previos

• ti = i T(n) es una función cuadrática

– Caso promedio• ???

57

Análisis

• Simplificaciones– Ignorar costos de las instrucciones– Lo interesante es el Orden de crecimiento :

• Lo que interesa son los términos de orden superior– Recordar, estamos haciendo análisis asintótico

– A medida que el tamaño de la entrada crece los términos de orden superior son dominantes

58

Notación para el límite superior• Decimos que el tiempo de ejecución del Sort

por Inserción es O(n2)– Se podría decir que está en O(n2)– O se lee “O-grande” (también se habla de “orden”)

• En general una función– f(n) es O(g(n)) si existen constantes positivas c y n0

tales que f(n) c | g(n) | para todo n n0

• Formalmente– O(g(n)) = { f(n): constantes positivas c y n0 tales

que f(n) c | g(n) | n n0

59

El Sort por Inserción Es O(n2)

• Prueba– Suponga que el tiempo de ejecución es an2 + bn + c

• Si a, b, y c son menores que 0 reemplace la constante por su valor absoluto

– an2 + bn + c (a + b + c)n2 + (a + b + c)n + (a + b + c) 3(a + b + c)n2 for n 1

– Sea c’ = 3(a + b + c) y sea n0 = 1

• Pregunta– ¿Es O(n3) el SortInserción?– ¿Es O(n) el SortInserción?

60

O Grande

• Un polinomio de grado k es O(nk)• Prueba:

– Suponga f(n) = bknk + bk-1nk-1 + … + b1n + b0

• Sea ai = | bi |

– f(n) aknk + ak-1nk-1 + … + a1n + a0

ik k k

i ik

nn a n a cn

n

nkai nkai cnk ni

nk

61

0

250

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

f(n) = n

f(n) = log(n)

f(n) = n log(n)

f(n) = n^2

f(n) = n^3

f(n) = 2^n

Complejidad Práctica

62

0

500

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

f(n) = n

f(n) = log(n)

f(n) = n log(n)

f(n) = n^2

f(n) = n^3

f(n) = 2^n

Complejidad Práctica

63

0

1000

1 3 5 7 9 11 13 15 17 19

f(n) = n

f(n) = log(n)

f(n) = n log(n)

f(n) = n^2

f(n) = n^3

f(n) = 2^n

Complejidad Práctica

64

0

1000

2000

3000

4000

5000

1 3 5 7 9 11 13 15 17 19

f(n) = n

f(n) = log(n)

f(n) = n log(n)

f(n) = n^2

f(n) = n^3

f(n) = 2^n

Complejidad Práctica