Asociación Profesional de Cuerpos Superiores de Sistemas y Tecnologías de La Información de Las Administraciones Públicas
Asociación Profesional de Cuerpos Superiores de Sistemas y Tecnologías de La Información de Las Administraciones Públicas
1
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
ÍNDICE
2
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
5. GLOSARIO ...................................................................................... 2
6. TEST................................................................................................ 5
6.1. PREGUNTAS DE TEST ........................................................................................5
6.2. SOLUCIONES A LAS PREGUNTAS DE TEST ...................................................7
3
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Esta parte hará comenzar a pensar en diseñar y analizar algoritmos. Tiene la intención de ser
una introducción sobre cómo especificar algoritmos y algunas de las estrategias de diseño
que usaremos y muchas de las ideas fundamentales que se usan en el análisis de algoritmos.
Este capítulo proporciona una descripción general de los algoritmos y su lugar en los sistemas
informáticos modernos. Este capítulo define qué es un algoritmo y enumera algunos ejemplos.
También argumenta que deberíamos considerar los algoritmos como una tecnología, junto
con tecnologías como el hardware, interfaces gráficas de usuario, sistemas orientados a
objetos y redes.
1.2. Algoritmos
4
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
5
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
orden, cada parte aparece antes que las partes que la usan (a menos que tengamos solo
unas pocas partes).
Otro ejemplo: Se nos dan n puntos en el plano y deseamos encontrar el casco convexo de
estos puntos. El casco convexo es el polígono convexo más pequeño que rodea todos los
puntos. Intuitivamente, podemos pensar que cada punto está representado por un clavo que
sobresale de una tabla. El casco convexo estaría representado por una banda de goma
ajustada, que rodea todos los clavos. Cada clavo alrededor del cual gira la goma elástica es
un vértice del casco convexo.
2. Tienen aplicaciones prácticas. De los problemas de la lista anterior, encontrar el camino más
corto proporciona los ejemplos más fáciles. Una empresa de transporte, como una empresa
de camiones o ferrocarriles, tiene un interés financiero en encontrar los caminos más cortos a
través de una red de carreteras o ferrocarriles porque tomar caminos más cortos resulta en
menores costos de trabajo y combustible. O un nodo de enrutamiento en Internet puede
necesitar encontrar la ruta más corta a través de la red para enrutar un mensaje rápidamente.
3. No todos los problemas resueltos por algoritmos tienen un conjunto de soluciones candidatas
fácilmente identificables. Por ejemplo, suponga que se nos da un conjunto de valores
numéricos que representan muestras de una señal y queremos calcular la transformada
discreta de Fourier de estas muestras. La transformada discreta de Fourier convierte el
dominio del tiempo en el dominio de la frecuencia, produciendo un conjunto de coeficientes
numéricos, por lo que podemos determinar la presencia de varias frecuencias en la señal
muestreada. Además de estar en el corazón del procesamiento de señales, las transformadas
discretas de Fourier tienen aplicaciones en la compresión de datos y la multiplicación de
grandes polinomios y de números enteros.
1.3.1. Técnica
6
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
. El centro de nuestro estudio trata sobre algoritmos eficientes. Nuestra medida habitual de
eficiencia es la velocidad, es decir, cuánto tarda un algoritmo en producir su resultado. Sin
embargo, existen algunos problemas para los que no se conoce una solución eficaz.
• En tercer lugar, varios problemas NP-completos son similares, pero no idénticos, a los
problemas para los que conocemos algoritmos eficientes. Los científicos están intrigados por
cómo un pequeño cambio en el planteamiento del problema puede provocar un gran cambio
en la eficiencia del algoritmo más conocido.
Se debe conocer los problemas NP-completos porque algunos de ellos surgen
sorprendentemente a menudo en aplicaciones reales. Si se le pide que produzca un algoritmo
eficiente para un problema NP-completo, es probable que dedique mucho tiempo a una
búsqueda infructuosa. Si puede demostrar que el problema es NP-completo, puede dedicar
su tiempo a desarrollar un algoritmo eficiente que proporcione una buena solución, pero no la
mejor posible.
Como ejemplo concreto, considere una empresa de entrega con un depósito central. Cada
día, carga cada camión de reparto en el depósito y lo envía para entregar mercancías a varias
direcciones. Al final del día, cada camión debe retroceder al depósito para que esté listo para
ser cargado para el día siguiente. Para reducir los costos, la empresa desea seleccionar un
orden de entrega que produzca la distancia total más baja recorrida por cada camión. Este
problema es el conocido "problema del visitador comercial" y es NP-completo. No tiene un
algoritmo eficiente conocido. Sin embargo, bajo ciertos supuestos, conocemos algoritmos
eficientes que dan una distancia total que no está muy por encima de la más corta posible.
Son los llamados "algoritmos de aproximación".
1.3.3. Paralelismo
Durante muchos años, pudimos contar con un aumento constante de la velocidad del reloj del
procesador. Sin embargo, las limitaciones físicas presentan un obstáculo fundamental para
las velocidades de reloj cada vez mayores: debido a que la densidad de potencia aumenta
super linealmente con la velocidad del reloj, los chips corren el riesgo de derretirse una vez
que sus velocidades de reloj se vuelven lo suficientemente altas.
Por tanto, para realizar más cálculos por segundo, los chips se diseñan para contener no solo
uno, sino varios "núcleos" de procesamiento. Podemos comparar estos ordenadores
multinúcleo con varios procesadores secuenciales en un solo chip; en otras palabras, son un
tipo de "computación paralela". Para obtener el mejor rendimiento de los ordenadores
7
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Supongamos que los ordenadores fueran infinitamente rápidos y la memoria estuviera libre.
¿habría alguna razón para estudiar algoritmos? La respuesta es sí, aunque sólo sea por eso,
sería bueno demostrar que su método de solución termina y lo hace con la respuesta correcta.
Si los ordenadores fueran infinitamente rápidos, cualquier método correcto para resolver un
problema sería suficiente. Probablemente se desee que la implementación esté dentro de los
límites de las buenas prácticas de ingeniería de software (por ejemplo, la implementación
debe estar bien diseñada y documentada), pero normalmente se usaría el método más fácil
de implementar. Por supuesto, los ordenadores pueden ser rápidos, pero no infinitamente
rápidos. Y la memoria puede ser barata, pero no gratuita. Por tanto, el tiempo es un recurso
limitado, al igual que el espacio en la memoria. Se deben utilizar estos recursos con prudencia,
y los algoritmos que sean eficientes en términos de tiempo o espacio ayudarán a hacerlo.
1.4.1. Eficiencia
Los diferentes algoritmos ideados para resolver el mismo problema a menudo difieren
dramáticamente en su eficiencia. Estas diferencias pueden ser mucho más significativas que
las debidas al hardware y al software. Como ejemplo, veremos dos algoritmos para ordenar.
El primero, conocido como “ordenación por inserción”, toma un tiempo aproximadamente igual
a c1n2 para ordenar n elementos, donde c1 es una constante que no depende de n. Es decir,
lleva un tiempo aproximadamente proporcional a n2. El segundo, el tipo de combinación, toma
un tiempo aproximadamente igual a c2nlog n, donde(log n) significa log2 (n) y c2 es otra
constante que tampoco depende de n. La “ordenación por inserción” normalmente tiene un
factor constante más pequeño que la ordenación por fusión o combinación (mergesort), de
modo que c1 < c2. Veremos que los factores constantes pueden tener un impacto mucho
menor en el tiempo de ejecución que la dependencia del tamaño de entrada n.
Vamos a representar, como veremos posteriormente, el tiempo de ejecución de la ordenación
por inserción como c1n2 y el tiempo de ejecución de la ordenación mergesort como c2*n*logn.
Luego vemos que donde la ordenación por inserción tiene un factor de n en su tiempo de
ejecución, la ordenación por combinación tiene un factor de logn, que es mucho más pequeño.
(Por ejemplo, cuando n = 1000, logn es aproximadamente 10, y cuando n es igual a un millón,
logn es aproximadamente solo 20.)
Aunque la ordenación por inserción generalmente se ejecuta más rápido que la ordenación
por mergesort, para tamaños de entrada pequeños, una vez que el tamaño de entrada n se
vuelve lo suficientemente grande, la ventaja del tipo de mergesort de log n frente a n
compensará con creces la diferencia en los factores constantes. No importa cuánto más
pequeño sea c1 que c2, siempre habrá un punto de cruce más allá del cual la ordenación por
mergesort es más rápida.
Para un ejemplo concreto, comparamos un ordenador muy rápido (ordenador A) que ejecuta
la ordenación por inserción contra un ordenador más lento (ordenador B) que ejecuta la
ordenación por mergesort. Cada uno de ellos debe ordenar una matriz de 10 millones de
8
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
números. (Aunque 10 millones de números puede parecer mucho, si los números son enteros
de ocho bytes, ocupan en la entrada alrededor de 80 megabytes).
Suponga que el ordenador A ejecuta 10 mil millones de instrucciones por segundo y el
ordenador B ejecuta solo 10 millones de instrucciones por segundo, por lo que el ordenador
A es 1000 veces más rápido que el ordenador B en potencia de cómputo bruta. Para hacer la
diferencia aún más dramática, suponga que el programador más cualificado del mundo ordena
la inserción de códigos en lenguaje de máquina para el ordenador A, y que el código resultante
requiere 2n2 instrucciones para ordenar n números.
Suponga además que solo un programador promedio implementa mergesort, usando un
lenguaje de alto nivel con un compilador ineficiente, con el código resultante tomando 50nlogn
instrucciones. Para ordenar 10 millones de números, el ordenador A toma más de 5,5 horas,
mientras que el ordenador B toma: 1163 segundos (menos de 20 minutos):
Al usar un algoritmo cuyo tiempo de ejecución crece más lentamente, incluso con un
compilador deficiente, el ordenador B es más de 17 veces más rápido que el ordenador A. La
ventaja de la ordenación por mergesort es aún más pronunciada cuando ordenamos 100
millones de números: donde la ordenación por inserción demora más de 23 días, la ordenación
por mergesort toma menos de cuatro horas. En general, a medida que aumenta el tamaño del
problema, también lo hace la ventaja relativa de la ordenación por mergesort.
El ejemplo anterior muestra que deberíamos considerar los algoritmos, como el hardware, es
decir, como una tecnología. El rendimiento total del sistema depende tanto de elegir
algoritmos eficientes como de elegir hardware rápido. Así como se están logrando rápidos
avances en otras tecnologías informáticas, también se están realizando en algoritmos. Quizás
se cuestione si los algoritmos son realmente tan importantes en los ordenadores
contemporáneos a la luz de otras tecnologías avanzadas, tales como: arquitecturas
informáticas avanzadas, tecnologías de fabricación, interfaces gráficas de usuario (GUI
intuitivas y fáciles de usar), sistemas orientados a objetos, tecnologías web integradas y redes
rápidas, tanto cableadas como inalámbricas. La respuesta es: sí.
Aunque algunas aplicaciones no requieren explícitamente contenido algorítmico a nivel de la
aplicación (como las aplicaciones simples basadas en la Web), muchas sí lo hacen. Por
ejemplo, considere un servicio basado en la Web que determina cómo viajar de un lugar a
otro. Su implementación se basaría en hardware rápido, una interfaz gráfica de usuario, redes
WAN y también posiblemente uso de orientación a objetos en el lenguaje de desarrollo. Sin
embargo, también requeriría algoritmos para ciertas operaciones, como encontrar rutas
(probablemente usando un algoritmo de cálculo de iruta más corta), representar mapas y
buscar direcciones.
Además, incluso una aplicación que no requiere contenido algorítmico a nivel de aplicación
depende en gran medida de los algoritmos. ¿La aplicación se basa en hardware rápido? El
diseño de hardware utilizó algoritmos. ¿La aplicación se basa en interfaces gráficas de
usuario? El diseño de cualquier GUI se basa en algoritmos. ¿La aplicación depende de la red?
El enrutamiento en redes se basa en gran medida en algoritmos. ¿La aplicación estaba escrita
en un lenguaje diferente al código máquina? Luego fue procesado por un compilador,
intérprete o ensamblador, todos los cuales hacen un uso extensivo de algoritmos.
Los algoritmos son el núcleo de la mayoría de las tecnologías utilizadas en los ordenadores
contemporáneos. Además, con las capacidades cada vez mayores de éstos, las usamos para
resolver problemas más grandes que nunca. Como vimos en la comparación anterior entre la
“ordenación por inserción” y la ordenación por mergesort, es en los tamaños de problemas
más grandes donde las diferencias de eficiencia entre los algoritmos se vuelven
particularmente prominentes. Tener una base sólida de conocimientos y técnicas algorítmicas
9
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Los números que se desea ordenar también se conocen como claves. Aunque
conceptualmente estamos ordenando una secuencia, la entrada llega en forma de una matriz
con n elementos. En este capítulo, normalmente se describen los algoritmos como programas
escritos en un pseudocódigo que es similar en muchos aspectos a C, C ++, Java, Python o
Pascal. Si ha sido introducido a cualquiera de estos lenguajes, no debería tener problemas
leer los algoritmos presentados.
10
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Figura 1.2 Clasificar una mano de cartas usando la clasificación por inserción.
Figura 1.3. El funcionamiento de INSERTION-SORT en la matriz A= {5,2,4,6,1,3}. Los índices de matriz aparecen
encima de los rectángulos y los valores almacenados en las posiciones de la matriz aparecen dentro de los
rectángulos. (a) - (e) Las iteraciones del bucle for de las líneas 1–8. En cada iteración, el rectángulo negro contiene
la clave tomada de A[j], que se compara con los valores de los rectángulos sombreados a su izquierda en la prueba
de la línea 5. Las flechas sombreadas muestran los valores de la matriz movidos una posición a la derecha en la
línea 6, y negro las flechas indican a dónde se mueve la clave en la línea 8. (f) La matriz ordenada final.
11
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
INSERTION-SORT.A
1 for j = 2 to A,length
2 key = A[j]
3 // Insert A[j] into the sorted sequence A[1…j-1]
4 i = j-1
5 while i>0 and A[ j ] > key
6 A[ i+1 ] = A[ i ]
7 i = i -1
8 A[ i+1 ] = key
La figura 1.3 muestra cómo funciona este algoritmo para A= {5,2,4,6,1,3}. El índice j indica la
"carta actual" que se inserta en la mano. Al comienzo de cada iteración del ciclo ‘for’, que está
indexado por j, la submatriz que consta de los elementos A[1…j -1] constituye la mano
actualmente ordenada, y la submatriz restante A[j+1…j - n] corresponde al montón de cartas
que aún están en la mesa. De hecho, los elementos A[1…j -1] son los elementos
originalmente en las posiciones 1 a (j – 1), pero ahora ordenados. Declaramos estas
propiedades de A[1…j -1] formalmente como un ciclo invariante:
Al comienzo de cada iteración del bucle ‘for’ de las líneas 1-8, la submatriz A[1…j -1] consta
de los elementos originalmente en A[1…j -1], pero ordenados.
Usamos invariantes de bucle para ayudarnos a comprender por qué un algoritmo es correcto.
Debemos mostrar tres cosas sobre un ciclo invariante:
Inicialización: es cierto antes de la primera iteración del bucle.
Mantenimiento: si es verdadero antes de una iteración del bucle, permanece
verdadero antes de la siguiente iteración.
Terminación: cuando el bucle termina, la invariante nos da una propiedad útil que
ayuda a demostrar que el algoritmo es correcto.
Obsérvese la similitud con la inducción matemática, donde para probar que se cumple una
propiedad, se prueba un caso base y se realiza un paso inductivo. Aquí, mostrar que el
invariante se cumple antes de la primera iteración corresponde al caso base, y mostrar que el
invariante se cumple de una iteración a otra corresponde al paso inductivo.
La tercera propiedad es quizás la más importante, ya que usamos el invariante de bucle para
mostrar la corrección. Por lo general, usamos el invariante de bucle junto con la condición de
que provocó la terminación del bucle. La propiedad de terminación difiere de cómo usamos
habitualmente la inducción matemática, en la que aplicamos el paso inductivo infinitamente;
aquí, detenemos la "inducción" cuando termina el bucle.
Veamos cómo se mantienen estas propiedades para la ordenación por inserción.
Inicialización: Se comienza mostrando que el invariante del bucle se mantiene antes de la
primera iteración del ciclo, cuando j = 2. 1 La submatriz A[1,…j- 1], por lo tanto, consiste solo
en el elemento A[1], que de hecho es el elemento original en A[1]. Además, esta submatriz
1 Cuando el ciclo es un ciclo for, el momento en el que verificamos el invariante del ciclo justo antes de la primera
iteración es inmediatamente después de la asignación inicial a la variable contador de ciclo y justo antes de la
primera prueba en el encabezado del ciclo. En el caso de INSERTION-SORT, este tiempo es después de asignar
2 a la variable j pero antes de la primera comprobación de si j ≤ [Link].
12
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
está ordenada (trivialmente, por supuesto), lo que muestra que el invariante del bucle se
mantiene antes de la primera iteración del ciclo.
Mantenimiento: A continuación, abordamos la segunda propiedad: mostrar que cada
iteración mantiene el ciclo invariante. De manera informal, el cuerpo del bucle ‘for’ funciona
moviendo A[j - 1], A[j - 2,] A[j - 3], y así sucesivamente una posición hacia la derecha hasta
encontrar la posición adecuada para A[ j ] (líneas 4-7), en cuyo punto inserta el valor de A[ j ]
(línea 8). La submatriz A[1…j] entonces consta de los elementos originalmente en A[1…j],
pero ordenados. Incrementar j para la siguiente iteración del ciclo ’for’ conserva el bucle
invariante.
Un tratamiento más formal de la segunda propiedad nos requeriría enunciar y mostrar un ciclo
invariante para el bucle ‘while’ de las líneas 5-7. En este punto, sin embargo, es preferible no
empantanarnos en tal formalismo, por lo que confiamos en nuestro análisis informal para
mostrar que la segunda propiedad es válida para el bucle externo.
Estrictamente hablando, se debe definir con precisión las instrucciones del modelo RAM y sus
costos. Sin embargo, hacerlo sería tedioso y proporcionaría poca información sobre el diseño
y análisis de algoritmos. También, debemos tener cuidado de no abusar del modelo RAM. El
modelo RAM contiene instrucciones que se encuentran comúnmente en ordenadores reales:
aritmética (como sumar, restar, multiplicar, dividir, restar, truncamiento, redondeo),
movimiento de datos (cargar, almacenar, copiar) y control (bifurcación condicional e
incondicional, llamada de subrutina y retorno). Cada una de estas instrucciones requiere una
cantidad constante de tiempo.
Los tipos de datos en el modelo RAM son enteros y de coma flotante (para almacenar números
reales). En algunas aplicaciones la precisión es crucial. También asumimos un límite en el
tamaño de cada palabra de datos. Por ejemplo, cuando trabajamos con entradas de tamaño
n, normalmente asumimos que los enteros están representados por ‘c*log n’ bits para alguna
constante ‘c ≥ 1’. Se requiere ‘c ≥ 1’ para que cada palabra pueda contener el valor de n, lo
13
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
que nos permite indexar los elementos de entrada individuales, y restringimos c para que sea
una constante de modo que el tamaño de la palabra no crezca arbitrariamente. (Si el tamaño
de la palabra pudiera crecer arbitrariamente, podríamos almacenar grandes cantidades de
datos en una palabra y operar en todo ello en un tiempo constante, claramente un escenario
poco realista).
14
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
2 Aquí hay algunas sutilezas. Los pasos computacionales que especificamos en inglés son a menudo variantes de un procedimiento que
requiere más que una cantidad constante de tiempo. Por ejemplo, más adelante podríamos decir "ordenar los puntos por la coordenada x",
lo que, como veremos, lleva más de una cantidad constante de tiempo. Además, tenga en cuenta que una instrucción que llama a una
subrutina lleva un tiempo constante, aunque la subrutina, una vez invocada, puede tardar más. Es decir, separamos el proceso de llamar a
la subrutina (pasarle parámetros, etc.) del proceso de ejecutar la subrutina.
15
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
contribuirá con ‘cin’ al tiempo total de ejecución 3. Para calcular T(n), el tiempo de ejecución
de INSERTION-SORT en una entrada de n valores, sumamos los productos del costo y los
tiempos columnas, obteniendo
T(n) = c1n+ c2(n - 1) + c4(n - 1) + c5 ∑𝒏𝒏𝒋𝒋=2(𝒕𝒕𝒋𝒋 ) + c6 ∑𝒏𝒏𝒋𝒋=2(𝒕𝒕𝒋𝒋 𝒋𝒋 − 1) + c7∑𝒏𝒏𝒋𝒋=2(𝒕𝒕𝒋𝒋 − 1) + c8(n-1)
Incluso para entradas de un tamaño determinado, el tiempo de ejecución de un algoritmo
puede depender de qué entrada de ese tamaño se proporcione. Por ejemplo, en INSERTION-
SORT, el mejor caso ocurre si la matriz ya está ordenada. Para cada j = 2,3,…n, , entonces
encontramos que ‘A[i] ≤ key’ en la línea 5 cuando i tiene su valor inicial de j - 1. Así ‘tj = 1’
para’ j = 2, 3,… n’, y el mejor tiempo de ejecución es:
T(n) = c1n + c2(n - 1) + c4(n - 1) + c5(n - 1) + c8(n - 1) = (c1 + c2 + c4 + c5 + c8)n – (c2 + c4 + c5
+ c8)
Podemos expresar este tiempo de ejecución como (an + b) para las constantes a y b que
dependen de los costos del enunciado ci, por tanto, es una función lineal de n.
Si la matriz está en orden inverso, es decir, en orden decreciente, se produce el peor de los
casos. Debemos comparar cada elemento A[j] con cada elemento en todo la submatriz
ordenada A[ 1,2,…j-1 ], y así tj = j para j = 2,3 …,n. Tenemos entonces que:
𝑛𝑛
𝑛𝑛(𝑛𝑛 + 1)
� 𝑗𝑗 = −1
2
𝑗𝑗=2
Y
𝑛𝑛
𝑛𝑛(𝑛𝑛 − 1)
�(𝑗𝑗 − 1) =
2
𝑗𝑗=2
Encontramos que, en el peor de los casos, el tiempo de ejecución de INSERTION-SORT es :
𝒏𝒏(𝒏𝒏+1) 𝒏𝒏(𝒏𝒏−1) 𝒏𝒏(𝒏𝒏−1)
T(n) = c1n + c2(n-1) + c4(n-1) + c5*� − 1�+ c6* +c7* + c8(n -
2 2 2
𝒄𝒄5 𝒄𝒄6 𝒄𝒄7 𝒄𝒄5 𝒄𝒄6 𝒄𝒄7
1)=� + + �n + (𝒄𝒄1 + 𝒄𝒄2 + 𝒄𝒄4 +
2
− − + 𝒄𝒄8 )n -(𝒄𝒄2 + 𝒄𝒄4 + 𝒄𝒄5 + 𝒄𝒄8)
2 2 2 2 2 2
Podemos expresar esto tiempo de ejecución en el peor de los casos como:
a∗n2 +b*n + c para las constantes a, b y c que nuevamente dependen de los costos de
declaración ‘ci’; por tanto, es una función cuadrática de n. Por lo general, en la “ordenación
por inserción”, el tiempo de ejecución de un algoritmo se fija para una entrada determinada,
aunque existen algunos algoritmos "aleatorizados" interesantes cuyo comportamiento puede
variar incluso para una entrada fija.
En nuestro análisis de “ordenación por inserción”, hemos analizado tanto el caso mejor, en el
que la matriz de entrada ya está ordenada, como el peor de los casos, en el que la matriz de
entrada se ordenó al revés. Sin embargo, normalmente durante el resto de esta exposición,
nos concentraremos en encontrar sólo el tiempo de ejecución del peor de los casos, es decir,
el tiempo de ejecución más largo para cualquier entrada de tamaño n. Damos tres razones
para esta orientación.
3 Esta característica no es necesariamente válida para un recurso como la memoria. Una declaración que hace referencia a m palabras de
la memoria y se ejecuta n veces no necesariamente hace referencia a m* n palabras distintas de la memoria.
16
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
• Para algunos algoritmos, el peor de los casos ocurre con bastante frecuencia. Por
ejemplo, al buscar en una base de datos un dato en particular, el peor de los casos del
algoritmo de búsqueda ocurre cuando la información no está presente en la base de
datos. En algunas aplicaciones, las búsquedas de información inexistente pueden ser
frecuentes.
• El "caso medio" suele ser tan malo como el peor de los casos. Suponga que elegimos
aleatoriamente n números y aplicamos ordenación por inserción. ¿Cuánto tiempo se
tarda en determinar en qué lugar de la submatriz A[ 1…j – 1 ], se inserta el elemento
A[ j ]?. En promedio, la mitad de los elementos de A[ 1…j – 1], son menores que A[ j
] y la mitad de los elementos son mayores. Por lo tanto, en promedio, verificamos la
mitad de la submatriz A[ 1…j – 1 ], por lo que tj es aproximadamente j / 2. El tiempo
medio de ejecución resultante resulta ser una función cuadrática del tamaño de
entrada, al igual que el tiempo de ejecución del peor de los casos.
17
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Podemos elegir entre una amplia gama de técnicas de diseño de algoritmos. Para la
ordenación por inserción, usamos un enfoque incremental: habiendo ordenado la submatriz
A[ 1…j – 1 ], insertamos el elemento individual A[j] en su lugar apropiado, produciendo la
submatriz ordenada A[ 1….j ]. En esta sección, examinamos un enfoque de diseño alternativo,
conocido como “divide y vencerás. Lo usaremos para diseñar un algoritmo de ordenación cuyo
tiempo de ejecución en el peor de los casos, sea mucho menor que el de la ordenación por
inserción.
Muchos algoritmos útiles tienen una estructura recursiva: para resolver un problema dado,
se llaman a sí mismos recursivamente una o más veces para tratar subproblemas muy
relacionados. Estos algoritmos suelen seguir un enfoque de “divide y vencerás”: dividen el
problema en varios subproblemas que son similares al problema original, pero de menor
tamaño, resuelven los subproblemas de forma recursiva y luego combinan estas soluciones
para crear una solución al problema original.
Plan Básico.
• Dividir la matriz en dos mitades.
18
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Resuelve los subproblemas de forma recurrente. Sin embargo, si los tamaños de los
subproblemas son lo suficientemente pequeños, se resuelven los subproblemas de la manera
más directa.
Combina las soluciones de los subproblemas en la solución del problema original. El
algoritmo de ordenación por mergesort sigue de cerca el paradigma de “divide y vencerás”.
Intuitivamente, funciona de la siguiente manera.
Dividir: Divide la secuencia de n elementos para clasificar en dos subsecuencias de
(n / 2) elementos cada una.
Superar: Ordena las dos subsecuencias de forma recursiva utilizando la clasificación
por combinación (mergesort).
Combinar: Combina las dos subsecuencias ordenadas para producir la respuesta
ordenada.
La recursividad “llega a su fin” cuando la secuencia a ordenar tiene longitud 1, en cuyo caso
no hay trabajo por hacer, ya que cada secuencia de longitud 1 ya está ordenada.
Objetivo. Dados dos submatrices ordenadas a[lo] hasta a[mid] y a [mid + 1] hasta a
a[hi], reemplazar con la submatriz ordenada a[lo] a[hi].
19
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
colocando boca abajo en la pila de salida. Computacionalmente, cada paso básico toma un
tiempo constante, ya que estamos comparando solo las dos cartas superiores. Dado que
realizamos como máximo n pasos básicos, la combinación lleva 𝜣𝜣(n) tiempo.
El siguiente pseudocódigo implementa la idea anterior, pero con un giro adicional que evita
tener que verificar si alguna pila está vacía en cada paso básico. Colocamos en la parte inferior
de cada pila una tarjeta centinela, que contiene un valor especial que usamos para simplificar
nuestro código. Aquí, usamos ∞ como valor centinela, de modo que siempre que una carta
con ∞ esté expuesta, no puede ser la carta más pequeña a menos que ambas pilas tengan
sus cartas centinela expuestas. Pero una vez que eso sucede, todas las cartas que no son
centinelas ya se han colocado en la pila de salida. Como sabemos de antemano que
exactamente r - p + 1 cartas se colocarán en la pila de salida, podemos detenernos una vez
que hayamos realizado tantos pasos básicos.
MERGE(.A, p, q, r)
1 n1 = q - p + 1
2 n2 = r - q
3 Sean L[ 1….n1 + 1 ] y R[ 1….n2 + 1 ] nuevas matrices
4 for i =1 to n1
5 L [ i ] = A[ p + i - 1 ]
6 for j=1 to n2
7 R[ j ] = A[ q+ j ]
8 L[ n1 + 1 ] = ∞
9 R[ n2 + 1 ] = ∞
10 i=1
11 j=1
12 for k = p to r
13 if L[ i ] ≤ R[ j ]
14 A[ k ] ≈ L[ i ]
15 i≈i+1
16 else A[ k ] ≈R[ j ]
17 j = j +1
20
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Figura 1.6 La operación de las líneas 10-17 en la llamada MERGE(A, 9, 12, 16), cuando la submatriz
A[9,…16] contiene la secuencia {2, 4, 5, 7, 1, 2, 3, 6}. Después de copiar e insertar centinelas, la matriz L
contiene {2, 4, 5, 7, ∞}, y la matriz R contiene {1, 2, 3, 6, 1, ∞}. Las posiciones ligeramente sombreadas
en A contienen sus valores finales, y las posiciones ligeramente sombreadas en L y R contienen valores
que aún no se han vuelto a copiar en A. En conjunto, las posiciones ligeramente sombreadas siempre
comprenden los valores originalmente en A[9…16], junto con los dos centinelas. Las posiciones muy
sombreadas en A contienen valores que se copiarán, y las posiciones muy sombreadas en L y R contienen
valores que ya se han copiado de nuevo en A. (a) - (h) Las matrices A, L y R, y sus respectivas índices k,
i, y j antes de cada iteración del ciclo de las líneas 12-17 (i) Las matrices e índices al final. En este punto,
la submatriz en A[9,..16] está ordenada, y los dos centinelas en L y R son los únicos dos elementos en
estas matrices que no se han copiado en A.
Debemos demostrar que este ciclo invariante se mantiene antes de la primera iteración del
ciclo ‘for’ de las líneas 12-17, que cada iteración del ciclo mantiene el invariante y que el
invariante proporciona una propiedad útil para mostrar la corrección cuando el ciclo termina.
Inicialización: antes de la primera iteración del ciclo, tenemos k = p, de modo que la
submatriz A[ p…k – 1 ] está vacío. Esta submatriz vacía contiene los k - p = 0
21
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
elementos más pequeños de L y R, y dado que i = j = 1, tanto L[i] como R[j] son los
elementos más pequeños de sus matrices, que no se han vuelto a copiar en A.
Mantenimiento: Para ver que cada iteración mantiene el bucle invariable, vamos a
suponer que L[i] ≤ R[j]. Entonces L[i] es el elemento más pequeño que aún no se ha
copiado en A. Dado que A[ p…k-1 ] contiene los elementos k - p más pequeños,
después de que la línea 14 copia L[i] en A[k], el submatriz A[ p….k ] contendrá los k –
p – 1 elementos más pequeños. Incrementando k (en la actualización del bucle ‘for’)
e i (en la línea 15) prepara el bucle para la siguiente iteración. Si en su lugar L[i] > R[j],
a continuación, las líneas 16–17 realizan la acción adecuada para la siguiente iteración
del bucle.
4 Veremos en el apartado 1.3 cómo interpretar formalmente las ecuaciones que contienen la notación 𝜣𝜣(n).
5 La expresión [x] denota el menor entero mayor o igual a x, y │x │ denota el mayor entero menor o igual a x. Estas notaciones se definen
en el apartado 1.3. La forma más fácil de verificar que el ajuste q a [(p + r)/2] produce submatrices A[p,,..q] y A[q+1,..r] de tamaños [n/2] y
[n/2] respectivamente, es examinar los cuatro casos que surgen dependiendo de si cada uno de p y r es par o impar.
22
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
MERGE-SORT.(A,p,r)
1 If p <r
2 q = [(p +r) / 2]
3 MERGE-SORT(A, p, q)
4 MERGE-SORT(A q +1, r)
5 MERGE(A, p, q, r)
Para ordenar toda la secuencia A = ( A[1], A[2],…. A[n1] ), hacemos la llamada inicial
MERGE-SORT(A,1, [Link]), donde una vez más [Link] = n. La figura 1.7 ilustra el
funcionamiento del procedimiento de abajo hacia arriba cuando n es una potencia de 2. El
algoritmo consiste en combinar pares de secuencias de 1 elemento para formar secuencias
ordenadas de longitud 2, combinando pares de secuencias de longitud 2 para formar
secuencias ordenadas de longitud 4, y así sucesivamente, hasta que dos secuencias de
longitud n / 2 se fusionen para formar la secuencia final ordenada de longitud n.
Mergesoft: implementación de Java:
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
Cuando un algoritmo contiene una llamada recursiva a sí mismo, a menudo podemos describir
su tiempo de ejecución mediante una ecuación de recurrencia o recurrente, que describe el
tiempo de ejecución general en un problema de tamaño n, en términos del tiempo de ejecución
en entradas más pequeñas. Luego, podemos usar herramientas matemáticas para resolver la
recurrencia y proporcionar límites sobre el rendimiento del algoritmo.
23
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Figura 1.7 La operación de clasificación por fusión en la matriz A{5, 2, 4, 7, 1, 3, 2, 6}. Las longitudes de las
secuencias ordenadas que se fusionan aumentan a medida que el algoritmo avanza de abajo hacia arriba.
La repetición del tiempo de ejecución de un algoritmo de divide y vencerás se sale de los tres
pasos del paradigma básico. Como antes, dejamos que T(n) sea el tiempo de ejecución de un
problema de tamaño n. Si el tamaño del problema es lo suficientemente pequeño, digamos n
≤ c para alguna constante c, la solución sencilla toma un tiempo constante, que escribimos
como 𝛩𝛩(1). Suponga que la división del problema produce x subproblemas, cada uno de los
cuales es 1 / y del tamaño del original. (Para la ordenación mergesort, tanto x como y son 2,
pero veremos muchos algoritmos de divide y vencerás en los que x ≠ .) Se necesita tiempo
T(n/y) para resolver un subproblema de tamaño n /y, por lo que toma tiempo xT(n/y) resolver
uno de ellos. Si tomamos D(n) el tiempo para dividir el problema en subproblemas y C(n) el
tiempo para combinar las soluciones de los subproblemas en la solución del problema original,
obtenemos la recurrencia
𝚯𝚯(1) 𝑆𝑆𝑆𝑆 𝑛𝑛≤𝑐𝑐
𝑇𝑇𝑇𝑇 = � 𝑛𝑛 �
𝑎𝑎𝑎𝑎� �+𝐷𝐷(𝑛𝑛)+𝐶𝐶(𝑛𝑛) 𝐸𝐸𝐸𝐸 𝑜𝑜𝑜𝑜𝑜𝑜𝑜𝑜 𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐
𝑏𝑏
24
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Cuando agregamos las funciones D(n) y C(n) para el análisis de mergesort, estamos
agregando una función que es 𝜣𝜣(n) y una función que es‚ 𝜣𝜣(1). Esta suma es una función
lineal de n, es decir 𝜣𝜣(n). Al agregarlo al término 2T(n/2) del paso "conquistar", se obtiene la
recurrencia del tiempo de ejecución del peor caso T(n) del mergesort:
Debido a que la función logaritmo crece más lentamente que cualquier función lineal, para
entradas lo suficientemente grandes, mergesort, con su tiempo de ejecución 𝜣𝜣(n log n)
supera al ordenamiento por inserción, cuyo tiempo de ejecución es‚ 𝜣𝜣(n2) en el peor de los
casos. Necesitamos el teorema maestro para comprender intuitivamente por qué la solución
de la recurrencia (2.1) es T(n) = 𝛩𝛩(n log n) Reescribamos la recurrencia (2.1) como
𝑐𝑐 𝑆𝑆𝑆𝑆 𝑛𝑛=1
T(n)≈� 𝑛𝑛 � (2.2)
2𝑇𝑇� �+𝑐𝑐𝑐𝑐 𝑆𝑆𝑆𝑆 𝑛𝑛>1
2
6 Es poco probable que la misma constante represente exactamente tanto el tiempo para resolver problemas de tamaño 1 como el tiempo
por elemento de matriz de los pasos de dividir y combinar. tiempos y entendiendo que nuestra recurrencia da un límite inferior en el tiempo
de ejecución. tiempo de ejecución. Ambos límites están en el orden de n log n y, en conjunto, dan un Θ(n log n) tiempo de ejecución.
Podemos solucionar este problema dejando que c sea el mayor de estos tiempos y entendiendo que nuestra recurrencia da un límite
superior en el tiempo de ejecución, o dejando que c sea el menor de estos.
25
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Figura 1,8 Cómo construir un árbol de recursividad para la recurrencia T(n) = 2T(n /2) + cn. La parte (a) muestra
T(n), que se expande progresivamente en (b) - (d) para formar el árbol de recursividad. El árbol completamente
expandido en la parte (d) tiene niveles de (log n + 1) (es decir, tiene una altura de log n, como se indica), y cada
nivel aporta un costo total de cn. El costo total, por lo tanto, es cn * log n + cn, que es 𝜣𝜣(n * log n )
26
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
• Paso inductivo: suponga que las llamadas recursivas funcionan correctamente, y utilice
esta suposición para probar que la llamada actual funciona correctamente.
27
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Proposición: Si D(N) satisface D(N) 2D(N / 2) + N para N> 1, con D (1) = 0, luego
D(N) N lg N.
Pf 1. [suponiendo que N es una potencia de 2]
28
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
2.1. Introducción.
29
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
30
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
optimista, otra moderada y otra pesimista realizas por un experto. Otra de las técnicas
clásicas es la Delphi, que consiste en enviar la información a 3 expertos independientes y
ponderar sus estimaciones.
Las técnicas clásicas dependen del conocimiento del experto, mientras que las
técnicas de puntos función o medición funcional, se basan más en metodologías que
evalúan con precisión cada componente, ponderando la complejidad de cada uno, e
introduciendo modificadores según lo estable del sistema o experiencia del equipo.
• Una vez lograda la primera estimación base, ahora se debe considerar los riesgos.
• El riesgo no constituye una amenaza si es gestionado adecuadamente.
• El motivo deriva de la incertidumbre existente en cada componente a desarrollar.
Por ejemplo:
o Si una actividad depende de una condición, existe el riesgo que esta no se
cumpla y esto produzca un impacto.
o Todas las actividades tienen insumos (un producto previo) y recursos, si
estos no están disponibles, provocan un impacto. Ej. Recursos escasos,
personal no disponible o costoso, proyectos externos, etc.
• Todo esto provoca pérdida de tiempo, costo, calidad. A esta pérdida se le conoce
como el impacto del riesgo.
• Para dar respuesta al riesgo se establecen acciones y planes de respuesta, tales
como:
o Realizar provisiones adicionales en las estimaciones parciales (agregar
holgura).
o Agregar más actividades y por tanto, mayor es la estimación, para
contemplar el trabajo necesario para mitigar el riesgo.
• Una vez identificados los riesgos, se debe volver al paso 2 y 3 para revisar
nuevamente nuestras estimaciones.
• Por último, siempre es una buena práctica realizar una evaluación formal de las
estimaciones.
• Para que sea la revisión sea objetiva, se debe realizar por alguien que no participó
en la elaboración de la estimación.
• En la evaluación, se debe revisar:
o Las bases, el desglose de tareas, las premisas y las restricciones.
o Si el procedimiento de estimación cumplió la metodología establecida.
• Debe enfocarse en identificar:
o Premisas no ciertas o con alta probabilidad de no cumplirse.
o Riesgos no identificados.
o Requerimientos ocultos no identificados.
o Posibles requerimientos extraordinarios.
31
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Cuando surja la necesidad de estimar cuánto dinero se necesita para desarrollar el próximo
proyecto de software, es conveniente que se cuente con ejemplos de estimación de costos de
proyectos de software anteriores, los cuales se puedan usar como referencia y guía.
Para realizar una estimación de costos de un proyecto de software se necesitarán dos cosas,
en primer lugar determinar el tamaño del software que se va a desarrollar, utilizando alguna
unidad de medida, luego, se necesitará saber cuántas unidades de dicha medida puede
desarrollar el equipo de trabajo, a un determinado costo.
COSMIC tiene la ventaja de no establecer límites arbitrarios al tamaño funcional, así puede
medir componentes de software muy grandes o pequeños. Adicionalmente, está basado en
el desglose funcional de los componentes de software, alineado con las prácticas de
Ingeniería de software.
32
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Facturación de pedidos
Desde la pantalla de pedidos pendientes, el usuario podrá seleccionar uno o varios pedidos
para ser facturados. Se deberá poder facturar un pedido individual o un lote de pedidos. El
usuario podrá elegir entre emitir una factura por pedido o agrupar las facturas por cliente. Una
vez facturado, se debe cambia el estatus del pedido a “facturado”, y así, al refrescar la lista
de pedidos pendientes este no será mostrado.
Finalidad de la medición
Realizar la estimación funcional de mejora del sistema de administración, que abarca los
requisitos de lista de pedidos pendientes, la facturación de pedidos y el envío de email al
facturar el pedido.
Usuarios
Mapeo y medición
En el método COSMIC, se utiliza ingeniería de software del proyecto para determinar los
procesos funcionales y los flujos de datos que lo componen. Posteriormente, se asigna un
punto de función COSMIC por cada movimiento de datos identificado.
El ejemplo está compuesto por los siguientes procesos funcionales y movimientos de datos:
Proceso funcional: Visualizar lista de pedidos pendientes de facturación.
Flujos de datos:
• Entrada: Seleccionar en el menú la opción “lista de pedidos pendientes”.
• Lectura: Obtener todos los pedidos pendientes de venta.
• Salida: Sacar en pantalla todos los pedidos de venta pendientes.
• Entrada: Especificar fecha inicial y final del pedido.
• Entrada: Especificar cliente de pedido.
• Lectura: Obtener pedidos de venta filtrados a partir de los parámetros de búsqueda.
• Salida: Mostrar en pantalla la lista de pedidos pendientes según filtrado de criterios.
• Salida: Imprimir la lista de pedidos.
• Salida: Exportar la lista de pedidos a Excel.
33
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Movimientos de datos:
• Entrada: Seleccionar el pedido a facturar.
• Entrada: Seleccionar la facturación individual o agrupada por cliente por cada pedido.
• Entrada: Iniciar proceso de facturación actuando sobre un botón de inicio.
• Lectura: Leer de la base de datos los datos de pedidos seleccionados para
facturación.
• Lectura: Leer las líneas de cada pedido.
• Escritura: Crear un registro de factura para cada pedido (Facturación individual).
• Escritura: Crear registro de líneas de factura individual.
• Escritura: Agrupar pedidos de un mismo cliente y crear un registro de factura
(Facturación por cliente).
• Escritura: Crear registro de líneas de factura por cliente.
• Escritura: Cambiar el estado de pedido a “facturado”.
Si este proyecto se realiza para un tercero, se debe añadir además el margen de ganancia
(beneficio industrial) que se espera obtener.
Para que esta medición sea exacta, se considera que un punto de función está desarrollado
solamente cuando está totalmente acabado e instalado en el entorno de producción. Si una
34
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Costo punto de función = Costo mes del equipo de trabajo / puntos de función del mes
De nuestro ejemplo:
Costo por punto de función = 21.800 € / 23 puntos de función = 947,82 € / Punto de función
Una vez que se cuenta con la medición del tamaño del software y el costo por unidad de
medida, se puede determinar el costo del proyecto de software usando la siguiente formula:
Costo de un proyecto de software = Tamaño del software x Costo por punto de función
Duración del proyecto = 19 puntos de función COSMIC / 23 puntos de función COSMIC mes
Conclusión:
De esta forma se ha determinado que el proyecto de software durará 0,83 meses en
desarrollarse (Poco menos de un mes) y costará 18.008,69 €
Los principales productos que es útil medir son: la especificación, el diseño y el código.
El número de líneas de código (LOC) es la medida más usada para medir la longitud del
código fuente. Se han realizado muchas propuestas para su contabilización. Una de ellas:
Líneas de código efectivas (ELOC: effective lines of code) o no comentadas (NCLOC)
35
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
• Es la más extendida
36
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Puntos de función
• El análisis de los puntos de función (FPA) es una medida de la funcionalidad propuesta en el
método de estimación del esfuerzo de Albrecht [Albrecht, 1979]
• El paso previo al cálculo de los puntos de función, FP, es el cálculo de UFC (unadjusted
function point count):
Se determinan los siguientes elementos de alguna representación del software:
• Entradas externas: entradas de usuario que proporcionan datos a la aplicación
37
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
• IFPUG (The International Function Point Users’ Group) [ISO/IEC 20926:2003]: estándar de uso
de FPA
38
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
39
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Cálculo de ECF:
8
7
Puntos de caso de uso - Wikipedia, la enciclopedia libre
40
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
• Objetos (OB)
• Relaciones (RE)
• Estados (ES)
• Transiciones (TR)
Se determinan cuentas adicionales para:
• Primitivas modificadas de la función manual (PMFu)
41
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
• Dominio de los datos: medida basada en el número de entidades y relaciones del diagrama
entidad-relación
RE/PFu < 0,7 aplicación de dominio de función
0,8 < RE / PFu < 1,4 aplicación híbrida
RE/PFu > 1,5 aplicación de dominio de datos
Las métricas se calculan a partir de incrementos PFu y OB corregidos (IPFuC e IOBC):
TCi IPFuC
2 1,0 REi IOBC
5 5,8 1 1,0
10 16,6 3 4,0
15 29,3 6 9,8
20 43,2
Las métricas bang pueden definirse formalmente y calcularse automáticamente mediante
herramientas CASE
2.9. Complejidad
Complejidad de un problema: cantidad de recursos que se requieren para una óptima
solución del problema
Complejidad de la solución: recursos necesarios para implementar una solución particular:
• Complejidad de tiempo: el recurso es tiempo de ordenador
42
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
43
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
3. COMPLEJIDAD ALGORÍTMICA
44
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
El caso mejor corresponde a la traza (secuencia de sentencias) del algoritmo que realiza
menos instrucciones. Análogamente, el caso peor corresponde a la traza del algoritmo que
realiza más instrucciones. Respecto al caso medio, corresponde a la traza del algoritmo que
realiza un número de instrucciones igual a la esperanza matemática de la variable aleatoria
definida por todas las posibles trazas del algoritmo para un tamaño de la entrada dado, con
las probabilidades de que éstas ocurran para esa entrada.
A la hora de medir el tiempo, siempre lo haremos en función del número de operaciones
elementales que realiza dicho algoritmo, entendiendo por operaciones elementales (en
adelante OE) aquellas que el ordenador realiza en tiempo acotado por una constante. Así,
consideraremos OE las operaciones aritméticas básicas, asignaciones a variables de tipo
predefinido por el compilador, los saltos (llamadas a funciones y procedimientos, retorno
desde ellos, etc.), las comparaciones lógicas y el acceso a estructuras indexadas básicas,
como son los vectores y matrices. Cada una de ellas contabilizará como 1 OE.
En general, es posible realizar el estudio de la complejidad de un algoritmo sólo en base a un
conjunto reducido de sentencias, aquellas que caracterizan que el algoritmo sea lento o rápido
en el sentido que nos interesa. Para hacer un estudio del tiempo de ejecución de un algoritmo
para los tres casos citados comenzaremos con un ejemplo concreto. Supongamos entonces
que disponemos de la definición de los siguientes tipos y constantes:
CONST n =...; (* num. maximo de elementos de un vector *); TYPE vector = ARRAY [1..n] OF
INTEGER;
y de un algoritmo cuya implementación es:
PROCEDURE Buscar (VAR a:vector; c:INTEGER):CARDINAL;
VAR j:CARDINAL;
BEGIN
J:=1; (* 1 *)
WHILE (a[J]<c) AND (j<n) DO (* 2 *)
J:=J+1 (* 3 *)
END; (* 4 *)
IF a[J]=c THEN (* 5 *)
RETURN J (* 6 *)
ELSE RETURN 0 (* 7 *)
END (* 8 *)
END Buscar;
Para determinar el tiempo de ejecución, calcularemos primero el número de operaciones
elementales (OE) que se realizan:
– En la línea (1) se ejecuta 1 OE (una asignación).
– En la línea (2) se efectúa la condición del bucle, con un total de 4 OE (dos
comparaciones, un acceso al vector, y un AND).
– La línea (3) está compuesta por un incremento y una asignación (2 OE).
– La línea (5) está formada por una condición y un acceso al vector (2 OE).
– La línea (6) contiene un RETURN (1 OE) si la condición se cumple.
– La línea (7) contiene un RETURN (1 OE), cuando la condición del IF anterior es falsa.
No se contabiliza la copia del vector a la pila de ejecución del programa, pues se pasa por
referencia y no por valor (está declarado como argumento VAR, aunque no se modifique
dentro de la función). En caso de pasarlo por valor, necesitaríamos tener en cuenta el coste
que esto supone (un incremento de n OE).
En el caso mejor para el algoritmo, se efectuará la línea (1) y de la línea (2) sólo la primera
mitad de la condición, que supone 2 OE (suponemos que las expresiones se evalúan de
izquierda a derecha, y con “cortocircuito”, es decir, una expresión lógica deja de ser evaluada
45
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
en el momento que se conoce su valor, aunque no hayan sido evaluados todos sus términos).
Tras ellas la función acaba ejecutando las líneas (5) a (7). En consecuencia, T(n)=1+2+3=6. •
En el caso peor, se efectúa la línea (1), el bucle se repite n–1 veces hasta que se cumple la
segunda condición, después se efectúa la condición de la línea (5) y la función acaba al
ejecutarse la línea (7). Cada iteración del bucle está compuesta por las líneas (2) y (3), junto
con una ejecución adicional de la línea (2) que es la que ocasiona la salida del bucle. Por
tanto:
𝑛𝑛−1
Es importante observar que no es necesario conocer el propósito del algoritmo para analizar
su tiempo de ejecución y determinar sus casos mejor, peor y medio, sino que basta con
estudiar su código.
En este caso, un examen más detallado de la función nos muestra que tras su ejecución, la
función devuelve la posición de un entero dado c dentro de un vector ordenado de enteros,
devolviendo 0 si el elemento no está en el vector. Lo que acabamos de probar es que su caso
mejor se da cuando el elemento está en la primera posición del vector. El caso peor se
produce cuando el elemento no está en el vector, y el caso medio ocurre cuando
consideramos equiprobables cada una de las posiciones en las que puede encontrarse el
elemento dentro del vector (incluyendo la posición especial 0, que indica, como se ha
comentado, que el elemento a buscar no se encuentra en el vector).
46
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
FOR i:=1 TO n DO
S
END;
puede ser calculado a partir del bucle equivalente:
i:=1;
WHILE i<=n DO
S; INC( i )
END;
• El tiempo de ejecución de una llamada a un procedimiento o función F(𝑃𝑃1, 𝑃𝑃2,, 𝑃𝑃3, … . . 𝑃𝑃𝑛𝑛, ) es 1
(por la llamada), más el tiempo de evaluación de los parámetros 𝑃𝑃1, 𝑃𝑃2,, 𝑃𝑃3, . . 𝑃𝑃𝑛𝑛, más el tiempo
que tarde en ejecutarse F, esto es, T = 1 + T(𝑃𝑃1, ) + 𝑇𝑇(𝑃𝑃2,, )+ ... + T(𝑃𝑃𝑛𝑛, ) + T(F). No contabilizamos
la copia de los argumentos a la pila de ejecución, salvo que se trate de estructuras complejas
(registros o vectores) que se pasan por valor.
El paso de parámetros por referencia, por tratarse simplemente de punteros, no contabiliza
tampoco.
También es necesario tener en cuenta, cuando el compilador las incorpore, las optimizaciones
del código y la forma de evaluación de las expresiones, que pueden ocasionar “cortocircuitos”
o realizarse de forma “perezosa” (lazy). En el presente trabajo supondremos que no se
realizan optimizaciones, que existe el cortocircuito y que no existe evaluación perezosa.
47
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
(a) La 𝛩𝛩-notación delimita una función entre factores constantes. Escribimos f(n) =
𝜣𝜣(g(n)). Si existen constantes positivas n0, c1 y c2 tales que a la derecha de n0, el
valor de f(n) siempre se encuentra entre c1g(n) y c2g(n) inclusive.
(b) La notación-O da un límite superior para una función dentro de un factor
constante. Escribimos f(n) = O(g(n)) si hay constantes positivas n0 y c tales que en y
a la derecha de n0, el valor de f(n) siempre se encuentra en o por debajo de cg(n).
(c) La Ω-notación da un límite inferior para una función dentro de un factor constante.
Escribimos f(n) = Ω(g(n)) si hay constantes positivas n0 y c tales que en y a la derecha
de n0, el valor de f(n) siempre se encuentra en o por encima de cg(n).
48
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
3.3.2. Propiedades de O
Veamos las propiedades de la cota superior. La demostración de todas ellas se obtiene
aplicando la definición.
1. Para cualquier función f se tiene que si f ∈O(f):.
2. f ∈O(g) ⇒ O(f) ⊂ O(g).
3. O(f) = O(g) ⇔ f ∈O(g) y g ∈O(f).
4. Si f ∈O(g) y g ∈O(h) ⇒ f ∈O(h).
5. Si f ∈O(g) y f ∈O(h) ⇒ f ∈O(min(g,h)).
6. Regla de la suma: Si f1 ∈O(g) y f2 ∈O(h) ⇒ f1 + f2 ∈O(max(g,h)).
7. Regla del producto: Si f1 ∈O(g) y f2 ∈O(h) ⇒ f1·f2 ∈O(g·h).
8. Si existe
𝑓𝑓(𝑛𝑛)
lim = 𝑘𝑘, dependiendo de los valores que tome k obtenemos:
𝑛𝑛→ ∞ 𝑓𝑓(𝑛𝑛)
a) Si k ≠0 y k < ∞ entonces O(f) = O(g).
b) Si k = 0 entonces f ∈O(g), es decir, O(f) ⊂ O(g), pero sin embargo se verifica que g
∉O(f).
De las propiedades anteriores se deduce que la relación ~O, definida por f ~O g si y sólo si
O(f) = O(g), es una relación de equivalencia. Siempre escogeremos el representante más
sencillo para cada clase; así los órdenes de complejidad constante serán expresados por
O(1), los lineales por O(n), etc.
49
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
La figura 1.13 (c) muestra la idea tras la notación- Ω. Para todos los valores n en o a la derecha
de n0, el valor de f(n) es igual o superior a cg(n). A partir de las definiciones de las notaciones
asintóticas que hemos visto hasta ahora, es fácil probar el siguiente teorema importante:
Teorema 3.1
Para dos funciones cualesquiera f(n) y g(n), tenemos f(n) = 𝜣𝜣(g(n)) si y solo si f(n) = O(g(n))
y f(n) = Ω(g(n)).
Como ejemplo de la aplicación de este teorema, nuestra prueba de que an2 + bn + c = 𝜣𝜣(n2),
para cualesquiera constantes a, b y c, donde a > 0, implica inmediatamente que an2 + bn + c
= Ω(n2), y an2 + bn + c = O(n2). En la práctica, en lugar de usar el teorema 3.1 para obtener
límites superior e inferior asintóticos a partir de límites asintóticamente estrechos, como
hicimos en este ejemplo, generalmente lo usamos para demostrar límites asintóticamente
estrechos a partir de límites superiores e inferiores asintóticos.
Cuando decimos que el tiempo de ejecución de un algoritmo es Ω(g(n)) queremos decir que:
no importa qué entrada particular de tamaño n se elija para cada valor de n, el tiempo de
ejecución en esa entrada es al menos una constante multiplicada por g(n), para n
suficientemente grande. De manera equivalente, estamos dando un límite inferior en el mejor
tiempo de ejecución de un algoritmo. Por ejemplo, el mejor tiempo de ejecución de la
ordenación por inserción es Ω(n).
Por tanto, el tiempo de ejecución de la ordenación por inserción pertenece tanto Ω(n), como
a O(n2), ya que cae en cualquier lugar entre una función lineal de n y una función cuadrática
de n. Además, estos límites son asintóticamente lo más ajustados posible: a saber, el tiempo
de ejecución de la ordenación por inserción no es Ω(n2), ya que existe una entrada para la
cual la ordenación por inserción se ejecuta en 𝜣𝜣(𝒏𝒏2 ) tiempo (Cuando la entrada ya está
ordenada).
Sin embargo, no es contradictorio decir que el peor tiempo de ejecución de la ordenación por
inserción es Ω(n2), ya que existe una entrada que hace que el algoritmo tome tiempo Ω(n2).
3.3.4. Propiedades de Ω
Veamos las propiedades de la cota inferior Ω. La demostración de todas ellas se obtiene de
forma simple aplicando la definición.
[Link] cualquier función f se tiene que f ∈Ω(f).
2. f ∈Ω(g) ⇒ Ω(f) ⊂ Ω(g).
3. Ω(f) = Ω(g) ⇔ f ∈Ω(g) y g ∈Ω(f).
4. Si f ∈Ω(g) y g ∈Ω(h) ⇒ f ∈Ω(h).
5. Si f ∈Ω(g) y f ∈Ω(h) ⇒ f ∈Ω (max(g, h)).
6. Regla de la suma: Si f1 ∈Ω(g) y f2 ∈Ω(h) ⇒ f1 + f2 ∈ Ω(g + h).
7. Regla del producto: Si f1 ∈Ω(g) y f2 ∈Ω(h) ⇒ f1·f2 ∈Ω(g·h).
𝑓𝑓(𝑛𝑛)
8. Si existe lim = k, dependiendo de los valores que tome k obtenemos:
𝑛𝑛→∞ 𝑓𝑓(𝑁𝑁)
a) Si k ≠ 0 y k < ∞ entonces Ω(f) = Ω(g).
b) Si k = 0 entonces g ∈Ω(f), es decir, Ω(g) ⊂ Ω(f), pero sin embargo se verifica que
f ∉Ω(g).
De las propiedades anteriores se deduce que la relación ~Ω, definida por f ~Ω g si y sólo si
Ω(f) = Ω(g), es una relación de equivalencia.
50
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
Como última cota asintótica, definiremos los conjuntos de funciones que crecen
asintóticamente de la misma forma.
1 2
𝑛𝑛 2 − 3𝑛𝑛 = 𝛩𝛩( 𝑛𝑛2 )
2
Para hacerlo, debemos determinar las constantes positivas c1, c2 y n0 tales que
1
𝑐𝑐1 𝑛𝑛2 ≤≤ 𝑛𝑛2 − 3𝑛𝑛 ≤ 𝑐𝑐2 𝑛𝑛2
2
para todo n ≥ n0. Dividiendo entre n2 se obtiene:
1 3
𝑐𝑐1 ≤ − ≤ 𝑐𝑐2
2 𝑛𝑛
51
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
suficiente para dominar los términos de orden inferior. Por tanto, establecer c1 en un valor
ligeramente menor que el coeficiente del término de orden más alto y establecer c2 en un valor
ligeramente mayor permite satisfacer las desigualdades en la definición de la notación-Θ. El
coeficiente del término de orden superior también puede ignorarse, ya que solo cambia c1 y
c2 por un factor constante igual al coeficiente.
Como ejemplo, considere cualquier función cuadrática f(n) = an2 + bn + c, donde a, b y c son
constantes y a > 0. Desechando los términos de orden inferior e ignorando los rendimientos
constantes f(n) = 𝜣𝜣(𝒏𝒏2 ). Formalmente, para mostrar lo mismo, tomamos las constantes
|𝒃𝒃| |𝒄𝒄|
(c1 =a/4), (c2 = 7a/ 4) y n0 = 2.𝐦𝐦𝐦𝐦𝐦𝐦( ,� )
𝒂𝒂 𝒂𝒂
Puede verificar que 0 ≤ c1n2 ≤ an2 + bn + c ≤ c2n2 para todo n ≥ n0. En general, para cualquier
polinomio p(n)= ∑𝒅𝒅𝒊𝒊=0 𝒂𝒂𝒊𝒊 𝒏𝒏𝒊𝒊 , donde ai son constantes y ad > 0, tenemos p(n) = Θ(nd).
Dado que cualquier constante es un polinomio de grado 0, podemos expresar cualquier
función constante como Θ(n0), o Θ(1). Sin embargo, esta última notación es una “licencia
menor”, porque la expresión no indica qué variable tiende al infinito. 8 A menudo usaremos la
notación Θ(1) para significar una constante o una función constante con respecto a alguna
variable.
Veamos las propiedades de la cota exacta. La demostración de todas ellas se obtiene también
de forma simple aplicando la definición 1.3 y las propiedades de O y Ω.
1. Para cualquier función f se tiene que f ∈Θ(f).
2. f ∈Θ(g) ⇒ Θ(f) = Θ(g).
3. Θ(f) = Θ(g) ⇔ f ∈Θ(g) y g ∈Θ(f).
4. Si f ∈Θ(g) y g ∈Θ(h) ⇒ f ∈Θ(h).
5. Regla de la suma: Si f1 ∈Θ(g) y f2 ∈Θ(h) ⇒ f1 + f2 ∈Θ(max(g,h)).
6. Regla del producto: Si f1 ∈Θ(g) y f2 ∈Θ(h) ⇒ f1·f2 ∈Θ(g·h).
𝑓𝑓(𝑛𝑛)
7. Si existe lim = k, dependiendo de los valores que tome k obtenemos:
𝑛𝑛→∞ 𝑓𝑓(𝑁𝑁)
a) Si k ≠ 0 y k < ∞ entonces Θ(f) = Θ(g).
b) Si k = 0 los órdenes exactos de f y g son distintos.
8 El problema real es que nuestra notación ordinaria para funciones no distingue funciones de valores. En λ-cálculo, los parámetros de una
función están claramente especificados: la función n2 podría escribirse como λn,n2, o incluso λ r.r2. Sin embargo, adoptar una notación más
rigurosa complicaría las manipulaciones algebraicas, por lo que optamos por tolerar el abuso.
52
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
4. Por último, diremos que un algoritmo es de orden exacto Θ(f) si su tiempo de ejecución en
el caso medio 𝑇𝑇1/2 (𝑛𝑛) es de este orden.
𝑻𝑻(𝒏𝒏) = 𝒄𝒄𝟏𝟏 𝒑𝒑𝟏𝟏 (𝒏𝒏)𝒓𝒓𝒏𝒏𝟏𝟏 + 𝒄𝒄𝟐𝟐 𝒑𝒑𝟐𝟐 (𝒏𝒏)𝒓𝒓𝒏𝒏𝟐𝟐 + ……. 𝒄𝒄𝒌𝒌 𝒑𝒑𝒌𝒌 (𝒏𝒏)𝒓𝒓𝒏𝒏𝒌𝒌 = ∑𝒌𝒌𝒊𝒊=𝟏𝟏 𝒄𝒄𝒊𝒊 𝒑𝒑𝒊𝒊 (𝒏𝒏)𝒓𝒓𝒏𝒏𝒊𝒊
donde los valores 𝑐𝑐1 , 𝑐𝑐2 ..., 𝑐𝑐𝑛𝑛 , y 𝑟𝑟1 , 𝑟𝑟2 ,, ..., 𝑟𝑟𝑚𝑚 son números reales, y 𝑝𝑝1(𝑛𝑛), 𝑝𝑝2(𝑛𝑛), … . , 𝑝𝑝𝐾𝐾(𝑛𝑛), son
polinomios en n con coeficientes reales.
Para resolverlas haremos el cambio 𝑥𝑥 𝑛𝑛 = T(n), con lo cual obtenemos la ecuación
característica asociada:
𝑎𝑎𝑜𝑜 𝑥𝑥 𝑘𝑘 + 𝑎𝑎1 𝑥𝑥 𝑘𝑘−1 + 𝑎𝑎2 𝑥𝑥 𝑘𝑘−2 + ⋯ 𝑎𝑎𝑘𝑘 = 0
Llamemos 𝑟𝑟1 , 𝑟𝑟2 … . . 𝑟𝑟𝑘𝑘 a sus raíces, ya sean reales o complejas. Dependiendo del orden de
multiplicidad de tales raíces, pueden darse los dos siguientes casos.
Caso 1: Raíces distintas
Si todas las raíces de la ecuación característica son distintas, esto es, 𝑟𝑟𝑖𝑖 ≠ 𝑟𝑟𝑗𝑗 si i ≠ j, entonces
la solución de la ecuación en recurrencia viene dada por la expresión:
T(n) = 𝒄𝒄𝟏𝟏 𝒓𝒓𝟏𝟏 + 𝒄𝒄𝟐𝟐 𝒓𝒓𝟐𝟐 + 𝒄𝒄𝟑𝟑 𝒓𝒓𝟑𝟑 + ⋯ 𝒄𝒄𝒏𝒏 𝒓𝒓𝒏𝒏 = ∑𝒌𝒌𝒊𝒊=𝟏𝟏 𝒄𝒄𝒊𝒊 𝒓𝒓𝒊𝒊
donde los coeficientes 𝑐𝑐𝑖𝑖 se determinan a partir de las condiciones iniciales.
Como ejemplo, veamos lo que ocurre para la ecuación en recurrencia definida para la
sucesión de Fibonacci:
T(n) = T(n–1) + T(n–2), n ≥ 2
con las condiciones iniciales T(0) = 0, T(1) = 1. Haciendo el cambio 𝑥𝑥 2 = T(n) obtenemos su
ecuación característica 𝑥𝑥 2 = x + 1, o lo que es igual, 𝑥𝑥 2 – x – 1 = 0, cuyas raíces son:
1 + √5 1 − √5
𝑟𝑟1 = 𝑟𝑟2 =
2 2
y por tanto .
𝑛𝑛 𝑛𝑛
�1 + √5� 1 − √5
𝑇𝑇(𝑛𝑛) = 𝑐𝑐1 � � + 𝑐𝑐2 � �
2 2
Para calcular las constantes c1 y c2 necesitamos utilizar las condiciones iniciales de la
ecuación original, obteniendo:
53
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
0 0
�1+ √5� 1− √5
𝑇𝑇(0) = 𝑐𝑐1 � � + 𝑐𝑐2 � � = 𝑐𝑐1 + 𝑐𝑐2 = 0
2 2
1
𝑐𝑐1 = −𝑐𝑐2 =
√5
1 1
�1+ √5� 1− √5
𝑇𝑇(1) = 𝑐𝑐1 � � + 𝑐𝑐2 � � = 1
2 2
𝑛𝑛
1 �1 + √5� 1 1 − √5
𝑇𝑇(𝑛𝑛) = � � − � � ∈ 𝐎𝐎(𝝆𝝆𝒏𝒏 ).
√5 2 √5 2
54
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
55
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
4. RESUMEN ESQUEMÁTICO
La mejor técnica para diferenciar la eficiencia de los algoritmos es el estudio de los órdenes
de complejidad. El orden de complejidad se expresa generalmente en términos de la
cantidad de datos procesados por el programa, denominada n, que puede ser el tamaño
dado o estimado.
La notación asintótica se describe por medio de una función cuyo dominio es los números
naturales (N) estimado a partir de tiempo de ejecución o de espacio de memoria de
algoritmos en base a la longitud de la entrada. Se consideran las funciones asintóticamente
no negativas.
A un conjunto de funciones que comparten un mismo comportamiento asintótico le
denominaremos un orden de complejidad. Habitualmente estos conjuntos se
denominan O, existiendo una infinidad de ellos; pero nos centraremos en unos pocos
de uso frecuente.
Para cada uno de estos conjuntos se suele identificar un miembro f(n) que se utiliza como
representante de la clase.
conjuntos u órdenes de
complejidad
O (1) orden
constante
O (log n) orden
logarítmico
O (n) orden lineal
O (n log n)
O(𝑛𝑛2 ) orden
cuadrático
O(𝑛𝑛𝑎𝑎 ) orden
polinomial (a >
2)
O(𝑎𝑎𝑛𝑛 ) orden
exponencial
(a > 1)
O (n!) orden factorial
Tabla 1.14. Órdenes de complejidad
ÍNDICE
Las funciones de la notación asintótica deben presentarse de la manera más simple posible. Se
considerará erróneo presentar un resultado como O(𝑛𝑛2 /2 + n), por ejemplo.
Presentar resultados como E(n) o T(n2) es erróneo. Se debe indicar como E(n) = O(n) o bien
T(n) Є O(𝑛𝑛2 ). (Los símbolos: = o Є son equivalentes en el uso habitual de la notación asintótica).
Los resultados deben expresarse en función del tamaño (o tamaños) de la entrada. Es erróneo
el que aparezcan variables locales en la función (por ejemplo, indicar que el orden del problema
es O(i) en vez de O(n)).
La complejidad de los algoritmos de ordenación más conocidos es:
algoritmo complejidad
inserción O(n2)
selección O(n2)
burbuja O(n2)
quick sort O(n log(n))
1
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
5. GLOSARIO
aleatorizados Java
Hecho aleatoriamente mediante algún Java es un lenguaje de programación y una
proceso., 20 plataforma informática que fue
C ++ comercializada por primera vez en 1995 por
Sun Microsystems., 12
C++ es un lenguaje de programación
diseñado en 1979 por Bjarne Stroustrup. La Los puntos de historia son un artefacto
intención de su creación fue extender al abstracto que nos permite ponernos de
lenguaje de programación C mecanismos acuerdo más fácilmente en la complejidad,
que permiten la manipulación de objetos., esfuerzo y riesgo que tiene una determinada
12 tarea., 37
combinatoria mergesort
La combinatoria es una rama de la El algoritmo de ordenamiento por mezcla
matemática perteneciente al área de (merge sort en inglés) es un algoritmo de
matemáticas discretas que estudia la ordenamiento externo estable basado en la
enumeración, construcción y existencia de técnica divide y vencerás., 9
propiedades de configuraciones que metodología ágil
satisfacen ciertas condiciones Las metodologías ágiles de desarrollo de
establecidas., 17 software buscan proporcionar en poco
componentes de 3GL tiempo pequeñas piezas de software en
En este tipo de lenguajes, los funcionamiento para aumentar la
programadores deben indicarle los satisfacción del cliente., 35
procedimientos específicos que debe hacer ordenación por inserción
el ordenador para lograr un objetivo. El ordenamiento por inserción (insertion sort
Ejemplos de lenguajes 3GL son C, Fortran, en inglés) es una manera muy natural de
Smalltalk, ADA, C++, C#, Cobol, Delphi, etc, ordenar para un ser humano, y puede
48 usarse fácilmente para ordenar un mazo de
especificación cartas numeradas en forma arbitraria., 9
Es una descripción completa del parámetros por referencia
comportamiento del sistema que se va a Un parámetro por referencia tiene por
desarrollar., 4 objetivo modificar el contenido de una
firmas, variable que se le envía a un procedimiento.
a firma electrónica es un concepto jurídico, Si por medio de un parámetro por valor llega
equivalente electrónico al de la firma un dato a un procedimiento, por un
manuscrita, donde una persona acepta y da parámetro por referencia se retorna y sale
por validado el contenido de un mensaje un dato de un procedimiento., 54
electrónico a través de cualquier medio pasan por valor
electrónico que sea legítimo y permitido., 4 Paso por valor
Fuzzy Logic Se crea una copia local de la variable dentro
La lógica difusa es una forma de lógica de de la función. Paso por referencia
muchos valores en la que el valor de verdad Se maneja directamente la variable, los
de las variables puede ser cualquier número cambios realizados dentro de la función le
real entre 0 y 1. Se emplea para manejar el afectarán también fuera., 54
concepto de verdad parcial, donde el valor
Pascal
de verdad puede variar entre
completamente verdadero y completamente Pascal es un lenguaje de programación
falso., 36 creado por el profesor suizo Niklaus Wirth
entre los años 1968 y 1969, y publicado en
invariante
1970. Su objetivo era crear un lenguaje que
Un invariante de bucle es una condición facilitara el aprendizaje de programación a
[entre las variables del programa] que es sus alumnos., 12
necesariamente verdadera inmediatamente
permutación
antes e inmediatamente después de cada
iteración de un bucle., 14
2
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
ÍNDICE
3
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
PREGUNTAS DE TEST
4
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
PREGUNTAS DE TEST
6. TEST
6.1. PREGUNTAS DE TEST
1. Marque aquellas estrategias de ordenación que tienen un tiempo O(n) cuando se les pide ordenar
un vector en el que todos los elementos son iguales:
a.☐ Ordenación por inserción.
b.☐ Ordenación por selección.
c.☐ Ordenación por fusión.
d.☐ Ordenación rápida (pivote primer elemento).
2, ¿Cómo se consigue una medida del tiempo que tarda un algoritmo independiente del procesador?
a.☐ Dividiendo el análisis en casos.
b.☐ Expresándola mediante una función, no un valor.
c.☐ Expresándola en función del número de operaciones elementales.
d.☐ Usando un análisis en tiempo amortizado.
e.☐ No se puede conseguir.
3. El análisis en tiempo promedio.
a.☐ Calcula la media de los tiempos del peor y mejor caso.
b.☐ Calcula la media de los tiempos de las ejecuciones con todas las posibles entradas de un
mismo tamaño.
c.☐ Calcula la media de los tiempos de las ejecuciones con las entradas del peor caso de todos
los tamaños posibles.
d.☐ Calcula la media de una secuencia de ejecuciones del algoritmo.
4. Marque los conjuntos de cota a los que pertenece la función n3/100 + 3n2 (no estamos hablando de
cotas ajustadas)
a.☐ O(n2)
b.☐ O(n3)
c.☐ O(n4)
d.☐ O(2n)
5. Cuando para distintas instancias del problema con el mismo tamaño de entrada, no obtenemos el
mismo resultado:
a.☐ No es posible calcular la complejidad a priori y debemos ejecutar el programa varias veces
con los mismos datos y obtener el tiempo medio para hallar la complejidad media.
b.☐ Debemos asegurarnos de que los datos son los mismos.
c.☐ Calculamos el máximo y mínimo coste que nos puede dar el algoritmo
d.☐ No se puede aplicar la técnica de paso de programa, ya que esta técnica es para calcular
la complejidad a priori.
5
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
PREGUNTAS DE TEST
𝑛𝑛
9. ∑𝑖𝑖=1 𝑖𝑖 𝑘𝑘 pertenece a:
a.☐ O(𝑛𝑛𝑘𝑘+1 )
b.☐ O(𝑛𝑛𝑘𝑘 )
c.☐ Tanto O(𝑛𝑛𝑘𝑘+1 ) 𝑐𝑐𝑐𝑐𝑐𝑐𝑐𝑐 O(𝑛𝑛𝑘𝑘 )
d.☐ Ninguna de las anteriores.
11. Dado el polinomio f(n) = 𝐴𝐴𝑚𝑚 𝑛𝑛𝑚𝑚 + 𝐴𝐴𝑚𝑚−1 𝑛𝑛𝑚𝑚−1 + ⋯ 𝐴𝐴𝑜𝑜 , 𝑐𝑐𝑐𝑐𝑐𝑐 𝐴𝐴0 Є 𝑅𝑅 +, entonces pertenece al orden:
a.☐ Ω(𝑛𝑛𝑚𝑚 )
b.☐ O(𝑛𝑛𝑚𝑚 )
c.☐ Θ(𝑛𝑛𝑚𝑚 )
d.☐ Las dos primeras respuestas son correctas.
6
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
SOLUCIONES A LAS PREGUNTAS DE TEST
PREGUNTA SOLUCIÓN
Pregunta 1 A,B
Pregunta 2 C
Pregunta 3 B
Pregunta 4 B,C,D
Pregunta 5 C
Pregunta 6 B
Pregunta 7 D
Pregunta 8 C
Pregunta 9 A
Pregunta 10 B
Pregunta 11 D
7
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
SOLUCIONES A LAS PREGUNTAS DE TEST
7. BIBLIOGRAFÍA BÁSICA
7.1. BIBLIOGRAFÍA BÁSICA
1. AHO, Alfred H., Hopcroft, John E. y Ullman, Jeffrey D. Estructuras de Datos y Algoritmos,
Addison-Wesley Iberoamericana, 1988.
2. ALFRED V. AHO, John E. Hopcroft, and Jeffrey D. Ullman. The Design and Analysis
of Computer Algorithms. Addison-Wesley, 1974.
3. ANANY LEVITIN. Introduction to the Design & Analysis of Algorithms. Addison-
Wesley,2007
4. BAASE, S.; Van Gelder, A. Computer Algorithms. Introduction to Design and Analysis. Addison-
Wesley, 2000.
5. BALCAZAR, José L. Apuntes sobre el Cálculo de la Eficiencia de los Algoritmos, Universidad
Politécnica de Cataluña, España.
6. BRASSARD, G., Bratley, P., Fundamentals of Algorithmics. Prentice Hall,1995.
7. CORMEN Thomas, Leiserson Charles and Rivest Ronald. Introduction to Algorithms. The MIT
Press, 1990.
8. DEXTER C. KOZEN. The Design and Analysis of Algorithms. Springer, 1992
9. DONALD E. KNUTH. Fundamental Algorithms, volume 1 of The Art of Computer
Programming. Addison-Wesley, 1968. Third edition, 1997.
10. ELLIS HOROWITZ, Sartaj Sahni, and Sanguthevar Rajasekaran. Computer
Algorithms. Computer Science Press, 1998
11. G. H. GONNET. Handbook of Algorithms and Data Structures. Addison-Wesley, 1984.
12. GILLES BRASSARD and Paul Bratley. Fundamentals of Algorithmics. Prentice Hall, 1996.82
13. GIMÉNEZ Cánovas, Domingo. Apuntes y Problemas de Algorítmica. .Facultad de Informática.
Universidad de Murcia, 2001.
14. GONNET, G. H., Baeza-Yates, R. Handbook of Algorithms and Data Structures, Addison-Wesley,
1991.
15. HERBERT S. WILF. Algorithms and Complexity. A K Peters, second edition, 2002.
16. HOROWITZ, E.; Sahni, S. Fundamentals of Data Structures. Computer Science Press, 1976.
17. JON L. BENTLEY. Writing Efficient Programs. Prentice Hall, 1982.
18. MICHAEL T. GOODRICH AND ROBERTO TAMASSIA. Algorithm Design:
Foundations, Analysis, and Internet Examples. John Wiley & Sons, 2001
19. JON KLEINBERG AND EVA TARDOS. ´ Algorithm Design. Addison-Wesley, 2006
20. JOAO SETUBAL AND JOAO MEIDANIS. Introduction to Computational Molecular
Biology. PWS
21. Publishing Company, 1997.
22. JEFFREY H. KINGSTON. Algorithms and Data Structures: Design, Correctness,
[Link]-Wesley, second edition, 1997.
23. KURT MEHLHORN. Sorting and Searching, volume 1 of Data Structures and
Algorithms. Springer, 1984.
24. KURT MEHLHORN. Graph Algorithms and NP-Completeness, volume 2 of Data
Structures and Algorithms. Springer, 1984.
25. KURT MEHLHORN. Multidimensional Searching and Computational Geometry,
volume 3 of Data Structures and Algorithms. Springer, 1984
26. KNUTH, Donald E. "Fundamental algorithms", volume 1 de "The Art of Computer
Programming", segunda edición, Addison-Wesley Publishing Company, Reading,
Massachusetts, 1973.
27. KNUTH, Donald E. "Sorting and Searching", volume 3 de "The Art of Computer Programming",
segunda edición, Addison-Wesley Publishing Company, Reading, Massachusetts, 1973.
28. MICHA HOFRI. Analysis of Algorithms. Oxford University Press, 1995
8
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
SOLUCIONES A LAS PREGUNTAS DE TEST
29. PAUL W. PURDOM, Jr. and Cynthia A. Brown. The Analysis of Algorithms. Holt,
Rinehart and Winston, 1985.
30. PARBERRY Ian. Problems on Algorithms. Prentice Hall, 1995.
31. PAVEL A. PEVZNER. Computational Molecular Biology: An Algorithmic Approach. The
MIT Press, 2000.
32. SANJOY DASGUPTA, Christos Papadimitriou, and Umesh Vazirani. Algorithms.
McGraw-Hill,2008.
33. RICHARD JOHNSONBAUGH and Marcus Schaefer. Algorithms. Pearson Prentice
Hall, 2004.
34. ROBERT SEDGEWICK and PHILIPPE FLAJOLET. An Introduction to the Analysis of
Algorithms. Addison-Wesley, 1996.
35. ROBERT SEDGEWICK, Kevin Wayne Algorithms - – 4th ed. Addison-Wesley.
36. SARA BAASE and ALAN VAN GELDER. Computer Algorithms: Introduction to Design
and Analysis. Addison-Wesley, third edition, 2000
37. STEVEN S. SKIENA. The Algorithm Design Manual. Springer, second edition, 1998.
38. SYMONS CR Software Sizing and Estimating MKII FPA. John Wiley and Sons, 1991.
39. UDI MANBER. Introduction to Algorithms: A Creative Approach. Addison-Wesley, 1989
40. WEISS, M. A., Estructuras de datos y algoritmos. Addison-Wesley Iberoamericana, 1995.
41. WIRTH, Niklaus. Algoritmos y Estructuras de Datos. Pentice Hall, 1987
i
Notas del capítulo: Hay muchos textos excelentes sobre el tema general de los algoritmos, Halstead,
1977 incluidos los de Aho, Hopcroft y Ullman [5, 6]; Baase y Van Gelder [28]; Brassard y Bratley [54];
Dasgupta, Papadimitriou y Vazirani [82];Goodrich y Tamassia [148]; ofri [175]; Horowitz, Sahni y
Rajasekaran [181]; Johnsonbaugh y Schaefer [193]; Kingston [205];Kleinberg y Tardos [208]; Knuth
[209, 210, 211]; Kozen [220]; Levitina [235]; Manber [242]; Mehlhorn [249, 250, 251]; Purdom y Brown
[287]; Reingold, Nievergelt y Deo [293]; Sedgewick [306]; Sedgewick y Flajolet [307]; Skiena [318]; y
Wilf [356]. Bentley [42, 43] y Gonnet [145];Gusfield [156], Pevzner [275], Setubal y Meidanis [310].Se
pueden encontrar descripciones generales de los algoritmos utilizados en biología computacional en
los libros de texto de Gusfield [156], Pevzner [275], Setubal y Meidanis [310] y Waterman [350].
ii
En 1968, Knuth publicó el primero de tres volúmenes con el título general “El arte de la programación
informática” [209, 210, 211]. El primer volumen marcó el comienzo del estudio moderno de algoritmos
9
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información
SOLUCIONES A LAS PREGUNTAS DE TEST
informáticos con un enfoque en el análisis del tiempo de ejecución, y la serie completa sigue siendo
una referencia interesante y valiosa para muchos de los temas presentados aquí. Según Knuth, la
palabra "algoritmo" se deriva del nombre "al-KhowÂarizmÎ", un matemático persa del siglo IX. Aho,
Hopcroft y Ullman [5] abogaron por el análisis asintótico de algoritmos, utilizando las notaciones que
introduce el Capítulo 3, incluida la 𝜣𝜣-notación, como un medio para comparar el rendimiento relativo.
También popularizaron el uso de relaciones de recurrencia para describir los tiempos de ejecución de
los algoritmos recursivos. Knuth [211] proporciona un tratamiento enciclopédico de muchos algoritmos
de clasificación. Su comparación de algoritmos de clasificación incluye análisis de conteo de pasos
exactos, como el que realizamos aquí para la “clasificación por inserción”. La discusión de Knuth sobre
la ordenación por inserción abarca varias variaciones del algoritmo. El más importante de ellos es el
ordenamiento de “Shell”, introducido por D. L. Shell, que usa ordenamiento por inserción en
subsecuencias periódicas de la entrada para producir un algoritmo de ordenamiento más rápido. Knuth
también describe la ordenación por combinación (mergesort). Menciona que en 1938 se inventó un
clasificador mecánico capaz de mezclar dos barajas de cartas perforadas en una sola pasada. J. von
Neumann, uno de los pioneros de la informática, aparentemente escribió un programa para la
clasificación por combinación en el ordenador EDVAC en 1945. Gries [153] describe la historia
temprana de demostrar que los programas son correctos, y atribuye a P. Naur el primer artículo de este
campo. Gries atribuye invariantes de bucle a R. W. Floyd. El libro de texto de Mitchell [256] describe un
progreso más reciente en la demostración de que los programas son correctos.
10
Tema 98 . La estimación de recursos y esfuerzo en el desarrollo de sistemas de información