Subido por Roy Chavarria

Resumen de analisis

Anuncio
Capítulo 1 - Introducción al análisis de algoritmos
Problema Computacional Establece una relación entre la especificación general de una entrada que describe
todas las posibles instancias del problema y la especificación de la salida esperada.
Es importante notar que el problema sigue la noción de caja negra
Los problemas computacionales son producto de la abstracción En otras palabras, podemos percibir y pensar
en muchos detalles acerca de una situación particular de la realidad; cuando abstraemos esta situación
ignoramos algunos detalles y prestamos atención a otros, en función del objetivo que queremos lograr.
Ejemplo: Juego veintiuno que quitamos características innecesarias.
Algoritmo Especificación de la solución a un problema computacional. El algoritmo especifica cómo se
transforman las entradas en salidas.
Desde una perspectiva teórica, el algoritmo debe ser correcto o eficaz
Desde una perspectiva práctica debe ser eficiente (No consumir muchos recursos)
Eficiencia
Los algoritmos consumen recursos de las máquinas que los ejecutan, principalmente ciclos de procesador y
memoria, pero también almacenamiento persistente, interfaces de red, memorias caché y GPUs, entre otros.
Los algoritmos eficientes minimizan sus requerimientos de recursos.
Los principales aspectos de eficiencia a considerar en un algoritmo son tiempo y espacio.
Existe un patrón el cual es que cuando un algoritmo consume más memoria, entonces este consume menos
ciclos de reloj y viceversa.
Capítulo 1 - Modelo Ram
Para acercarnos a las preguntas sobre tiempo de ejecución y consumo de memoria, es necesaria una
perspectiva teórica y por tanto hablamos de análisis de complejidad temporal y de complejidad espacial.
La máquina de acceso aleatorio, RAM por sus siglas en inglés, es una máquina teórica basada en una
arquitectura de registros, de procesamiento lineal y funcionalmente equivalente a una máquina de Turing.
Complejidad temporal(T(n))
Con respecto a la utilización de tiempo el modelo RAM hace una diferenciación entre operaciones simples
y complejas. Cada operación simple –por ejemplo, las operaciones aritméticas, las operaciones lógicas o el
condicional if– toma exactamente una unidad de tiempo en ejecutarse, a esta unidad le llamaremos paso. Las
operaciones complejas corresponden a ciclos y procedimientos y podemos entenderlas como composiciones
de operaciones simples y complejas.
Cada acceso a memoria, ya sea de lectura o de escritura, toma exactamente un paso en ejecutarse.
Complejidad espacial S(n): En este modelo cada parámetro y variable local de tipo primitivo consume una
unidad de memoria. Un arreglo de tamaño n consume n unidades de memoria.
Sin embargo, es importante notar que con las llamadas recursivas de pila es necesario contabilizar la memoria
utilizada por cada llamada. Recordemos que la recursividad de pila deja cálculos pendientes y, por lo tanto, la
memoria no puede ser liberada hasta que estos sean resueltos.
Finalmente, es importante tomar en cuenta si los parámetros que recibe la función a analizar están siendo
pasados por valor o por referencia. Cuando los parámetros se pasan por referencia, se está compartiendo 7
memoria entre la función que invoca y la función invocada, y por tanto su consumo sólo debe ser
contabilizado
una vez.
Interpretación de las funciones T(n) y S(n): Puesto que estamos prestando especial atención al crecimiento
de las funciones y no tanto a sus detalles
específicos, podemos simplificar las expresiones que definen a las funciones T(n) y S(n) para tomar en cuenta
únicamente su término de mayor crecimiento.
Por ejemplo, para un T(n) = 3n + 10 tenemos los términos 3n y 10, tomamos el de mayor crecimiento 3n, y
descartamos la constante 3 quedando entonces con n. Por tanto, decimos que T(n) = O(n).
Capítulo 2 – Análisis asintótico
A través del análisis asintótico vamos a poder determinar cotas o límites superiores e inferiores para nuestras
funciones T (n) y S(p). Si la función g(n) es una cota superior de T (n), entonces el tiempo de ejecución T (n)
nunca va a ser mayor que c · g(n), donde c es una constante específica. Por otro lado, si g(n) es una cota
inferior de T (n), entonces el tiempo de ejecución de T (n) nunca va a ser menor que c · g(n), donde c es una
constante específica.
Cota Superior Decimos que c · g(n) es una cota superior de f (n) si y sólo si existen n 0 y c tal que
n 0 ≥ 0 ∧ c > 0 ∧ c · g(n) ≥ f (n) , ∀ n ≥ n 0 .
La cota superior se denota f (n) = O(g(n))
Descargar