Seleccion de un algortimo

Cuando se resuelve un problema y hay la necesidad de elegir entre
varios algoritmos, que nos puedan dar un resultado, existen dos
objetivos que suelen contradecirce para elegir uno.

a)Que el algortimo sea facil de entender,
codificar y depurar
(Vs.)
b)Que el algoritmo use eficientemente los
recursos de la computadora y se ejecute con
la mayor rapidez posible.

NOTA.-
Un algoritmo que nosotros al verlo lo podamos codificar ver si
es facil o no.

El primer punto (a) se debe elegir cuando se escribe un programa que
se va a utilizar una o pocas veces ya que el costo del tiempo de programacion
no sera tan relevante, ya que solo se ejecutara en pocas ocaciones.

El punto (b) es mas importante cuando se presenta un problema
cuya solucion se va a utilizar muchas veces ya que el costo de ejecucion
del programa minimizara al costo de escritura.

(SUGERENCIA)

En conclusion siempre sera mas ventajozo del punto de vista economico realizar
un algoritmo complejo siempre y cuando el tiempo de ejecucion del programa
resulte significativamente menor.

Complejidad en el espacio

Complejidad Espacial

Es la memoria que utiliza un programa para su ejecucion.
Lo que implica que la eficiencia, en memoria de un algoritmo
lo indica la cantidad de espacios requeridos para ejecutarlo
es decir, el espacio en memoria que ocupan todas las variables
propias del algoritmo.




EJEMPLO

Algoritmo de busqueda en arboles.

---funcion busqueda_arboles(problema (entra aki raiz))
---devuelve solucion/fallo
---inicializa arbol de busqueda con estado inicial
---ciclo hacer (ciclo do)
---si no hay candidatos para para expandir(si no existe el nodo fallo)
---entonces devolver fallo
++---en otro caso escoger nodo para expandir ( (insquiera ponen los menores y a la derecha los mayores si es mayor o menos a la raiz es para donde se va)si el que queremos expandir es mayo a la derecha si no a la izquierda)
---el nodo es el objetivo
---entonces devolver solucion
---en otro caso expandir nodo [si hay se regresa ++]



Simulación

==RESULTADOS OBTENIDOS==

Depth Nodes Time(tiempo) Memory (espacio)
0 1 1 millisecond 100 bytes
2 111 .1 seconds 11 kilobytes
9 11,111 11 seconds 1 megabyte
6 10^6 18 minutes 111 megabyte
8 10^8 31 hours 11 gigabytes
10 10^10 128 days 1 terabyte
12 10^12 35 years 111 terabytes




==Nota==
Factor de ramificacion-> 10 nodos sucesores p/cada uno como maximo
profundidad del arbol-> infinito

Complejidad

Tiempo de ejecucion de un algoritmo

Cómo se mide el tiempo de ejecución de un programa en función de N-->(número de datos)?

Esta funcion se puede medir fisicamente calculandolo con un reloj o se puede calcular
sobre el codigo contando las instrucciones a ejecutar y multiplicandolo por el tiempo
requerido por cada instruccion.

==Reglas practicas para calcular la complejidad de un algoritmo==

1.-Sentencia Sencilla
Asignacion, E/O de datos
Se refiere a las sentencias de asignación de entrada y salida de datos siempre y cuando
no trabajen sobre estructuras cuyo tamanio esta relacionado con N. Como requiere un
tiempo contanste de ejecución su complejidad es el del orden Constante--> O(1)

2.- Sentencia de Sentencias: Suma de complejidad
Su complejidad esta dada por la suma de complejidades individuales de acuerdo al tipo de
sentencias que se trata tomandose encuenta el orden mas alto.

3.- Decisión (if): La condicion suele ser de orden constante-->O(1), sumando en la peor rama posible ya sea la del THEN o del ELSE.

4.- Bucles (ciclos):En los ciclos o contadores Explicitos, existen dos casos el tamanio N forme parte de los limites del ciclo o no.

Ejemplo
a)contador explicito-->
for (int i=0;i {s1}
entonces k* O(1)=O(1)
for (int i=0;i {s1}
entoncesN*O(1)=O(n)Lineas


b)Evolucion de variables de control
No lineal(While)-->

En los ciclos multiplicativos como el while y el do while, el incremento o el decremento de la
variable e control no es lineal, lo que hace incrementar el orden de complejidad como en los
ejemplos siguientes

==EJEMPLO incremento==

c=1;
while (c{
s1;
c=2*c;
}
Entonces la complejidad logaritmica O(log n)

==EJEMPLO decremento==

c=N
while (c>1)
{
s1;
c=c/2;
}
Complejidad logaritmica O(log n)

5.- Llamadas de Procedimientos:
La complejidad de llamar a un procedimiento esta dada por la complejidad del contenido en procedimiento en si, es decir su complejidad depende del tipo de instrucciones o sentencias que existan en el cuerpo del procedimiento. En conclusión la complejidad de un procedimiento tiene a complicarse si se trata de procedimientos recursivos(llamandose a si mismo).

==EJEMPLO==

Funcion factorial (no recursiva) (Iterativo<--ciclos)

int factorial(int n)/*Sentencia entrada O(1)*/
{
int fact=1;/*sentencia de asignacion O(1)*/
for (int i=n;1>0,i--)/*Ciclo contador explicito O(n)*/
fact=fact*1;/*Sentencia de asignacion O(1)*/
return fact;/*Sentencia de salida O(1)*/
}

entonces: Complejidad lineal O(n) po el ciclo for con numero de iteraciones iguales a n.

_____________________________________________________________________________________________

==Ordenes de complejidad==

O(1) Constante Ideal
O(n) Lineal Eficiente
O(log n) Logaritmico "
O(n log n) Casi lineal "
O(n^k) Polinomial Tratable
O(k^n) Exponencial Intratables
O(n!) Factorial "

Notación asintótica "Omega" grande

La función omega grande, se utiliza para especificar una cota inferior para la velocidad del crecimiento, de una funcion F(n) cuando esta en funcion de n. Se usa la notacion que se lee T(n) Ω(g(n)) y significa que existe una constante c, tal que T(n)>=c(g(n)) , para un numero infinito de valores de n.

Ejemplo

Verificar la fucion T(n)=n^3+2n^2, c=1 para todos los valores n>=0

n^3+2n^2>=cn^3
(1)(1)^3+2(1)^2>=1(1)^3
1+2>=1
3>=1

Nota 1
El exponente mayor es el que se lo pone a 'n' en
la segunda ecuacion

Nota 2
O es menor el signo omega es mayor.


_____________________________________________________

Aritmética de la notación O.

Notación asintótica “O” grande.

Se utiliza para hacer referencia a la velocidad de crecimiento de los valores de una función. La utilidad de aplicar esta notación a un algoritmo es encontrar el límite superior del tiempo de ejecución, es decir el peor caso.

Definición
|g(n)|<=|c.f(n)|, para todo ne>=n0
Esto significa que la función g(n) pertenece o es válida para f(n) si solo si existen las constantes c y no tales que para n>=n0:
-T(n)<=cn
Nota
El orden de magnitud de la función será el orden del término de la función más grande respecto de n.

Ejemplo 1:
Supóngase que T(n) = (n+1) ^2, n_0=1 y c=4 para n>=1. Verifique la función utilizando la ‘O’ grande.

(n+1)^2<=cn^2

(1+1)^2<=4(1)^2
2^2=4
4<=4

Si se cumple la Función

Clases de Complejidad

Definición
Es la parte de la teoría de la computación que estudia los recursos requeridos durante el calculo para resolver un problema los cuales se dividen en: el tiempo y el espacio.

Los problemas de decisión se clasifican en conjuntos de complejidad llamadas clases de complejidad:

Clase de complejidad P
Es el conjunto de los problemas de decisión que puedan ser resueltos en tiempo polinómico calculado a partir de la entrada por una maquina de turins determinista y que corresponde a problemas que pueden ser resueltos aun en el peor de sus casos.

Ejemplo:

1.
Saber si un numero entero es primo.
2.
Saber si una frase pertenece a un conjunto de frases.

Clase de complejidad NP

Es el conjunto de los problemas de decisión que pueden ser resueltos por una maquina de turins no determinista en tiempo polinómico las cuales tienen la propiedad de que su solución puede ser verificada.

Clase de complejidad NP-Completo

Es el subconjunto de los problemas de decisión en NP que destacan por su extrema complejidad y que decimos se hayan en la frontera externa de la clase NP.