Ingeniero Técnico en Informática de Sistemas


Metodología: Algoritmia


9 - 10 - 97

ALGORITMIA

JOAQUIN ABEGER

  • Análisis de Algoritmos ( eficiente , tiempo y memoria ).

  • Diseño de Algoritmos ( esquemas de diseño ).

  • Verificación de Algoritmos ( estudio lógico ).

BIBLIOGRAFIA

Diseño y Análisis de Algoritmos . Ed. Paraninfo . Carmen Torres.

1.- ANALISIS DE ALGORTIMOS

TEMA 1 : CONCEPTO DE ALGORITMO

  • Introducción

    • Valores / Datos : son distintos :

    Tipo de Datos en Abstracto ( independientemente de la representación utilizada ) , esta formada por un conjunto de valores y las operaciones se pueden realizar con esos valores.

    Tipo Datos " Estructura Algebraica ( N , + , . )

    Valores , tienen un carácter abstracto independientemente de cómo se van a representar . No ocupan lugar ni tienen duración en el tiempo.

    Nº 13 - 13 , 1101 , 26 / 2

    Dato , elemento de información que representa a un valor de un determinado tipo . No son abstractos tienen entidad física ( ocupan espacio y tiene duración ) . El aspecto abstracto de un dato es el método de codificación . El dato representa físicamente un valor , cuesta tiempo operar con él.

    • Problemas - admiten especificación , la tarea de análisis de un problema consiste en la especificación del problema.

    • Precondición , es obtener los tipos de datos de entrada y las condiciones que deben cumplir sus valores.

    • Postcondición , tipos de datos de salida y la condición que cumplen sus valores.

    Cada posibilidad de valor de entrada que cumple la precondición representa a un ejemplar o caso del problema ( caracteriza al problema ).

    Los valores de salida que cumplen la postcondición representan una solución a ese caso del problema.

  • Definición de Algoritmo

  • Algoritmo - proviene de un matemático Persa 825.

    Algoritmo de Euclides , calcula el máximo común divisor de dos enteros.

    { m y n Enteros positivos } Precondición

    Forma clásica del algoritmo.

    E1.- Dividir m por n y obtener el resto r.

    E2.- Si r = 0 entonces n es el MCD ( m0 , n 0 ) y terminar.

    E3.- m ! n ; n ! r ; ir a E1.

    Definición Intuitiva - es un conjunto finito de reglas , que al aplicarse desencadena una secuencia de operaciones que permiten resolver el problema .

    A este conjunto de reglas se le exige las siguientes características o condiciones :

    • Finitud - cualquiera que sean los valores de los datos de entrada , el número de operaciones que realiza el procesador debe ser un número finito.

    • Definibilidad - cada operación que debe realizarse debe estar bien definida para el procesador , y debe estar bien definido el orden en que se realizan la operaciones .

    • Generalidad - los valores de entrada representan a un caso del problema ( cumplen la precondición ) . Los valores de salida deben de representar siempre a la solución a ese caso del problema .

    • Efectividad - cada operación que ordena realizando el algoritmo debe ser eficaz y en un tiempo finito .

    Uno de los criterios para saber si una operación es efectiva es si una persona puede realizarla en un tiempo finito .

     * n ! nunca es efectivo , ya que  nunca se utiliza con su valor exacto es una aproximación .

  • Observaciones

    • El procesador de un algoritmo es cualquiera capaz de procesar la información y capaz de entender el algoritmo .

    • No todos los problemas que admiten una especificación algorítmica tienen algoritmos que lo resuelvan , son problemas no computables.

    Parada , algoritmo o programa que dado cualquier problema este se detiene al final para sus posibles datos de entrada .

    Ej. : Algoritmo ; Dividir 17 entre 5 para hallar el cociente entero y el resto . No sabemos multiplicar.

    • 5

    -5 ! ! C " 1

    12

    -5 ! ! C " 2

    7

    -5 ! ! C " 3

    • 2 < 5 cierto FIN

    Representación mediante reglas Euclides ( si no se dice nada pasamos siempre a la siguiente regla ).

    { m y n enteros y m " 0 y n > 0 )

    DE1 : C ! 0

    DE2 : Si m< n entonces cociente = C y el resto = m Y terminar

    DE3 : m ! m - n ; C ! C + 1 ; e ir a DE2

  • Métodos de Cálculo

  • Definición matemática del algoritmo ( formalizarlo ).

    Cuaterna formada por elementos

    ( Q , I ,  , f )

    Q - conjunto de estados de computación .

    I - conjunto de estados iniciales ( I " Q ) .

     - conjunto de estados finales (  " Q ) .

    f - aplicación de Q en Q

    f : Q Q

    x f ( x )

    Cumple la siguiente propiedad : " z "  , f ( z ) = z

    Una Secuencia de Cálculo es una sucesión de estados de x0 , x1 , x2 , ... / x0 " I ( x0 estado inicial ) y " k " 0 , f ( x k ) = x k+1 , es decir la secuencia de cálculo es :

    x0 ! f ( x0 ) = x 1 ! f ( x1 ) = x2! ...

    f f

    estado de computación que le sigue

    Se dice que una secuencia de cálculo termina cuando " un entero k tal que f ( xk ) = xk

    " k , xk " 

    El valor más pequeño de k que cumple la condición , es el número de pasos que la secuencia de cálculo termina.

    xk = f ( xk ) = x k+1 = f ( x k+1 ) = xk+2 = ...

    A partir del estado k-ésimo todos los estados son el mismo.

    16 - 10 - 97

    Un método que termina en un número finito de pasos , cualquiera que sea el estado de entrada es un “ método de cálculo que termina “ .

    Ej. : Método formalizado del algoritmo de Euclides

    { m > 0 y n > 0 }

    E1 r ! m mod n

    E2 si r = 0 entonces fin , n es el mcd.

    E3 m ! n ; n !r ; e ir a E1

    I = { ( m , n ) | m > 0 y n > 0 } # entrada #

    Q = { ( m , n ) ; ( m , n , r , s ) ; ( n ) | s = 1 , 2 , 3 }

     = { ( n ) } # salida #

    f ( m , n ) = ( m , n , 0 , 1 ) # estado inicial #

    f ( m , n , r , 2 ) = ( u ) si r = 0

    ( m , n , r , 3 ) si r " 0

    f ( m , n , r , 3 ) = ( n , r , r , 1 )

    f ( n ) = ( n )

  • Métodos Efectivos de Cálculo

  • Un método de cálculo definido formalmente como en el ejemplo anterior no tiene porque tener efectividad en cada una de sus operaciones.

    Ej. : si x , y " R un método puede ser f ( x , y , ... = ( x / y , y , ...) , donde x / y no es una operación efectiva ( el cociente exacto ) .

    La idea de efectividad se basa en la manipulación finita de un conjunto finito de símbolos.

    El modelo formal lleva la sustitución de símbolos hasta sus últimas consecuencias para obtener así una idea matemática ( exacta ) de efectividad .

    Los alfabetos utilizados son conjuntos finitos de símbolos ( A ) .

    A* = conjunto de secuencias finitas de símbolos A que incluye la secuencia vacía.

    N > 0

    Conjunto : estados computación Q = { (  , j ) |  " A* y  " j " N }

    Estado de entrada I = { ( E ,  ) | P ( E ) y E " A* }

    siendo P la propiedad o condición que cumplen las

    cadenas de entrada.

    Estados de salida  = { (  , N }ø  " A* }

    La definición de la función transformadora de estados ( f ) , requiere que se halla definido los siguientes parámetros :

    j " A* , j " A* , aj " N , bj " N

    que cumplen  < aj " N y  < bj " N

    para  " j < N.

    (  , j ,  , aj ) , si j aparece en  de la forma  =  j 

    f (  , j ) con  de la longitud mínima.

    (  , bj ) , si j no aparece en 

    f (  , N ) = (  , N )

    Un método efectivo de cálculo que termina es muy similar a la idea intuitiva o informal de algoritmia .

    Ej. : Obtener un método efectivo de cálculo que de el resultado de | A - B | siendo A y B enteros no negativos.

    # alfabeto # A = { a , b } A B

    # entrada # I = { ( E ,  ) | E = aa ... a bb ... b

    S = aa ... a

    | A - B |

    | 3 - 5 | E = aaabbbbb S = aa ... a

    | A - B |

    N = 3 ! número de estados

  • Máquina Turing

  • Formalizar algoritmos , son ideales .

    MT - es un autómata finito , una cinta se longitud infinita dividida en celdas , cada una contiene un símbolo de un alfabeto finito A.

  • El número de símbolos de la cinta distintos de uno especial , que llamaremos blanco , es finito.

  • La cabeza de la máquina esta siempre encima de una celda y se puede mover según el conjunto de movimientos M.

  • M = { ! , ! , stop } ! mover a la celda derecha .

    ! mover a la celda izquierda

  • La máquina pueden estar en uno de los estado de Q ( conjunto de estados ) , Q es finito ; Q = { q0 , q1 , ... , qn }.

  • En un ciclo la máquina lee el carácter de la celda y según su estado interno escribe un símbolo que sustituye al anterior , según el símbolo leído realiza un movimiento que en un caso especial es la señal de stop.

  • 1.6.1. Descripción Formal

    f : A x Q ! A x M la f lee un símbolo y según el estado interno de la máquina escribe

    otro símbolo y se mueve.

    f es la función de salida

    g : A x Q ! Q según el símbolo leído y el estado interno produce otro estado.

    ( ei , Qj ) !qL

    g es la función de transición

    1.6.2. Funcionamiento

    El funcionamiento particular de una MT queda determinado por :

    • Posición inicial de la cabeza en la fila.

    • Estado interno inicial.

    • Especificación de la máquina ( especificación de f y g ).

    Se puede especificar poniendo todos los vectores posibles :

    ( ei , qj , ek , mh , qL ) para todos los valores de ei , qj

    Se realiza una tabla de doble entrada.

    Qj \ ei ... ei

    ...

    qj ek mh qL

    Dada una información en la cinta inicial pueden ocurrir dos cosas :

  • al cabo de un número finito de pasos la máquina se detiene ( stop ) . Se dice entonces que la máquina es aplicable a la cinta.

  • El caso contrario , nunca se produce la señal de stop . La máquina es inaplicable a la cinta.

  • Ej. : Se pretende sumar m y n ( m > 0 y n > 0 )

    A = { 1 , * “ ” }

    m n

    111 ...1 * 11 ... 1 Cinta de E

    !

    Posición Inicial Máquina ; estado inicial q0

    La suma aparece :

    m + n

    11 ........... 1

    qj \ ei 1 * “ “

    q0 “ “ ! q1 “ stop

    q1 1 ! q1 * ! q2

    q2 1 ! q2 1 ! q3

    q3 1 ! q2 * ! q4

    q4 1 ! q4 “ ” ! q0

  • Hipótesis de CHARCH ( 1936 )

  • Las siguientes ideas son equivalentes :

    • Idea intuitiva de algoritmo.

    • Método efectivo de cálculo que termina ( par aun especificación de entrada ).

    • Máquina de Turnig aplicable a una cinta inicial especificada.

    Equivalencia , debe entenderse como todo cálculo que es posible realizar con una de las tres ideas , es realizable con las otras dos ( hipótesis plauxible , sin demostrar ).

    TEMA 2 : ANALISIS DE ALGORITMOS

    2.1. Introducción

    Análisis de Algoritmos - consiste en la evaluación de la eficiencia del algoritmo . Los recursos que se evalúan son la memoria y el tiempo.

    Eficiencia en memoria y en tiempo son conceptos inversos a la cantidad de memoria y tiempo que consume.

    2.2. Evaluación de Memoria

    La determinación de la cantidad de memoria que precisa un algoritmo suele ser sencilla en la mayoría de los casos , pero cuando el algoritmo utiliza memoria o variables dinámicas o consume gran cantidad de memoria estática se hace necesario el análisis de memoria . Para ello se utilizan los mismos métodos que en la evaluación del tiempo.

    2.3. Evaluación de Tiempo

    El tiempo que utiliza un algoritmo para resolver un determinado caso de un problema depende de tres factores :

    1.- Tamaño del ejemplar

    2.- Implantación del algoritmo ( ordenador + programación compilado ).

    3.- Características del ejemplar sobre el que actúa.

    2.4. Estrategias de Análisis

  • Empírica ( a posteriori ) - medir el tiempo con ejemplares bien escogidos.

  • Teórica ( a priori ) - a partir del número de veces que se realiza cada operación del algoritmo y de su coste unitario , se obtiene una función dependiente del tamaño . Se llaman funciones de complejidad respecto al algoritmo.

  • Híbrida - obtener una función de complejidad con coeficientes indeterminados ( parte a priori ) , después se mide el tiempo del programa para diversos tamaños . Por medios estadísticos se ajustan los coeficientes a los datos específicos.

  • 2.5. Concepto de Tamaño

    Formalmente - es el número de bits necesario para representar un ejemplar del problema de forma razonablemente compacta . En la práctica se sustituye por algún parámetro que sea más o menos proporcional al tamaño en bits.

    • en ordenación : número de elementos.

    • En problemas aritméticos : se usa la longitud de los operandos.

    • Etc.

    Algunos problemas necesitan más de un parámetro como algoritmos de grafos ( en alguno de los cuales se hace necesario usar un número de vértices y número de arcos ).

    2.6. Principio de Invarianza

    Las funciones de complejidad (representa el tiempo que tarda un algoritmo) son el tipo :

    T : N ! R* aplicación de N en R

    n ! t ( n )

    R* - números reales positivos y el cero R* " {  }

    N = { 0 , 1 , 2 , ... }

    Cuando el tiempo de ejecución depende , además del tamaño de las características del ejemplar , no existe función de complejidad para el algoritmo . En ese caso se utiliza , según las necesidades alguna se las siguientes funciones de complejidad :

  • Tiempo del mejor caso : análisis del mejor caso.

  • Tiempo del peor caso : análisis del peor caso , es el más útil y no muy difícil.

  • Tiempo medio : se define :

  • Pi - probabilidad de que se de el caso i.

    ti - tiempo de ejecución para ese caso.

    ¿ Valor de una función de complejidad teórica , obtenido en un procesador ideal cuando el tiempo depende de la implantación del algoritmo ?

    t1 ( n ) " c t2 ( n ) , siendo t1 y t2 las funciones de complejidad de las dos implantaciones.

    Principio de Invarianza :

    ( " c , d > 0 ) ( " n0 " N ) ( " n " n0 ) ( t1 ( n ) " c t2 ( n ) y t1 ( n ) " d t2 ( n ) )

    Para todos los tamaños suficientemente grandes , la función t1 esta acotada por c t2 y t2 esta acotada por d y t1 .

    Ej. : t1 ( n ) = 10 n + 3 n0 = 1 , c = 2 , d = 1

    t2 ( n ) = 5 n + 4 " n " 1 , 10 n + 3 " 2 ( 5n + 4 )

    " n " 1 , 10 n + 3 " 1 ( 5 n + 4 )

    2.6.1. Acotación Sintótica

    Concepto de Acotación Asintótica

    Tenemos dos funciones del mismo tiempo

    Sean f , g : N ! R*

    F esta acotada asintóticamente por g ! (" c > 0) (" n0 " N) (" n " n0) (f (n) " c g (n) )

    [ f " g ] ! símbolo

    Ej. : t ( n ) = n exp 2 t' < t ya que " n " 11 = n0

    t' ( n ) = 10 n + 5 t' ( n ) = 10 n + 5 " 1 ( n exp 2 ) = 1 t ( n )

    t < t'

    Propiedades :

    • Reflexiva f " f

    • Transitiva f " g y q " h ! f " h

    • Constante 1 " f

    Por estas propiedades la relación " establece un orden parcial bien formado en las funciones N ! R*.

    3 - 11 - 97

    Teorema :

  • Si l = 0 , entonces f ( n ) es dominada asintóticamente por g .

  • f " g y g " f.

  • Si l = " , entonces g " f y g " f.

  • Si l " R y l " 0 , entonces f " g y g " f.

  • Ej. : f ( n ) = 2n² + n g ( n ) = 100 n + 500

    Ej. : f ( n ) = ln g ( n ) = n

    Consecuencias del teorema :

  • Si h < k ! ( n exp h ) " n ( exp k ) y ( n exp k ) " ( n exp h )

  • Si a > 1 y b > 1 ! logb m " loga y ! loga m " logb

  • Si k " 1 ! [ ( log n ) exp k ] " n y n " [ ( log n ) exp k ]

  • Si k " 1 y a > 1 ! ( n exp k ) " ( a exp n ) y ( a exp n ) " ( n exp k )

  • Si 1 < a < b ! ( a exp n ) " ( b exp n ) y ( a exp n ) " ( b exp n )

  • 2.6.2. Notación O ( o grande )

    Se define el siguiente conjunto de funciones :

    O ( f ( n ) ) = { t : N ! R* | t " f }

    Cuanto t ( n ) " O ( f ( n ) ) , se dice que t es el del O grande de f.

    Observaciones :

  • La función que figura en el paréntesis es representativa del conjunto.

  • Se suele colocar la función mas sencilla de todo el conjunto que la acote superiormente.

  • Cuando un algoritmo tiene una función de complejidad t ( n ) " O ( f ( n ) ) , se dice que la complejidad del algoritmo es O grande de f . Conviene en ese caso que f ( n ) sea la función más pequeña que acota superiormente al tiempo que utiliza el algoritmo.

  • t ( n ) = 3 n² + 2 n + 5 " O ( n³ )

  • t2 ( n ) = n² + 1 " O ( n³ )

    t2 ( n ) = 2n " O ( n³ )

    Propiedades :

  • f ( n ) " O ( f ( n ) )

  • a ) O ( f ( n ) ) " O ( g ( n ) ) ! f ( n ) " g ( n )

  • b ) O ( f ( n ) ) = O ( g ( n ) ) ! f ( n ) " g ( n ) y g ( n ) " f ( n )

  • Si t ( n ) " O ( f ( n ) ) y t' ( n ) " O ( g ( n ) )

  • a ) c * t ( n ) " O ( f ( n ) )

    b ) t ( n ) + t ` ( n ) " O ( f ( n ) + g ( n ) ) = O [ max ( f ( n ) , g ( n ) ) ]

    si f ( n ) es comparable asintóticamente con g ( n )

    c ) t ( n ) * t' ( n ) " O ( f ( n ) g (n ) )

    Ej. : t ( n ) = 3n² + 6n " = ( 3n² + 6n ) = { 1º prioridad }

    = O [ max ( 3n² , 6n ) ] = { 3º } = O ( 3n² ) ;

    ; 3n² " O ( n² ) = { 3º a }

    Ej. : t ( n ) = 4 log n + 6n = O ( log n + n ) = O [ max ( log n , n ) ] = O ( n )

    4 log n " O ( log n )

    6n " O ( n )

    Operaciones Conjuntísticas :

  • O ( f ( n ) ) + O ( g ( n ) ) = O ( f ( n ) + g ( n ) ) = 0 [ max ( f ( n ) , g ( n ) ) ]

  • si f y g son comparables

    El conjunto suma esta formada por funciones se la forma t ( n ) + t' ( n ) que pertenece respectivamente al 1º y 2º sumando.

  • O ( f ( n ) ) * O ( g ( n ) ) = O ( f ( n ) g ( n ) )

  • Producto conjustístico esta formado por funciones del tipo t ( n ) * t` ( n ) que pertenecen respectivamente al primer factor y al segundo factor.

    Ej. : t ( n ) = ( n² + n ) + log n " (1ª) O [ ( n² + n ) log n ] = O [ ( n² + n ) O ( log n )] =

    max ( n² , n )

    = O ( n² ) O ( log n ) = O ( n² log n )

    Conjuntos O más usuales :

    O (1) " O ( log n ) " O ( n ) " O ( n log n ) " O ( n exp k ) " O ( a exp n ) " O ( n! )

    " " " " k > 1 " a > 1 "

    Los algoritmos cuya función este en O ( log n ) su tiempo se dicen que tiene complejidad logarítmica . t ( n ) " O ( log n ).

    t ( n ) = O ( n ) complejidad lineal | t ( n ) = O ( a exp n ) complejidad exponencial

    t ( n ) = O ( n² ) complejidad cuadrática | t ( n ) = O ( n! ) complejidad factorial

    Cuando la complejidad de un algoritmo es superior a n³ , se supone que el algoritmo no es práctico.

    Cuando las complejidades son ( 2 exp n ) o n! , los algoritmos son impracticables.

    Los problemas de las que se saben que los algoritmos existentes tienen complejidad superior a la polinómica se llaman problemas intratables.

    2.6.3. Notación Omega 

    Dada f : N ! R* , se define

     ( f ( n ) ) = { t : N ! R* | t " f } ( todas las funciones acotadas inferiormente por f ).

    Cuando de un problema se sabe que todos sus algoritmos tienen funciones de tiempo t ( n ) "  ( f ( n ) ) , el problema es del tipo  ( f ( n ) ).

    Ej. : los tiempos de todas las ordenaciones por comparación son t ( n ) "  ( n - log n ) , el problema es tipo  ( n - log n ).

    2.6.4. Notación Zeta 

    Dada f : N ! R*

     ( f ( n ) ) = { t : N ! R* | t " f y f " t }

    Si t ( n ) "  ( f ( n ) ) , su complejidad es del orden exacto de f ( n ).

    Propiedades 

  • f ( n ) "  ( f (n) )

  •  ( f (n) ) =  ( g (n) ) ! f " g y f " g.

  • Si t (n) "  ( f (n) ) y t'(n) "  ( g (n) )

  • a ) c t(n) "  ( f (n) )

    b ) t (n) + t'(n) " ( f (n) + g (n) ) =  [ max ( f (n) , g (n) ) ]

    si t y g son compatibles

    c ) t (n) t'(n) "  ( f (n) g (n) )

    Relaciones Utiles

    n

    a )  ci "  ( n )

    i = 1

    n k + 1

    b )  ci "  ( n )

    i = 1 si k > 0

    c ) log ( n! ) "  ( n log n )

    -1

    d )  i "  ( log n )

    ( suma armónica = (1 /1 ) + ( 1/2 ) + ( 1/3 ) + ... + ( 1/n ) )

    2.7. Notación Asintótica con varios Parámetros

    Si el tiempo de un algoritmo depende de dos parámetros de tiempo :

    Sea f : N x N ! R*

    ( m , n ) ! f ( m , n )

    O ( f ( m , n ) ) = { t : N x N ! R* | ( " c > 0 ) ( " m0 , n0 " N )

    ( " m " m0 ) ( " n " n0 )

    t ( m , n ) " c f ( m , n ) }

    Ej. : la multiplicación normal se números de longitudes m y n es un tiempo :

    T ( m , n ) "  ( m n )

    Del mismo modo se definen :

     ( f ( m , n ) ) y  ( f ( m , n ) )

    f ( n , m ) = O ( g ( n , m ) ) si " c " R c > 0 n0 " N

    | f ( n , m ) | " c | g ( n , m ) |

    2.8. Notación Asintótica Condicional

    Definición :

    F ( n ) = O ( g (n ) / P ( n ) ) si " c > 0 c " R n0 " N

    P ( n ) : N ! B | f ( n ) | " c | g ( n ) | " P ( n ) "n " 1

    T ( n ) = O ( n² | n es par )

    T ( n ) = O ( log n | n = ( 2 exp k ) )

    TEMA 3 : ANALISIS ALGORITMOS ITERATIVOS

  • Propiedades de la Suma

  • Si T1 (n) = O ( f (n) ) y T2 (n) = O ( g (n) ) entonces

    T1 (n) + T2 (n) = O ( f (n) + g (n) )

    T1 (n) " C1 f (n) " T2 (n) " C2 g (n) " n01 > n " n02 > n

    T1 (n) + T2 (n) " C1 f (n) + C2 g (n) " max ( C1 , C2 ) ( f(n) + g(n) ) " n > max (n01 , n02 )

    T1 (n) + T2 (n) " C ( f (n) + g (n) ) " n > n0

    C = max ( C1 , C2 ) n0 = max ( n01 , n02 )

    T1 (n) + T2 (n) " C ( f (n) + g (n) ) " C ( max ( f (n) + g (n) )

    T1 (n) + T2 (n) = O ( max ( f (n) , g (n) )

    T = T1 + T2 ! El conjunto tiene la complejidad de la parte que tenga más complejidad.

    Propiedades :

    • Si g (n) " f (n) " n > n' ( Para valores grandes de n ).

    O ( f (n) + g (n) ) = O ( f (n) )

    • Si T1 (n) = O ( f (n) ) " T2 (n) = O ( g (n) )

    T1 (n) + T2 (n) = O ( f (n) + g (n) )

    • Si T (n) = O ( C f (n) ) entonces

    T (n) = O ( f (n) )

    Ej. : ( n + 1 )² = O ( ? )

    ( n + 1 )² = n² + 2n + 1

    n² = O ( n² ) 2n = O ( 2n ) = O ( n )

    1 = O ( 1 )

    n² + 2n + 1 = O ( n² ) + O ( n ) + O ( 1 )

    = ( max ( n² , 2n , 1 ) = O ( n² )

    Para averiguar cual es l complejidad de un algoritmo vamos a contar las instrucciones de las que consta.

    Ej. : Burbuja ( a : vector [ 1 .. n ] de elementos )

    Inicio

    Desde i ! 1 hasta n-1 hacer

    Desde j ! 1 hasta i + 1 paso-1 hacer

    Si A [ j - 1 ] > A [ j ] entonces

    temp ! A [ j - 1 ]

    A [ j - 1 ] ! A [ j ]

    A [ j ] ! temp

    finsi

    findesde

    findesde

    fin

    Ej. : Selección ( T [ 1 .. n ] )

    Desde i ! 1 hasta n-1 hacer

    min j ! i 2b O ( 1 ) + O ( i ) = O ( 1 )

    min x ! T [ i ]

    desde j ! i + 1 hasta n hacer

    si T [ j ] < min x entonces

    min j ! j O ( 1 ) a = comparaciones b + (n - i) * a + a +

    min x ! x b = asignaciones + 4b

    T [ min j ] ! T [ i ] O ( 1 ) a + 4 * b O ( n - i )

    T [ i ] ! min x - O ( 1 ) O(1) + O(1) + O(1) = 1

    fin

    Se halla la complejidad sin usar la propiedad de la suma.

    n-1

    b + ( n - 1 ) ( 3b + a ) + ( 2a + 4b )  n - i

    i

    [ n ( n-1 ) ] / 2

    = b + ( 3b + a ) ( n - 1 ) + [ n ( n - 1 ) ] / 2 ( 2a + 4b )

    n² ( a + 2b ) + n ( -a - 2b + 3b + a ) + ( b - 3b - a ) =

    n² ( a + 2b ) + n b - 2b - a = T (n)

    Utilizando la propiedad de la suma :

    Si

    O ( 1 ) + O ( 1 ) + O ( 1 ) = O ( max ( O ( 1 ) ) = O ( 1 )

    Desde interno

    O ( 1 ) + ( n - i ) ( O ( 1 ) + O ( 1 ) ) = O ( 1 ) + ( n - i ) ( O ( 1 ) ) =

    O ( 1 ) + ( n - i ) = O ( n - i )

    Desde externo

    n-1 comp asig

    O ( 1 ) +  O ( 1 ) + O ( 1 ) + O ( n - i )

    i=1

    n-1 n -1

    = O ( 1 ) +  O ( n - i ) = O ( 1 ) + O (  n - i ) =

    i=1 i = 1

    = O ( 1 ) + O [ ( n ( n - 1 ) ) / 2 ] = O ( 1 ) + O ( n² ) = O ( n² )

    CUADRATICA

    Ej. :

    Binaria ( A [ 1 .. n ] , elem )

    Inicio ! 1

    Fin ! n

    Medio = n /2

    Mientras fin > inicio hacer

    Si e = = A [ medio ] devolver ( medio ) O ( 1 )

    Sino si e < A [ medio ] entonces O ( 1 )

    Fin ! medio - 1 O ( 1 )

    Sino inicio ! medio + 1 O ( 1 )

    finsi

    medio ! ( fin - inicio ) / 2 O ( 1 )

    fin

    El bucle mientras se ejecuta como máximo log2 n.

    T (n) = O ( 1 ) + log n O ( 1 )

    O ( 1 ) + O ( log n ) = O ( log n )

    T (n) = O ( log2 n ) = O ( log n )

    COMPLEJIDAD LOGARITMICA

    Esta búsqueda es mejor que la lineal , pero debe estar ordenado el array.

    Si hubiera que ordenarlo , la complejidad sería de O ( n² ) , luego sería mejor la lineal.

  • Pistas para el Análisis

  • La complejidad de toda asignación , lectura o escritura de variables simples ( no arrays ) es constante es decir O ( 1 ).

  • La complejidad de una secuencia de instrucciones es la complejidad de la más compleja ( propia suma ).

  • La complejidad de la rama más compleja

  • La complejidad de un bucle , es igual a la suma de las complejidades de todos las ejecuciones del cuerpo más la complejidad de la evaluación de la condición de terminación.

  • Cuando en un programa hay llamadas a funciones , comenzar por evaluar la complejidad de las funciones que no llaman a otras funciones , y proceder de la misma manera hasta obtener la complejidad total.

  • Si tenemos una instrucción GOTO ; ESTA PROHIBIDO USAR LA SENTENCIA GOTO.

  • TEMA 4 : ANALISIS ALGORITMOS RECURSIVOS

    4.1. Introducción

    Ordenación por Mezcla :

    MezclaOrd ( L [ 1 .. n ] ) : array [ 1.. n ]

    Inicio

    Si n = = 1 entonces devolver ( L )

    Sino

    DividirEnDos ( L , L1 , L2 ) O (n)

    Devolver ( mezcla ( MezclaOrd ( L1 [ 1 .. n/2 ] ) , MezclaOrd ( L2 [ 1 .. n/2 ] )

    O (n) T [ n/2 ] T [ n/2 ]

    Finsi

    Fin

    T (n) = O ( 1 ) n = = 1 T (n) = C1 n = = 1

    2 T ( n/2 ) + O (n) 2 T ( n/2 ) + C2 n

    4.2. Ecuaciones de Recurrencia

    4.1. Suposición de una solución ( NO )

    Escogemos una solución que salga deducida de cómo funciona el algoritmo ( no lo vamos a utilizar ).

    4.2. Expansión de Recurrencias

    Partimos de la parte más compleja :

    T (n) = 2 T ( n / 2 ) + n

    T ( n / 2 ) = 2 T ( n / 4 ) + n / 2

    T ( n / 4 ) = 2 T ( n / 8 ) + n / 4

    ... sustituyo en

    T [ n / ( 2 exp i )] = = 2 T [ n / ( 2 exp i + 1 ) ] + n / ( 2 exp i ) t ( n / 2 )

    T (n) = 4 T ( n / 4 ) + ( 2n ) / 2 + n = 4 T ( n / 4 ) + 2n

    Sustituyo en t (n)

    = 8 T ( n / 8 ) + 4 ( n / 4 ) + 2n = 8 T ( n / 8 ) + 3n = 16 T ( n / 16 ) + 8 ( n / 8 ) + 3n =

    = 16 T ( n / 16 ) + 4n

    log n = i

    T (n) = n T1 + n log n = n + n log n = O ( n log n )

    3-11-97

    Divide y Vencerás DIVISION ... RECOMBINACION , dan lugar a ecuaciones :

    T (n) = a T ( n / b ) + d (n)

    a , b - valores positivos.

    d (n ) - coste o tiempo en hacer la división y recombinar.

    En la ecuación cambio n / b , hallar T , sustituyo en la ecuación de abajo :

    T (n / b) = a T (n / b²) + d (n / 2) = a² T (n / b²) + a d (n / b) + d (n) =

    T (n / b²) = a³ T (n / b³) d (n / b²) = a³ T (n / b³) + a² d (n / b²) + a d (n) + d (n)

    ...

    Tenemos que llegar en algún momento a n = 1

    Pararemos

    Solución homogénea

    La recurrencia se utiliza para resolver ecuaciones diferenciales.

    Si solo hubiera solución homogénea la complejidad sería :

    Los mejores valores de a y b deben hacer mínimo el exponente

    logb a sea menor , b debe ser mayor y a menor , si aumentamos la base el

    exponente puede ser más pequeño.

    a - número de subdivisiones

    b - tamaño relativo de la subdivisión

    Para conseguir la eficiencia se realiza esto , hay que intentar que la a sea pequeña y que b sea grande , nos conformaremos que a = b.

    Todo esto suponiendo que la solución sea mayor ( mucho más ) o no solo exista.

    Regla :

    Si d (n) es >" (n exp logb a) , n log n entonces la complejidad T (n) = O ( d (n) n log n ).

    T (n) = O ( d (n) ) Casi todo el coste o complejidad esta en dividir y recombinar . Este

    caso no es bueno , el mayor coste debe estar en solucionar el problema

    4.2. Resolución por el Método de la Ecuación Característica

    4.2.1. Recurrencias Homogéneas

    Se aplica para problemas en que T (n) = C1 T ( n-1 ) + C2 T ( n-2 ) + ... + Cn T ( n-k )

    Ej. : Fib (n)

    Inicio

    Si n = = 1 o n = = 2 entonces devolver 1

    Sino devolver Fib ( n-1 ) + Fib ( n-2 )

    Fin Dos llamadas recursivas

    T (n) = T ( n-1 ) + T ( n-2 )

    Manipular simbólicamente la ecuación :

  • Los términos con T ( n-k ) los paso a la izquierda.

  • T (n) - C1 T ( n-1 ) - C2 T ( n-2 ) - ... - Cn T ( n-k ) = 0

  • Cambio de signo , cambio el nombre por haber tanto negativo

  • a0 T(n) + a1 C1 T ( n-1 ) + a2 C2 T ( n-2 ) + ... +ak Cn T ( n-k ) = 0

    ai = -Ci ; i = 1 .. k ; a0 = 1

  • Cambio T (n) = tn

  • a0 tn + a1 tn-1 + a1 tn-2 + ... + ak tn-k = 0

  • Cambio

  • Sacamos factor común

  • tiempo = 0 , T = 0 ( solución cuando no ejecuto el algoritmo ).

  • Ecuación Característica de la Recurrencia

  • Puede ocurrir :

  • Todas la raíces son diferentes , Raíces Simples

  • x = ri solución para todos las i = 1 .. k . Deshacer las sustituciones

    Ej. : Tenemos la ecuación de recurrencia de un algoritmo :

    T (n) = 3 T ( n-1 ) + 4 T ( n-2 ) T (0) = 0 T (1) = 1 Condiciones iniciales

    T (n) - 3 T ( n-1 ) - 4 T ( n-2 ) = 0

    tn - 3 tn-1 - 4 tn-2 = 0 T (n) = tn

    x² - 3x - 4 = 0 Saco factor común

    r1 = 4 r2 = -1

    T (n) = tn =

    Calculamos C1 y C2 .

    T (0) = C1 4º + C2 ( -1 )º = C1 + C2 = 0

    T (0) = C1 4¹ + C2 ( -1 )¹ = 4 C1 - C2 = 1

    5 C1 = 0 C1 = 1/5

    1/5 + C2 = 0 C2 = - ( 1/5 )

    Ej. : Resolver el de fibonacci T (0) = 0 T (1) = 1

    T (n) = T ( n-1 ) + T ( n-2 )

    Primero la ecuación característica

    T (n) - T ( n-1 ) - T ( n-2 ) = 0

    tn - tn-1 - tn-2 = 0

    x² - x - 1 = 0

    C1 = 1 / " 5 ; C2 = -1 / " 5

  • Existe alguna raíz diferente , Raíces Múltiples

  • m

    Ej. : T (n) = 5 T ( n-1 ) - 8 T ( n-2 ) + 4 T ( n-3 )

    Primero ecuación característica x = nº términos + 1

    x³ - 5x² + 8x - 4 = 0

    ( x-1 ) ( x-2 )² = 0

    4.2.2. Ecuaciones de Recurrencias no Homogéneas

    T (n) = C1 T ( n-1 ) + C2 T ( n-2 ) + ... + Ck T ( n-k ) + b p(n)

    Dividir y reorganizar

    Ej. : T (n) = 2 T (n-1) +

    T (n) - 2 T (n) =

    tn - 2 tn-1 =

    3 tn - 6 tn-1 = * 3 multiplico por tres porque quiero eliminar el término

    t n+1 - 2 tn = en la original n ! n + 1 independiente , ahora resto 2-1.

    t n+1 + 5 tn + 6 tn-1 = 0 Ecuación homogénea equivalente

    x² - 5x + 6 = 0

    r1 = 2

    r2 = 3

    T (n) = 2 T ( n-1 ) ! ecuación homogénea de la del enunciado.

    tn - 2 tn-1 = 0

    ( x - 2 ) = 0

    Ej. :

    tn - 2 tn-1 = ( n+5 )

    9 tn - 18 tn-1 = ( n+5 ) * 9

    tn+2 - 2 tn+1 = ( n + 7 )3 n ! n + 2 Sumo las tres

    - 6 tn+1 +12 tn = - 6 ( n + 6 ) n ! n+1 + - 6

    tn+2 - 8 tn+1 + 12 tn - 18 tn-1 = 0

    x³ - 8x² + 21 x - 18 = 0 ( n+5 ) 3 ! ( x - 3 )² = 0

    ( x-2 ) ( x-3 )² = 0 T (n) = 2 T ( n-1 ) ! ( x-2 ) = 0

    La ecuación característica

    Ej. : T (n) = 2 T ( n-1 ) + n No homogénea , termino independiente = 0 , nos falta b

    T (n) = 2 T ( n-1 ) + n 1

    tn - 2 tn-1 + = n b = 1 p (n) = n d = 1

    Ecuación característica ( x-2 ) ( x-1 )²

    T (n) = C1 + C2 + C3 n = C1 + C2 + C3 n = O ( )

    Ej. : Torres de Hannoi

    Procedimiento MoverTorres ( n , a , b , c )

    Si n > 0 entonces

    MoverTorres ( n-1 , a , b , c ) ; escribir es constante = 1

    Escribir ( ` Paso un disco de ` , a , `a' , c ) ;

    MoverTorres ( n-1 , b , a , c ) ;

    Fin

    T (n) = 2 T ( n-1 ) + 1

    tn - 2 tn-1 = 1 (1 ) p (n) = 1 b = 1 d = 0

    ( x-2 ) ( x-1 ) = 0

    T (n) = C1 2 + C2 1 = C1 2 + C2 = O ( 2 ) Ineficiente algoritmo

    10-11-97

    T (n) = 2 T ( n-1 ) + n

    tn - 2 tn-1 = c (1 ) b p (n)

    ( x-2 ) ( x-1 )² = 0

    T (n) = C1 2 + C2 1 + C3 n 1 = C1 2 + C2 + C3 n = O (2 )

    Si tenemos ahora

    a1 tn + a2 tn-1 + a3 tn-2 + ... + an tn-n = b1 p1 (n) + b2 p2(n) + ... + bm pm (n)

    Ec. característica ( a1 x + a2 x + ... + ak ) ( x-b1 ) ( x-b2 ) ... ( x - bm ) = 0

    Parte homogénea di = grado polinomio Pi

    Ej. : T (n) = 2 T ( n-1 ) + n + 2 sustituyo T ( 1 , 2 y 3 )

    tn - 2 tn-1 = n + 2 b ( n ) d1 = 1

    polinomio = 1 d2 = 0

    1 n +2 1 exp = 1

    Ec. Característica ( x-2 ) ( x-1 )² ( x-2 ) = 0

    T (n) = C1 2 + C2 n 2 + C3 1 + C4 n 1 = C1 2 + C2 n 2 + C3 + C4 n

    Para los coeficientes sustituyo en la ecuación inicial

    T (0) = 0 ; T (1) = 3 ; T (2) = 12 ; T (3) = 35 ( 4 incógnitas , 4 valores de t ).

    T (0) = C1 + + C3 = 0 C1 = 2

    T (1) = 2 C1 + 2 C2 + C3 + C4 = 3 C2 = 1

    T (2) = 4 C1 + 8 C2 + C3 + 2 C4 = 12 C3 = -2

    T (3) = 8 C1 + 24 C2 + C3 + 3 C4 = 35 C4 = -1

    T (n) = 2 + n 2 - 2 - n = O ( n 2 )

    4.2.3. Cambio de Variable

    Transformar las ecuaciones divide y vence al tipo anterior

    T (n) = T ( n/2 ) Se realiza mediante un cambio de variable.

    Ej. : T (n) = 4 T( n/2 ) + n n = 2

    T ( 2 ) = 4 T ( 2 ) + 2

    tk = T ( 2 )

    tk = 4 tk-1 + 2

    tk - 4 tk-1 = 2 1

    Ecuación característica ( k-4 ) ( k-2 ) = 0

    T (k) = C1 4 + C2 2 4 = ( 2² ) = ( 2 )² = n²

    T (n) = C1 n² + C2 n = O ( n² | n = 2 ) Notación asintótica condicional , solo cuando

    n sea potencia de 2.

    La complejidad de un algoritmo siempre crece ( no tiene derivada negativa , pendiente positiva ) , por eso aunque solo sepamos para 2 será más o menos una parábola , es decir n².

    Ej. : T (n) = 4 T (n/2 ) + n² n = 2 n² = ( 2 ) ² = ( 2² ) = 4

    t ( 2 ) = 4 2 +4 log2 n = k

    tk = 4 tk-1 + 4

    tk - 4 tk-1 = 4 1

    ( x-4 ) ( x-4 ) = 0

    T (k) = C1 4 + C2 k 4

    T (n) = C1 n² + C2 n² log2 n = O ( n² log2 n | n = 2 )

    Ej : T (n) = 2 ( n/2 ) + n log n n = 2 n² = ( 2 )² = ( 2 ² )

    tk = 2 tk-1 + 2 k log n = k

    tk - 2 tk-1 = 2 k

    ( x-2 ) ( x-2 )² = 0

    t (k) = C1 2 + C2 k 2 + C3 k² 2

    T (n) = C1 n + C2 log n + C3 k log² n n = 0 ( n log² n | n = 2 )

    Ej. : T (n) = 3 T (n/2) + 5 2 n = 2

    tk = 3 tk-1 + 5 2

    tk - 3 tk-1 = 5 2 b = 2 pk = 5 d =0

    ( x-3 ) ( x-2 ) = 0

    T (k) = C1 3 + C2 2 3 a = b

    T (n) = C1 n + C2 n = O ( n | n = 2 )

    log a = log b ; log b log a = log b loga ; 3 = n

    DISEÑO DE ALGORITMOS

    TEMA 5 : FUERZA BRUTA

    Antitécnica , no hacer.

    Diseñamos el algoritmo sin pensar , sin aplicar ninguna técnica.

    Ej. : Cálculo del determinante de una matriz.

    a11 a12 a13 ... a1n

    a21 a22 a23 ... a1n

    ... ... ... ...

    an1 an2 an3 ... ann

    A nxn An

    Det (A) =  ( -1 ) aij Det ( A1j )

    Si A nxn n det de n-1 por n-1

    Determinante ( A : array [ 1..n , 1..n ] , n : entero ) : entero

    Si n = 2 Entonces

    devolver A [ 1,1 ] * A [ 2,2 ] - A [1,2 ] * A [ 2,1 ]

    sino

    s = -1

    Desde j!1 hasta n hacer /* Calcula la suma una vez positivo y otra negativa */

    m ! 1

    Desde k ! 2 hasta n hacer / * filas * /

    p ! 1

    Desde l ! i hasta n hacer / * columnas * /

    Si l < > j entonces /* menos la columna j */

    B [ m , p ] ! A [ k , l ] ; p++ construimos la matriz B

    Fin_si p - filas B n-1

    Fin_desde m - columnas n-1

    m++

    Fin_desde

    Suma = S * A [ 1 , j ] * Det ( B , n-1 ) ! lio , además del problema de

    S ! -S ; memoria , usamos muchas submatrices

    Fin_desde

    Devolver suma

    Fin

    Análisis

    n = 2 1 comprobación , 2 multiplicaciones , 1 asignación , 1 resta - constante

    n > 2 , bucles :

    • Más interno comparación y dos operaciones , n iteraciones.

    • Central , n * ( n-1 ). multiplicación

    • Más externo n T (n-1) + (n-1) n n + C2 n

    n llamadas recursivas al problema

    T (n) = n T ( n-1 ) + n³ - n² + C2 n

    Suponemos Det ( A , 5 )

    5 n

    Determinante B , cinco llamadas a una matriz de 4 X X

    4 n-1

    Determinante ( B , 3 ) X X n!

    3 ...

    Det ( B , 2 ) X X

    cte. cte.

    T (n) = n T (n-1 ) + n³ - n² + C2 n

    T (n) " n T ( n-1 ) + n³ Por expansión de recurrencias

    T (n-1) = n-1 T (n-2) + ( n-1 )³

    T (n-2) = n-2 T (n-3) + ( n-2 )³

    T (n) " n T (n-1) + n³ = n (n-1) T (n-2) + n (n-1) + n³ =

    = n (n-1) (n-2) T (n-3) + n (n-1) (n-2)³ + n ( n-1 ) n³ =

    = n (n-1) ... ( n - k ) T ( n - k ) + " n n!

    + n ( k-1 ) ... ( n-k+1 )³ +

    ...

    n = 20 ! tiempo = 20 millones de años . INEFICIENTE

    Ej. : Serie de Fibonacci ( suma los anteriores )

    1 1 2 3 5 8 13 21 34 ...

    Fibonacci (n) : entero

    Si n = = 1 o n = = 2 Entonces

    Devolver 1

    Sino Fib (n)

    Devolver Fibonacci ( n-1 ) + Fibonacci ( n-2 ) Fib (n-1) Fib (n-2)

    Finsi

    T (n) = 2 ( T n-1 ) O ( [ ( 1 + "5 ) / 2 ] exp n ) Fib(n-2) Fib(n-3) Fib(n-3) Fib(n-4)

    Una forma más sencilla :

    Fib (n) : Entero

    Si n " 2 Entonces

    a-b ! 1

    cont ! 2

    repetir

    t ! a + b

    a ! b

    b ! t

    hasta cont = = n

    17-11-97

    TEMA 6 : DIVIDE Y VENCE

  • Torres de Hanoi

  • No puede haber un disco de mayor tamaño sobre otro de menor tamaño.

    Pasar los discos de la barra A a la Barra B ( para ello se usa la barra C como auxiliar ).

    No se pueden mover dos discos a la vez

    Torres de Hanoi

    Mover Torre ( n , A , B , C : entero )

    Inicio

    Si n > 0 Entonces

    Mover Torre ( n-1 , A , C , B ) ;

    Escribir ( “ Mover un disco de “ , A “a” , B ) ;

    Mover Torre ( n-1 , B

    Fin_si

    Fin

  • Multiplicación de Números Grandes

  • X e Y.

    X n / 2 n / 2 Operaciones : número dígitos X * número de dígitos de Y

    A B T (n) = n²

    Y n / 2 n / 2

    C D

    X = A 2 + B

    Y = C 2 + D X Y = A C 2 + ( AD + CB ) 2 + BD

    T (n) = T ( n/2 ) + c n = O ( n / 2 )

    X Y = A * C 2 + [ ( A - B ) ( D - C ) + AC + BD ] *2 + BD

    Hemos descompuesto el problema en tres subproblemas de tamaño medio más la suma.

    T (n) = 3 T ( n / 2 ) + c n = O ( n ) = O ( n )

    Mult ( x , y , n : enteros ) : enteros

    Var

    S , m1 , m2 , m3 , A , B , C , D : enteros

    Inicio

    S ! signo ( x ) * signo ( y ) /* quitar el signo */

    x ! abs ( x ) /* quitar el signo de x e y */

    y ! abs ( y )

    Si n = = 1 Entonces /* Cantidad de dígitos en número es 1 */

    Si x = = 1 && y = = 1 Entonces

    Devolver (S)

    Sino

    Devolver (0)

    Sino

    A = x >> n / 2

    B = x % exp ( 2 , n / 2 ) /* % ! módulo */

    C = y >> n / 2

    D = y % exp ( 2 , n / 2 )

    m1 = Mult ( A , C , n / 2 ) /* T ( n / 2 ) */

    m2 = Mult ( A-B , D-C , n / 2 ) /* T ( n / 2 ) */

    m3 = Mult ( B , D , n / 2 ) /* T ( n / 2 ) */

    Devolver ( S * ( m1 << n + m1 + m2 + m3 << n / 2 + m3 ) )

    Fin_si

    Fin

  • Elaboración Calendario Deportivo

  • n equipos ( EQ ) , tienen que jugar todos contra todos en el menor número de días posibles

    Días

    EQ 1 2 3 4 5 6 7

    1

    2

    3

    4

    5

    6

    7

    8

    La casilla 5,5 indica que juega con el equipo 5 el día 5 , en esa columna ya no aparecerá más el 5.

    Usamos n-1 , un equipo juega un partido diario.

    Se podría dividir en cuatro partes

    Días

    EQ 1 2 3 4 5 6 7

    1 2 3 4 5 8 7 6 1 2 3 1

    2 1 4 3 6 5 8 7 1 2 3 4 1 2

    3 4 1 2 7 6 5 8 2 1 4 3 2 1

    4 3 2 1 8 7 6 5 3 4 1 2 Sencillo , igual

    5 6 7 8 1 2 3 4 4 3 2 1 bloque inferior

    6 5 8 7 2 3 4 1

    7 8 5 6 3 4 1 2 1 2 3 1

    8 7 6 5 4 1 2 3 5 6 7 8 5 6

    Permutaciones 6 5 8 7 6 5

    sin repetición 7 8 5 6

    8 7 6 5

    Estas ya da igual , una vez

    rellenado uno relleno el otro

    Un número impar es más complicado.

  • Esquema General

  • DV ( x )

    Si x es pequeño o simple entonces /* ver si es simple , si lo es solución directa */

    devolver ( solución ( x ) )

    sino

    descomponer ( x , x1 , x2 , ... , xn ) x en n partes /* dividir de alguna forma */

    desde i ! 1 hasta n hacer

    yi ! DV ( xi ) /* reaplicamos el esquema para buscar una solución parcial

    Fin desde

    Recombinar ( y1 , y2 , y3 , ... , yn )

    Devolver ( y )

    Fin si

    La complejidad es el número de divisiones de n y el tamaño de cada parte , la combinación y recombinación suele ser lineal.

    Problemas

    • Que es pequeño - cuando descomponemos o dividimos ( cuando es simple ).

    • Merece la pena hacer la recursión , umbral de no seguir haciendo recursión.

    A veces es mejor dividir una sola vez.

  • Calculo del Umbral

  • Por ejemplo en lugar de multiplicar dos números de n dígitos sabemos hacerlo con tres de n / 2.

    n/2

    n n/2

    n/2

    Por fuerza Bruta la complejidad es n² , TB (n) = n²

    Que ahorro haciendo una división , tres multiplicaciones y una recombinación.

    lineal ( descomposición y recombinación )

    TA (n) = 3 TB ( n/2 ) + cn = 3 ( n/2 )² = 3/4 n² + cn es un 25% de n²

    Algoritmo ( una sola división )

    Hemos ganado un 25% y algo lineal = 20%

    Si hacemos recursividad en lugar de pararme la primera vez.

    TR - recursivo

    TR (n) = 3 TR ( n/2 ) + cn = O ( n ) ; Ecuaciones recursivas n = 2 lo realizamos por Expansión de recurrencias o Cambio de variable.

    Para n muy grandes

    Si n = = ? entonces solucionar

    24-11-97

  • Búsqueda Binaria

  • Búsqueda Binaria ( T : array [ 1..n ] de Elementos , x : elemento ) : entero

    i ! 1 ;

    j ! 1 ;

    Si i = = j entonces devolver i

    k ! ( i + j ) ;

    Si x < T [k] entonces devolver Búsqueda Binaria ( T [ i .. k + 1 ] , x )

    Sino

    Devolver Búsqueda Binaria ( T [ k .. j ] , x )

    T (n) = T ( n/2 ) + cte. ! complejidad = O ( log n )

    Una desventaja es que es recursivo , hay que intentar que sea iterativo.

    Búsqueda Binaria ( T : array [ 1..n ] de elementos ; x : elemento ) : entero

    i ! 1 ;

    j ! 1 ;

    mientras i < j hacer

    k ! ( i + j + 1 ) div 2

    Si x < T [k] entonces j ! k - 1

    Sino

    i ! k + 1

    fin mientras

    Si T [k] = = x entonces sino devolver -1

    Tiene complejidad parecida a la anterior , un poco menor , usa menos memoria al no ser recursivo , como mucho las divisiones del array.

  • Selección del Elemento K-èsimo

  • Tenemos un array desordenado

    de n elementos

    nos interesa saber que elementos estarían en la posición k - ésima si estuviera ordenada ( para la mediana ).

    Parecido a la Búsqueda Binaria , tratamos de quitar el máximo de elementos del array del medio.

    T 10 5 11 -1 3 14 18 6 7 20

    Elemento mediana cumple :

    { # { i " [ 1..n ] / T [ i ] < m } < n/2

    " { # { i " [ 1..n ] / T [ i ] " m } " n/2

    porque la mediana se puede repetir

    Tomamos un elemento al azar , pivote , comprobamos cuantos elementos menores que él hay ( esto es recorriendo el array ) . 5

    Luego los que son menores o igual al pivote ( incluye el pivote ) , 6 . El pivote esta en la posición 6 si estuviera ordenado , sería la mediana . Suponemos que esta en el lugar 5 , entonces cogemos un array con los menores que él.

    5 -1 3 6 7

    nuevo ; menores 2 , menor o igual a él 3 ; mediana en T [ 5 ]

    pivote posición 5

    Buscamos en los elementos mayores al pivote

    6 7 Mediana en T [ 2 ] si estuviera ordenada ( en teoría no lo vemos ).

    Pivote menores 0 , menor o igual 1 ; mediana

    En lugar de la mediana elemento k - ésimo

    K - ésimo { # { i " [ 1..n ] / T [ i ] < m } < k

    " { # { i " [ 1..n ] / T [ i ] " m } " k

    Ej. : k = 8

    10 -1 20 7 18 11 5 14 6 3

    pivote , menor 5 menor o igual 6 , k = 8 , ni el pivote ni los menores.

    20 18 11 14

    pivote , menor 3 menor o igual 4 ; k = 8 , será el lugar segundo , no es el pivote ni los mayores.

    18 11 14

    nuevo pivote , menor 2 menor o igual 3 ; k = 8 sigue en el segundo

    11 14

    0 1 k = 2 14

    Cuando el array sea pequeño puede ordenarse. El algoritmo quedaría :

    Selección ( T : array [ 1..n ] de enteros , k : enteros ) : enteros

    Si n es pequeño entonces

    Ordenar ( T ) ;

    Devolver T [ n ] ;

    Sino

    p ! T [ 1 ] ;

    u ! 0 ;

    v ! 0 ;

    desde j ! 1 hasta n hacer

    Si T [ j ] < p entonces u ++

    Si T [ j ] " p entonces v ++

    Fin desde

    Si k " u entonces

    j ! 1

    desde i ! 1 hasta n hacer

    Si T [ i ]< p entonces

    U [ j ] ! T [i ] ; j ++

    Fin si

    Fin desde

    devolver selección ( U [ 1.. n ] , k )

    fin si

    Si k " v entonces

    devolver p

    sino

    j ! 1

    desde i ! 1 hasta n hacer

    Si T [ i ] > p entonces

    V [ j ] ! T [ i ] ; j ++

    Fin desde

    devolver selección ( V [ 1 .. n-v ] , k-v )

    fin si

    fin

  • Multiplicación de Matrices

  • A nxn B nxn C nxn

    X =

    n

    Cada elemento C i,j =  a i,k b k,j

    k = 1

    La complejidad n multiplicaciones y sumas , n x n x n = n³ por fuerza bruta . Parecido a Multiplicaciones de Grandes Números.

    Suponemos n = 2

    Dividimos las matrices en 4 partes

    Dos matrices de n/2 8 ( n/2 )³ + 4 sumas ; 4 x 2 ( n/2 )³ = 8 ( n³/8 ) = n³

    sumas = n² ; no mejoro nada.

    Manipulamos los productos intermedios . Si definimos :

    M1 = ( A21 + A22 - A11 ) x ( B22 - B12 + B11 )

    M2 = A11 x B11

    M3= A11 x B21

    M4 = ( A11 - A21 ) x ( B22 - B12 )

    M5 = ( A21 + A22 ) x ( B12 - B11 )

    M6 = ( A12 - A21 + A11 - A22 ) x B22

    M7 = A22 x ( B11 + B22 - B12 - B21 )

    C quedara

    7 ( n/2 )³ + 24 n² ( 24 sumas )

    Si en lugar de hacer las multiplicaciones directamente las hacemos recursivas.

    A B C

    X =

    T (n) = 8 T ( n/2 ) + 4 n² n³

    T (n) = 7 T ( n/2 ) + 24 n² n

  • Intercambio de Elementos en un Vector

  • A B C D E F G H I J K L M

    Trasladar sin vectores auxiliares

    J K L M A B C D E F G H I

    Intercambiar subvectores , elemento a elemento , usamos como mucho una posición auxiliar.

    O ( n log n )

    TEMA 7 : PARAMETROS ACUMULADORES

  • Parámetros Acumuladores y el Diseño de Algoritmos

  • Analizar el problema o algoritmo y deducir el número de llamadas que se hace en la recursión por medio de los parámetros.

    Fib ( n : entero ) : entero

    Si n = = 1 || n = = 2 entonces

    Devolver 1

    Sino

    Devolver Fib ( n-1 ) + Fib ( n-2 )

    Fin

    !

    FibPar ( n , y z = entero ) : entero

    Si n = = 0 entonces devolver y

    Sino devolver FibPAr ( n-1 , z , y + z )

    Fin

    La Llamada original :

    Fib ( n ) : entero

    devolver FiBPar ( n , 0 , 1 )

    Fib (5) ! FibPar (5 , 0 , 1) ! FibPar (4 , 1 , 1) ! FibPar (3 , 1 , 2) ! FibPar (2 , 2 , 3 )

    n = 0 no sumo la 2º y 3º posición 0 + 1 = 1

    ! FibPar ( 1 , 3 , 5 ) ! FibPar ( 0 , 5 , 8 ) ! 5

    Las cosas se calculan en la llamada y los resultados se acumulan en los parámetros.

    En el algoritmo anterior.

    Fib (5)

    Fib (4) Fib (3) El cálculo no se realiza hasta devolver las llamadas

    ...

    En FibPar la complejidad es lineal , n.

    1-12-97

    TEMA 8 : ALGORITMOS VORACES

    Problemas con una o varias soluciones , buscaremos la óptima ( puede no funcionar ).

    Ej. : Máquina de cambio automático de monedas , utilizando la mínima cantidad de monedas posibles y la máquina tiene monedas ilimitadas.

    Monedas : 1 5 25 50 100

    Devolver 288 ptas.

    Primero las monedas de 100 luego vamos bajando

    288-100 = 188

    188-100 = 88 resultado positivo vuelvo a restar una de 100

    88-100 = negativo , paso a las de 50

    88-50 = 38

    38-50 = negativo

    38-25 = 13

    13-5 = 8

    8-5 = 3

    3-1 = 2

    2-1 = 1

    1-1 = 0

    9 monedas

    Estrategia Voraz , porque vamos de lo más grande a los más pequeño de lo que podemos aplicar.

    Es más sencilla no hay algoritmos recursivos , la cuestión es elegir.

    Hay que determinar los Elementos Fundamentales para aplicar la estrategia :

  • Conjunto de candidatos ( monedas disponibles ).

  • Conjunto de candidatos seleccionados , tiene un inconveniente la acoplación de los tipos de datos ( conjunto ) a los lenguajes de programación ( monedas utilizadas en cada momento ).

  • Función que compruebe si un conjunto de candidatos seleccionados es ya la solución.

  • Función que determine si un conjunto de candidatos puede formar parte de la solución ( del conjunto de candidatos lo pasamos al conjunto de candidatos seleccionados , queremos saber que el último seleccionado no lo estropea ) . Es un conjunto de restricciones.

  • Función que seleccione al siguiente candidato.

  • Función que expresa un objetivo a optimizar ( número de monedas mínimo ).

  • Lo eficiente de este algoritmo es que no hay vuelta atrás , o incluimos el candidato o no lo incluimos y ya no nos ocupamos de él.

    8.1. Esquema General

    Voraz ( C : conjunto ) : conjunto partimos de C

    Var ( Candidatos ) S ( Solución )

    S : conjunto ; x y x x

    S ! { 0 }

    Mientras ( ( No ( Solución ( S ) ) ) y ( C < > { 0 } )

    X ! seleccionar ( C )

    C ! C \ { X } /* si no lo cogemos lo eliminamos de los candidatos */

    Si ( factible ( S " { X } ) ) Entonces

    S ! S " { X }

    Fin mientras

    Si solución ( S ) Entonces

    Devolver S

    Sino

    Escribir ( “ No hay solución “ )

    Fin

    El mientras es el bucle voraz , normalmente solo hay uno.

    8.2. Arboles de Recubrimiento Mínimos

    Yo tengo un grafo dirigido G formado por un conjunto de nodos y uno de aristas , quiero encontrar el número mínimo de aristas que unan todos los nodos , que formen un árbol y la suma del peso de todas las aristas sea un valor mínimo.

    G < N , A > , sin ciclos y no más de tres aristas por nodos.

    Hacemos una lista de las aristas ordenadas de menor a mayor.

    { 1,2 } , { 4,3 } , { 1,4 } , { 2,6 } , { 1,3 } , { 4,5 } , { 5,7 } , { 7,6 } , { 2,3 } , {3,6 } , { 3,5 } , { 3,7 }.

    Solución = número de aristas = número de nodos - 1 # S = n-1 # - elementos de S.

    Factible ( S " {x ,y} ) = no haya ciclos = { x ,y } no conecten nodos ya conectados , en cada paso del algoritmo determinado que nodos están unidas entre si ( nodos conexos ).

    La función de selección es tomar la siguiente arista de menor peso.

    Optimización u objetivo , la suma del peso de las aristas sea mínimo , objetivo = min (  peso { x , y }.

    En las componentes conexas tendremos cada nodo al principio CC = { { 1 } , { 2 } , { 3 } , { 4 } , { 5 } , { 6 } , { 7 } }.

    Cogemos la primera arista { 1,2 }.

    CC = { { 1,2 } , { 3 } , { 4 } , { 5 } , { 6 } , { 7 } }

    Arista { 3,4 }.

    CC = { { 1,2 } , { 3,4 } , { 5 } , { 6 } , { 7 } }

    Arista { 1,4 }.

    CC = { { 1,2,3,4 } , { 5 } , { 6 } , { 7 } }

    Arista { 2,6 }

    CC = { { 1,2,3,4,7 } , { 5 } , { 6 } }

    Arista { 4,5 }

    CC = { { 1,2,3,4,7,5 } , { 6 } }

    Arista { 6,7 }

    CC = { { 1,2,3,4,7,5,6 } } ya tenemos el árbol

    2

    1 6

    3 El árbol no es único

    4 7

    5

    7

    6

    2

    4

    3 5

    Este es el método KRUSKAL

    Kruskal ( G = < N , A > : grafo ; A : conjunto ) : Conjunto

    Inicio

    Ordenar ( A ) ;

    n ! # N ; /* número de nodos */

    T ! { 0 } ; /* Conjunto solución */

    Inicializar _n_conjunto ( ) ; /* Componentes conexas , uno por nodo */

    Repetir /* bucle voraz */

    { n , v } ! seleccionar ( A ) ; /* siguiente Candidato */

    ncomp ! ComponenteConexa { n }

    vcomp ! ComponenteConexa { v }

    Si ( ncomp != vcomp ) entonces

    Unir ( ncomp , vcomp ) /* son distintos no están unidos */

    T ! T " { { n , v } } /* uno los nodos */

    Fin si

    Hasta que ( # T = = n-1 )

    Devolver T

    Fin

    8.2.1. Arboles de Recubrimiento Mínimo ( Prim )

    Kruskal construye varios árboles hasta llegar al último ( bosque ).

    Prim escoge las aristas en orden , partiendo de un nodo ( el primero generalmente ) , siempre tenemos un único árbol.

    G = < N , A > B

    B - conjunto de nodos conectados en un momento dado.

    El siguiente paso es mirar el resto de las aristas que van de los nodos iniciales en B hacia el resto de nodos ( otros caminos ) , no considero las aristas que unen entre si a las no B.

    Que arista escojo , la menor ( mínimo ).

    Ej. :

    El desarrollo

    Cogemos una arista de menor peso { 1,2 } , B es ahora el nodo 1 y 2 más la arista que los une.

    Todos los nodos unidos con 1 y con 2 , escojo la arista de menor peso.

    { 1,2 } , { 1,3 } , { 3,7 } , { 3,4 } , { 4,5 } , { 3,6 }

    Arbol no binario

    Peso = 1

    2

    1

    3

    4 6 7

    5

    Prim ( L [ 1..n , 1..n ] ) : conjunto

    Inicio

    T ! { 0 }

    Desde i ! z hasta n hacer

    Cercano [ i ] ! 1

    Maindist [ i ] ! L [ i , 1 ]

    Fin desde

    Repetir

    Min ! MAXINT

    Desde j ! 2 hasta n

    Si ( mindist [ j ] " 0 y ( mindist [ j ] < min ) entonces

    Min ! mindist [ j ]

    K ! j

    Fin si

    Fin desde

    T ! T " { { k , cercano [ k ] } }

    Mindist ! [ k ] ! -1

    Desde j ! 2 hasta n hacer

    Si [ k,j ] < mindist [ j ] entonces

    Mindist [ j ] ! L [ k,j ]

    Cercano [ j ] ! k

    Finsi

    Fin desde

    Fin repetir

    Devolver T

    Fin

    Cercano - nodos que no están en B que esta más cerca

    Mindist [ j ] - longitud o distancia que va desde j hasta cercano de j.

    Cercano distmin

    L [ i,j ] = dist { i,j } L [ i , i ] = 0

    15-12-97

    Ej.: Kruskal en C

    # define N 10

    int encontrar ( int elem , int conjvert [ ] )

    { return ( conjvert [ elem ] ) } ;

    void mezclar ( int compu ; int compv , int conjvert [ ] ) {

    int x ;

    for ( conjvert [ x ] ; x = 0 ; x < N ; x++ )

    if ( conjvert [ x ] = = comp v ) conjvert [ x ] = compu ;

    } ;

    void inicializar ( int comp , int elem , int conjvert [ ] )

    { conjvert [ elem ] = comp } ;

    void Kruskal ( int ariini [ ] , int arifin [ ] , int aricoste [ ] , int Tini [ ] , int Tfin [ ] );

    {

    int conjvert [ N ] , i , min = 0 , n , v , ucomp , vcomp , i = 0

    ordenar ( ariini , arifin , aricoste ) ;

    for ( i = 0 ; i < N , i++ ) { inicializar ( i , 1 , conjvert )

    do {

    u = ariini [ min ] ; v = arifin [ min ] ;

    min ++ ;

    ucomp = encontrar ( u , conjvert ) ;

    ucomp = encontrar ( v , conjvert ) ;

    if ( ucomp ! = vcomp )

    { mezclar ( ucomp , vcomp , conjvert ) ;

    Tini [ t ] = u ; Tfin [ t++ ] = v } ;

    while ( t < N ) ;

    } ;

    Estructura de Datos :

    • Arrays paralelos para el conjunto de aristas , tres arrays :

    ariini - nodo desde el que se parte.

    arifin - nodo al que llega correspondiente.

    aricoste - peso

    • Las componentes conexas son conjuntos.

    Conjvert - de tamaño N , en cada posición del array hay nodo , en esa posición se indica la componente conexa

    5

    Al inicializar cada nodo pertenece a su propia componente conexa

    Conjvert [ elem ] = comp ;

    Primero ordenamos.

    Inicializamos las componentes conexas.

    Algoritmo voraz do - while

    t - índice que recorre el array Tini indicando que arista voy a coger , donde va Tfin.

    min - arista de mínimo peso.

    Mezclar - unión de conjuntos.

    1 2 3 4

    1 3 1 2 3 4

    1 1

    2 1 y 3 pertenecen a la misma componente conexa.

    8.3. Dijkstra

    Caminos más cortos entre nodos de un grafo.

    Tenemos un grado dirigido , camino más corto entre un nodo y el resto de los nodos.

    1

    10 50

    30

    5 100 2

    20

    10 5

    4 3

    50

    Conjunto de candidatos - vamos a ir eligiendo los nodos , de los que sabemos cual es el camino más corto.

    C 2,3,4,5

    S nodos con camino más corto conocido.

    • Factible.

    • Solución - C = {  }.

    • Objetivo ( ).

    • Siguiente ( ) - busca el nodo de camino más corto usando ese nodo ( esta elegido porque tiene el camino más corto ).

    C D

    2 3 4 5

    2 , 3 , 4 , 5 50 30 100 10 Caminos directos

    2 3 4 5

    2 , 3 , 4 50 30 20 10 Vemos si pasando por 5 reducimos los

    anteriores.

    2 3 4 5

    2 , 3 40 30 20 10 2 ! 4 ! 5 ! ; C - { 3 } , porque es el

    de camino más pequeño.

    2 3 4 5

    3 35 30 20 10 Este array no indica por donde pasa ,

    para ello usamos un array auxiliar P.

    Cada vez que paso por otro nodo lo guardo , en principio todos apuntan a 1 . En el primer paso el 4 pasa por el 5.

    P P P P

    1 2 1 2 4 2 4 2

    1 3 1 3 1 3 1 3

    1 4 5 4 5 4 5 4

    1 5 1 5 1 5 2 5

    Para sacar la información ( 1 , 2 ) P indica el paso siguiente es el 3 2 3 luego

    con el 1 2 3 1 camino más corto.

    El camino más corto entre el nodo k y 1 esta formado solo por caminos mínimos , sino es directo .

    k 1 de j a 1 es un camino mínimo . No me

    10 10 me preocupo por otros camino , solo

    j j a k porque es mínimo.

    Dijkstra ( L [ 1..n , 1..n ] : array [ 2..n ] )

    C ! { 2..n }

    desde i ! 2 hasta n ; D [ i ] ! L [ i ]

    repetir n-2 veces

    v ! mínimo ( D ) ; /* busco el elemento mínimo de D que esté. en C */

    C ! C \ { v }; /* elimino el elemento de C */

    para cada W " C hacer

    Si D [ W ] > D [ v ] + L [ v , W ] entonces

    D [ W ] ! D [ v ] + L [ v , W ]

    P [ W ] ! v

    fin si

    fin para

    fin repetir

    Devolver D

    Fin.

    El grafo esta en L que es de adyacencia , el peso esta en L [ i , j ] , L [ i , j ] " L [ j , i ],

    L [ i , i ] = 0 Diagonal

    L [ i , j ] = " " { i , j }

    # Define N 5

    void Dijstra ( int L [ n ] [ ] , int D [ ] , int P [ ] )

    { int C [ N + 1 ] , i , v , w , minc = MAXINT , veces = N - 2 ;

    for ( i = 2 ; i < = N ; i ++ ) C [ i ] = 1 ;

    for ( i = 2 ; i < = N , i ++ ) D [ i ] = L [ 1 ] [ i ] ;

    do { minc = MAXINT

    for ( i = 2 ; i < N ; i ++ )

    if ( C [ i ] && ( D [ i ] < minc ) ) /* si es 0 no esta en C */

    { v = i ; min = D [ i ] ; }

    C = [ v ] ;

    for ( w = 2 ; w < = N ; w ++ )

    if [ w ] && ( D [ w ] > D [ v ] + L [ v ] [ w ] )

    { D [ w ] = D [ v ] + L [ v ] [ w ] ;

    P [ w ] = v ;

    } ;

    while ( -- veces ) ;

    }

    8.4. Mochila

    Tenemos una mochila de capacidad C , se puede llenar con objetos que tienen un cierto valor o beneficio , llenar la mochila con el máximo de beneficio.

    Puede no haber límite de objetos.

    Primero cogemos los objetos menos pesados y que valgan más , la solución puede ser la solución no optima , pero el tiempo es rápido.

    8.5. Planificador de Tareas

    Asignar recursos

    T1 = 5 ; T2 = 10 ; T3 = 3

    El tiempo de espera , hasta realizar las tres tareas , sea el mínimo posible.

    5 + 5 espera + 10 + 5 espera + 10 espera + 3 = 38

    La orden de ejecución de tareas minimiza los tiempos de espera

    132 - 5 + 5 espera + 3 + 5 + 3 + 10 = 31

    213 - 10 + 10 + 5 + 10 + 5 + 3 = 41

    231 - 10 + 10 + 3 + 10 + 3 + 5 = 37

    312 - 3 + 3 + 5 + 3 +5 + 10 = 29 es el mejor.

    Primero las tareas pequeñas , es voraz una vez elija no se vuelve a utilizar

    8.5.1. Tareas con Plazo

    Ahora además de su tiempo tienen un plazo para realizar las tareas.

    Ej. : T1 = 1 T2 = 1 T3 = 1 T4 = 1

    B1 = 50 B2 = 10 B3 = 15 B4 = 30 Beneficio de realizarlo antes del plazo

    P1 = 2 P2 = 1 P3 = 2 P4 = 1

    Conjunto de tareas que se pueden realizar y en que orden de manera que se maximi-

    ce el beneficio.

    Subconjuntos Una tarea Dos tareas

    1 50 2,1 60

    2 10 1,3 65

    3 15 4,1 80

    4 30 3,2 25

    4,3 45

    Primero elegir las tareas según el máximo beneficio.

    Tiempo 1 2 3 1 2 3

    1 ! 4 1

    50 50

    Ej. : T1 T2 T3 T4 T5 T6

    B 25 15 10 7 5 3

    P 3 1 1 3 1 3

    8.5.2. Solución

    T1 T2 T3

    t1 t2 t3

    t1 + ( t2 + t3 ) + ( t1 + t2 + t3 ) = espera ! minimizarlo.

    Ordenamos las tareas de menor a mayor , es lo óptimo , primero ejecuto las menores.

    Las restricciones :

    T1 T2 T3

    Plazo d1 d2 d3

    Ganancias g1 g2 g3

    t1 = t2 = t3 = 1

    NO se pueden realizar todas las tareas en su plazo , minimizo las tareas.

    Elementos Básicos

    Candidatos : Tareas

    Seleccionadas : Tareas que pueden realizarse dentro de su plazo.

    Funciones :

    Factible ( ) : La nueva tarea puede ejecutarse además de las anteriores dentro de su

    plazo.

    Solución ( ) : El número de tareas seleccionadas es igual mínimo de tareas seleccio -

    nadas es igual a Min { número de tareas , distancia , i = 1 .. n }.

    Objetivo ( ) : Maximizar la suma de las ganancias de las tareas ejecutables.

    Siguiente ( ) : Tarea de mayor ganancia no seleccionada aun.

    T1 T2 T3 T4 T5 T6

    g : 25 15 10 7 5 3

    d : 3 1 1 3 1 3

    Como mucho tres tareas ya que el plazo máximo es tres

    1 2 3

    1

    T1 ya se ejecuta ( sino por lo menos esta escogida ).

    T2 no se puede ejecutar , si desplazamos la uno

    1 2 3

    2 1

    T3 no es factible sustituirla por ninguna , la 1 y 2 ya están escogidas.

    2 1 4

    T5 plazo 1 no es posible

    T6 plazo 3 y no se pueden mover la 1 y la 4.

    Planificación ( d [ 0 .. n ] ) : array [ 1 .. k ]

    j : array [ 0 .. n ]

    Inicio

    d [ 0 ] ! j [ 0 ] ! 0

    k ! j [ 1 ] ! 1 / * 1 * /

    desde i ! 2 hasta n hacer

    r ! k / * r apunta a la primera tarea * /

    mientras d [ j [ r ] ] > max ( d [ i ] r ) hacer r -- / * 2 * /

    si d [ i ] > r " d [ j [ r ] ] " d [ i ] entonces / * 3 * /

    desde m ! k hasta r + 1 paso -1

    j [ m + 1 ] ! j [ m ]

    findesde

    j [ r + 1 ] ! i

    finsi

    findesde

    devolver j [ 1 .. k ]

    fin

    d 0 3 1 1 3 1 3 ambos arrays se empiezan a numerar por 0 y

    0 1 2 3 su primer valor 0 .

    j 0 j - array tareas

    / * 1 * / siempre elegimos la primera tarea

    k - número de tareas seleccionadas , uno al principio.

    / * 2 * / el plazo de la última tarea con la tarea que estamos mirando y r da el lugar

    0 3 1 1 3 1 3

    k

    0 1 2 3

    0 1

    r

    / * 3 * / 1 > 0 " 0 " 1 Si

    0 1 2 3

    0 2 1

    0 3 1 1 3 1 3

    k = 3

    8.6. Viajante

    Vendedor que recorre una serie de ciudades , sabe el coste entre cada dos ciudades , recorrido de manera que no se pase dos veces por la misma ciudad ( excepto si la ciudad inicial es también la final ) y coste mínimo.

    Parecido al kruskal : no formar ciclos

    En un nodo no deben incidir más de dos aristas.

    Modificar Kruskal , al decidir la siguiente arista incluyendo estas dos condiciones.

    12-1-98

    este no vale porque pasamos dos veces por el

    mismo nodo.

    Igual al árbol de recubrimiento mínimo :

  • Todos los nodos están conectados.

  • Se minimiza la suma de los pesos de las aristas.

  • No se forman ciclos ( salvo para cerrar el recorrido , el primero y el último ).

  • La diferencia

  • En un nodo no inciden más de dos aristas ( árbol especial ).

  • Grado de un nodo = número de aristas que inciden en él.

    4'. El grado de los nodos es dos , siempre coinciden dos aristas.

    ELEMENTOS BASICOS

    Candidatos =

    aristas del grafo

    Candidatos Seleccionados =

    aristas seleccionadas ( forman el itinerario ).

    Cuatro funciones :

    Factible ( ) - aristas no forman ciclos y grado de los nodos " 2.

    Solución ( ) - Todos los nodos seleccionados están conectados por el conjunto de

    aristas.

    Objetivo ( ) - ( parte voraz del algoritmo ) , minimiza la suma de los costes de

    aristas.

    Siguiente ( ) - ( Criterio para elegir al candidato ) , arista de menor coste no

    escogida todavía.

    Viajante ( G : < N , A > grafo ) : conjcertices

    grado : array [ 1 .. # N ] de enteros

    T : conjvertices

    Inicio

    n ! # N

    T ! { 0 }

    Inicializar NComponentes ( )

    desde i ! 1 hasta n hacer grado [ i ] = 0

    ordenar ( A )

    { bucle voraz }

    repetir

    [ u , v } ! Siguiente ( A )

    ucomp ! encontrar ( u )

    vcomp ! encontrar ( v )

    Si ( ucomp != vcomp ) && ( grado [ u ] < 2 ) && ( grado [ v ] < 2 ) entonces

    mezclar ( ucomp , vcomp )

    T ! T " { { u , v } }

    grado [ u ] ++

    grado [ v ] ++

    finsi

    hasta que # T == n - 1

    devolver T

    fin

    16 - 2 - 98

    TEMA 9 : PROGRAMACION DINAMICA

    La estrategia es para optimizar el número de cálculos para conseguir la información de la manera más simple posible.

    9.1. Números Combinatorios

    n n - 1 n - 1

    = +

    k k k - 1

    n n

    = = 1

    0 n

    Cogemos el método divide y vence

    NC ( n , k : enteros ) : entero

    Si k == 0 o k == n entonces

    devolver 1

    sino

    devolver NC ( n - 1 , k ) + NC ( n - 1 , k - 1 )

    finsi

    fin

    La complejidad es exponencial , si vemos las llamadas :

    6

    3

    5 5

    2 3

    4 4 4 4

    1 2 2 3

    es mejor hacer los cálculos al revés de la base hacia el resultado final , reducimos las llamadas usando el triángulo de Tartaglia.

    0 1

    0

    1 1 1 1

    0 1

    2 2 2 1 2 1

    0 1 2

    • No usamos llamadas recursivas , reorganizamos los cálculos ( es lo común en la programación dinámica ) , pero empezando por el final ( lo más sencillo ).

    • Utilizamos tablas o vectores para no realizar dos veces el mismo cálculo.

    NCD ( n , k : enteros ) : entero / * D - dinámica * /

    Var

    NCV - array [ 0 .. n ] de enteros

    Inicio

    NCV [ 0 ] ! NCV [ 1 ] ! 1

    desde i ! 1 hasta n hacer

    NCV [ i ] ! 1 / * en la posición 1 un 1 * /

    desde j ! i - 1 hasta 1 paso -1 hacer

    NCV [ j ] ! NCV [ j ] + NCV [ j - 1 ]

    findesde

    findesde

    devolver NCV [ k ]

    fin

    NCV - cada vez es una línea diferente del triángulo de Tartaglia.

    NCV

    0 1 2 3 4 5 6 6

    1 1 1 3

    NCD ( 6 , 3 )

    2ª fila del triángulo

    en la posición 2 un 1 y en la 1 la suma de 0 y 1 = 2 dejándolo en j

    1 2 1 1

    en la posición 3 un 1 y vuelvo para atrás sumando

    9.2. Fibonacci

    Si n = 1 o n = 2 entonces

    devolver 1

    sino

    devolver Fib ( n - 1 ) + Fib ( n - 2 )

    a ! 1 b ! 1

    repetir n_veces

    aux ! a + b

    a ! b

    b ! aux 1 1 2 3 5

    fin repetir

    devolver b

    9.3. Campeonato

    Tenemos dos equipos A y B , gana el que primero gane n partidos , como mucho jugaran 2n - 1 partidos , hay que descubrir la probabilidad de que A gane el torneo.

    Tenemos ciertos datos :

    Misma probabilidad en todos los partidos de que A o B gane el partido

    p = probabilidad A gane un partido cualquiera

    0 < p < 1

    q = probabilidad de que B gane un partido

    q = 1 - p

    Lo que queremos calcular

    P ( i , j ) = probabilidad de que el equipo A gane el torneo cuando le faltan i partidos por ganar y a B le faltan j partidos.

    N = 10 A ganados 2

    B ganados 5

    P ( 8 , 5 )

    d P ( n , n ) ? Antes de empezar el torneo

    P ( 0 , j ) = 1 ! a A le faltan 0 partidos por ganar

    P ( i , 0 = ) 0 ! B ha ganado los partidos necesarios

    P ( i , j ) = P * P ( i - 1 , j ) + q * P ( i , j - 1 ) / * + " o * /

    Si A gana el partido le quedan i - 1 partidos por ganar.

    Si B gana el partido le quedan j - 1 partidos por ganar.

    Divide y Vence :

    P ( i , j : enteros ) : real

    Si i == 0 entonces

    Devolver 1 , 0

    Sino

    Si j == 0 entonces

    Devolver 0 , 1

    Sino

    Devolver p * p ( i - 1 , j ) + q * p ( i , j - 1 )

    finsi

    finsi

    fin

    T ( n ) = 2 T ( n - 1 ) + C

    Ec. Característica O = ( 2 ) , la complejidad esta en las llamadas

    P ( 10 , 10 )

    P ( 9 , 10 ) P ( 10 , 9 )

    P ( 8 , 10 ) P ( 9 , 9 ) P ( 9 , 9 ) P ( 10 , 8 )

    ... cálculo repetido

    Empezamos P ( 0 , x ) y P ( x , 0 )

    Campeonato ( n : entero , p : real ) : array [ 0 .. n ] [ 0 .. n ] de reales

    Var

    p : array [ 0.. n ] [ 0 .. ] de reales

    q : real

    Inicio

    q ! 1 - p

    desde s ! 1 hasta n hacer

    P [ 0 ] [ s ] ! 1 , P [ s ] [ 0 ]! 0

    desde k ! 1 hasta s - 1 hacer

    P [ k ] [ s - k ] ! p * P [ k - 1 ] [ s - k ] + q * P [ k ] [ s - k - 1 ]

    fin desde

    fin desde

    desde s ! 1 hasta n hacer

    desde k ! 0 hasta n - s hacer

    P [ s + k ] [ n - k ] ! p * P [ s + k - 1 ] + q * P [ s + k ] [ n - k - 1 ]

    fin desde

    fin desde

    devolver P

    fin

    j s = 1 s = 2 s = 3 s = 4 s = 5

    i 0 1 2 3 4 5

    0 1 1 1 1 1 s = 1

    1 0 k =1 k =1 k =1 k =1 s = 2

    2 0 k =2 k =2 k =2 s = 3

    3 0 k =3 k =3 P(i,j) s = 4

    4 0 k =4 s = 5

    5 0 Para P ( i , j ) necesitamos

    P ( i - 1 , j ) y P ( i , j - 1 )

    Devolvemos la matriz entera

    Rellenar la matriz sin repetir cálculos :

    • Columna a columna

    • Diagonal a Diagonal , la del algoritmo empezando por el final

    s - recorre cada diagonal

    k - elemento de la diagonales que no son primera fila y columna

    los dos primeros bucles rellenan la mitad.

    Complejidad n²

    23 - 2 - 98

    9.4. Problema de la Mochila

    Lo haremos con una mochila de tamaño 17 , M = 17

    Meter objetos en la mochila :

    Los objetos no se pueden fraccionar o dividir en partes.

    A B C D E

    3 4 7 8 9 Tamaño

    4 5 10 11 13 Valores ( por unidad )

    Llenar la mochila con el máximo valor y máximo número de objetos.

    Empezamos por lo más pequeño , usamos una estructura de datos que es una array y tamaño de mochilas de 1 a 17.

    Costes - array en el que indico el valor de los objetos que meto en el array hasta ese momento.

    Mejor - indica el último elemento introducido en la mochila.

    Lo hacemos en x pasos ( x - número de objetos ) . Primero objetos de A , luego de A y B , etc. ( de pequeño a mayor ).

    • Solo A

    3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

    4 4 4 8 8 8 12 12 12 16 16 16 20 20 20 Coste

    A A A A A A A A A A A A A A A Mejor

    tam [ A ]

    En la mochila de tamaño 3 cabe un objeto de tamaño A.

    En la mochila de tamaño 6 vamos a ver lo que podemos meter considerando que la mochila de tamaño 3 esta llena de la mejor manera , le resto al tamaño de la mochila en cada momento el tam [ A ] . Solo guardo el último objeto.

    9

    6 A

    3 A 6

    A 3

    17

    A 4

    • 16 para ver con detalle , 14 ! A + mochila tamaño 11! A + mochila tamaño 8 ... , 5 A' s huecos

    • A y B , podemos mejorar sacando algún objeto A y meter uno de b o meter uno de B antes de meter un A

    3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

    4 5 5 8 9 10 12 13 14 16 17 18 20 21 22 Coste

    A B B A B B A B B A B B A B B Mejor

    Mochila de tamaño 6 , ¿ puedo meter un objeto de tamaño B ? , si y queda un hueco de 2 , ¿ Es mejor que lo que teníamos ? , no dejamos lo que teníamos.

    Mochila de tamaño 7 , ¿ puedo meter un objeto de tamaño B ? , si queda un hueco de 3 , miro la mochila de 3.

    7

    B ! 5

    3 4

    9 ! miramos la última información , actualizando

    Mochila de tamaño 7 , ¿ puedo meter un objeto de tamaño B ? , si queda un hueco de 4 , en una de cuatro miro la mochila de tamaño 4 a otro B

    8

    4 B 5

    B 4 5

    Mochila de tamaño 15 , ¿ puedo meter un B ? , si deja un hueco de 11 , valor de la mochila 11.

    15

    B 5

    11 14

    19 , no mejoro , tenía 20 no cambia

    • A , B y C

    Coste y Mejor son vectores no tablas , C es de tamaño 7 entonces la mochilas inferiores 3 , 4 , 5 , 6 quedan como están.

    3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

    4 5 5 8 10 10 12 14 15 16 18 20 20 22 24 Coste

    A B B A C B A C C A C C A C C Mejor

    Mochila de tamaño 8 , ¿ Un B ? , si igual que antes dejo lo que había antes.

    Mochila de tamaño 9 , ¿ Un B ? , si valor 10 peor que antes no cambio.

    Mochila de tamaño 10 , ¿ Un B ? , si hueco de 3 , 10 + 4 = 14 cambio.

    Mochila de tamaño 17 , ¿ Un B ? , si hueco de 10 , 10 + 14 = 24 cambio

    • A , B , C y D

    3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

    4 5 5 8 10 11 12 14 15 16 18 20 21 22 24 Coste

    A B B A C D A C C A C C D C C Mejor

    • A , B , C , D y E

    3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

    4 5 5 8 10 11 13 14 15 17 18 20 21 23 24 Coste

    A B B A C D E C C E C C D E C Mejor

    Mochila de tamaño 17

    17

    E 13

    8 11

    24 , igual que lo anterior

    El mayor valor de la mochila = 24 , ¿ Como lo lleno ? , vamos a mejor

    Hay un C , 17 - tamaño [ C ] = 10 , mochila tamaño 10 un C , 10 - 7 = 3 , mochila tamaño 3 un A , CAA.

    17 Si hubiera dejado la E

    C 17 E D

    C E

    A D

    Este problema cumple :

    Principio de Optimalidad

    Para que funcione mejor un problema de programación dinámica “ obtener el mejor ... “.

    Para que el resultado sea óptimo las etapas han de ser óptimas.

    No calcular desordenadamente , si una parte en llenar es óptima y la otra también es óptima el resultado es óptimo.

    Mochila Dinámica ( tamaño , valor : array [ 1 .. M ] : array [ 1 .. M ] )

    Desde j ! 1 hasta N hacer / * A .. E , N - número de objetos * /

    Desde i ! 1 hasta M hacer / * M - tamaño mochila , 1 - M * /

    Si ( i - tamaño [ j ] " 0 ) entonces / * índice mochila , puedo meter el objeto * /

    Si (coste [ i ] < (coste [ i-tamaño ]+ valor [ j ] ) entonces /* mejor anterior */

    coste [ i ] ! coste [ i - tamaño [ j ] ] + valor [ j ] / * lo cambio * /

    mejor [ i ] ! j

    fin si

    fin si

    fin desde

    fin desde

    devolver coste

    fin

    Reconstruir la mochila una vez llenada

    Ercr Mochila ( mochila : entero ; tamaño : array [ 1 .. N ] ; coste , mejor : array [1 .. N])

    Inicio

    mientras mochila > 0 && coste [ mochila ] > 0 hacer

    escribir ( mejor [ mochila ] )

    mochila = tamaño [ mejor [ mochila ] ]

    fin mientras

    fin

    9.5. Grafos : Caminos Más Cortos

    Floyd

    15

    1 3

    30 Tenemos un grafo dirigidos , caminamos

    5 50 15 5 más cortos entre todos los nodos ( opti -

    5 malidad )

    2 4

    15

    Ir por orden empezando por poco escribiendo en una estructura.

    Primero por el nodo 1 , luego 1; 2 , 1; 2 ; 3 hasta 1 ; 2 ; 3 ; 4.

    En un momento dado se el camino más corto entre el nodo i y j pasando por los nodos 1..k ( por 1 o todos ).

    i j

    [ 1..k ] [ 1 .. k ] [ 1 .. k ] es menor i ! k+1 ! j que i ! j , si lo cambio

    si no el que tenía k ! k + 1

    k+1

    definimos el grafo como Matriz de Adyacencia

    L [ i , j ] = distancia { i , j } si " { i , j } ( existe camino )

    = 0 si i = j

    = " si " { i , j }

    0 5 " "

    50 0 15 15

    L = 30 " 0 15

    15 " 5 0

    Estructura - una matriz Dk [ i , j ] = caminos más corto entre i y j usando los nodos 1 , 2 hasta k.

    La matriz D0 = L ( caminos directos )

    • D1 caminos que pasan por 1

    D1 = 0 5 " " La fila y columna 1 no cambian ya que es 1

    50 0 15 5

    30 35 0 15

    15 20 5 0

    Camino entre 2 y 3 que pasen por el 1 , no ! se queda como esta.

    Camino entre 2 y 4 que pasen por el 1 , no ! se queda como esta.

    Camino entre 3 y 2 que pasen por el 1 , si 3 - 1 (30) , 1 - 2 (5) , si 35 < " cambio.

    Camino entre 4 y 2 que pasen por el 1 , si 4 - 1 (15) , 1 - 5 (5) = 15 + 5 = 20

    • D2

    D2 = 0 5 20 10

    50 0 15 5

    30 35 0 15

    15 20 5 0

    Camino entre 2 y 3 pasando por el 2

    Camino 3 y 4 , si peso 35 y del 2 al 4 peso 5 ; 35 + 4 = 40 < 15 , no , no se cambia.

    3 15 4

    D1 [ 3 , 4 ]

    D1 [ 3 , 2 ] D1 [ 2 , 4 ]

    35 2 5

    • D3

    D3 = 0 5 20 10

    45 0 15 5

    30 35 0 15

    15 20 5 0

    Camino 2 , 1 2-3 peso 15 , 3 - 1 peso 30 , 30 + 15 = 45 < 50 , si cambio

    • D4

    D4 = 0 5 15 10

    20 0 10 5

    30 35 0 15

    15 20 5 0

    Del 2 al 1 pasando por el 4 si , 20 < 45 , si cambio

    Tenemos los caminos mínimos , ahora nos preguntamos ¿Por donde pasan los caminos? , tenemos una matriz P inicializada a 0 , cuando meto un nuevo nodo en el camino lo pongo , dejo el último al ser cada etapa óptima.

    0 0 4 2 0 son caminos directos

    P = 4 0 4 0

    0 1 0 0

    0 1 0 0

    Camino corto entre el nodo 1 y 3 pasa por el nodo 2

    1 3

    Camino directo en P 0 entre 1 y 2 2 4

    Floyd ( L : array [ 1 .. n , 1 .. n ] ) : array [ 1 .. n , 1.. n ]

    Inicio

    D ! L

    desde k ! 1 hasta n hacer / * D1 , D2 , D3 , ... * /

    desde i ! 1 hasta n hacer / * Cada matriz por * /

    desde j ! 1 hasta n hacer / * fila y columnas * /

    Si D [ i , j ] > D [ i , k ] + D [ k , j ] / * antiguo > nuevo camino * /

    D [ i , j ] ! D [ i , k ] + D [ k , j ]

    P [ i , j ] ! k

    fin si

    fin desde

    fin desde

    fin desde

    devolver D

    fin

    2-3-98

    9.6. Multiplicación de Matrices

    Más de dos matrices , n matrices :

    M1 M2 M3 ... Mn

    Colocaremos los paréntesis de forma que el número de multiplicaciones sea el mínimo posible y sin repetir cálculos. Puede haber matrices no cuadradas.

    Mi * Mi+1 = M filas Mi columnas Mi+1 ! filas de Mi y columnas Mi+1

    Cogemos todas las filas de Mi * columnas Mi+1 , el total de multiplicaciones.

    filas Mi * columnas Mi * columnas Mi+1

    array r [ 1 .. N + 1 ]

    r [ i ] = filas de la matriz Mi

    r [ i+1 ] = columnas de Mi tienen que ser iguales para poder multiplicar

    filas de Mi+1

    C [ N+1 ] = columnas de MN

    Número de Multiplicaciones ( Mi * Mi+1 ) = r [ i ] * r [ i+1 ] * r [ i+2 ]

    Ahora hay que colocar los paréntesis entre las matrices

    ( M1 ... Mj ) ( Mj+1 ... MN ) es menor el coste de poner aquí los paréntesis , antes tengo que ver cada conjunto , voy a ir en conjunto de dos matrices , luego tres , etc. Sin repetir cálculos.

    ( M1 ... Mj ) ( Mj+1 ... MN ) ! r [ j+1 ] * r [ N+1 ] dimensiones de la segunda matriz

    r [ i ] * r [ j+1 ] dimensiones de la primera matriz

    El coste de la matriz total = r [ i ] * r [ N+1 ] * r [ j+1 ].

    Ahora veo cada parte

    Nº Multiplicaciones ( M1 ... Mk ) ( Mk+1 ... Mj ) = r [ i ] * r [ N+1 ] * r [ j+1 ]

    Columnas de la 1ª

    La función quedaría Num Mult ( i , j , k )

    Ej. : tenemos 6 matrices

    A4x2 B2x3 C3x1 D1x2 E2x2 F2x3

    Utilizamos una tabla de 5x5

    B C D E F

    A

    B

    C

    D

    E

    Primero multiplicamos matrices de 2 en 2 ( sin paréntesis ) , vemos lo que cuesta multiplicar A x B poniéndole en la casilla.

    A x B = 4 x 2 x 3 = 24 B C D E F

    B x C = 6 x 2 x 1 = 6 A AB

    C x D = 3 x 1 x 2 = 6 24

    D x E = 1 x 2 x 2 = 4 B BC

    E x F = 2 x 2 x 3 = 12 6

    C CD

    6

    D DE

    4

    E EF

    12

    Grupos de tres matrices :

    ( AB )4x3 C 24 + 4 x 3 x 1 = 36 B C D E F

    A4x2 ( BC )2x1 6 + 4 x 2 x 1 = 14 A AB A(BC) (ABC) D

    ( BC )2x1 D2x1 6 + 2 x 1 x 2 = 10 24 14 22

    B2x3 ( CD )3x2 6 + 1 x 2 x 2 = 10 B BC (BC) D (BC) (DE)

    ... 6 10 14

    Indico donde poner el C CD C ( DE )

    paréntesis , solo apunto el 6 10

    último D DE (DE) F

    4 10

    E EF

    12

    Grupos de 4 matrices , cada parte tiene que ser óptima para que todo sea óptimo

    A ( BCD ) A ( C ( CD ) )

    A ( ( BC ) D ) ! ya esta calculado

    ( AB ) ( CD )

    ( ABC ) D ( A ( BC ) ) D ! calculada

    ( ( AB ) C ) D

    Se queda en tres posibilidades :

    A4x2 (BCD)2x2 = 10 + 4 x 2 x 2 = 26

    (AB)4x3 (CD)3x2 = 24 + 6 + 4 x 3 x 2 = 54

    (ABC)4x1 D1x2 = 14 + 4 x 1 x 2 = 22

    Otro :

    C3x1 (DEF)1x3 = 10 + 3 x 1 x 3 = 19

    (CD)3x2 (EF)2x3 = 6 + 12 + 3 x 2 x 3 = 36

    (CDE)3x2 F2x3 = 10 + 3 x 2 x 3 = 28

    Grupo de 5 matrices :

    A4x2 (BCDE)2x2 = 14 + 4 x 2 x 2 = 30

    (AB)4x3 (CDE)3x2 = 24 + 10 + 4 x 3 x 2 = 58

    (ABC)4x1 (DE)1x2 = 14 + 4 x 1 x 2 = 26

    (ABCD)4x2 E2x2 = 22 + 4 x 2 x 2 = 38

    Grupos de 6 matrices :

    A4x2 (BCDEF)2x3 = 14 + 4 x 2 x 2 = 30

    (AB)4x3 (CDEF)3x3 = 24 + 19 + 4 x 3 x 3 = 79

    (ABC)4x1 (DEF)1x3 = 14 + 10 + 4 x 1 x 3 = 36

    (ABCD)4x2 (EF)2x3 = 26 + 12 + 4 x 2 x 3 = 62

    (ABCDE)4x2 F2x3 = 26 + 4 x 2 x 3 = 50

    fila A columna E

    B C D E F

    A AB A (BC) (ABC) D (ABC) (DE) (ABC) ( DEF)

    24 14 22 26 36

    B BC (BC) D (BC) (DE) (BC) (DEF)

    6 6 14 22

    C CD C (DE) C (DEF)

    6 10 19

    D DE (DE) F

    4 10

    E EF

    12

    Hacia atrás :

    ( A ( BC ) ) ( ( DE ) F ) 36 ! 14 A ( BC )

    10 ( DE ) F

    Multi Matrices ( r : array [ 1 .. N+1 ] de enteros ) : enteros

    Var

    coste : array [ 1.. N , 1 .. N ] de enteros ;

    mejor : array [ 1.. N , 1 .. N ] de enteros ;

    Inicio

    desde i ! 1 hasta N hacer

    desde j ! i+1 hasta N hacer

    coste [ i , j ] ! MAXINT

    fin desde

    fin desde

    desde i ! 1 hasta N hacer coste [ i ,i ] ! 0 / * la diagonal a 0 * /

    desde j ! 1 hasta N-1 hacer / * de 2 en 2 , 3 en 3 , etc. * /

    desde i ! 1 hasta N- j hacer / * para cada grupo de x matrices donde ponemos

    desde k ! i+1 hasta i+ j hacer / * el paréntesis * /

    t ! coste [ i , k-1 ] + r [ i ] * r [ k ] + r [ i+j+1 ]

    Si t < coste [ i , i+ j ] entonces

    coste [ i , i+ j ] ! t

    mejor [ i , i+ j ] ! k

    fin si

    fin desde

    fin desde

    fin desde

    devolver coste [ 1 , N ]

    fin

    i - en los grupos de 3 en 3 cuantos se pueden formar de tres en tres.

    k - paréntesis , lugar donde pongo el paréntesis.

    t - cuanto cuesta realizar una multiplicación.

    Mi Mk-1 Mk M i +j

    coste [i , k-1 ] + coste [ k, i+ j ] + coste multiplicación r [ i ] * r [ k ] * r [ i+j+1 ]

    Escribir el orden de los paréntesis :

    orden ( i , j : enteros )

    Si i == j entonces

    escribir ( nombre [ i ] )

    sino

    escribir ( ` ( ` )

    orden ( i , mejor [ i , j ] - 1 ) / * que poner de la matriz 1 hasta k - 1 * /

    escribir ( ` * ` )

    orden ( mejor [ i , j ] , j ) / * de k hasta N * /

    escribir ( ` ) ` )

    fin si

    fin

    Existirá una tabla con el nombre de las matrices :

    char nombre [ ] = { ` A ` , ` B ` , ` C ` , ` D ` , ` E ` , ` F ` } ;

    9.7. Arbol de Claves

    Tenemos una serie de claves o palabras que están en un árbol binario ordenado , tenemos que intentar que la búsqueda sea lo más fácil.

    Las palabras más fáciles de encontrar ( las que buscamos más veces , tienen menor esfuerzo ) están en la raíz , las que menos buscamos están en la hojas.

    Como decidimos cual colocamos más arriba.

    K1 < K2 < ... < Kn Palabras o claves ordenadas

    f1 < f1 < ... < fn frecuencias de búsqueda de las palabras , números enteros.

    K

    Arbol Binario - rama izquierda hijo más pequeño

    K K rama derecha hijo más mayor.

    K K K K

    ...

    Arriba las de frecuencia mayor

    n

    Peso del árbol =  fi * ( di + 1 )

    i = 1

    profundidad d = distancia entre niveles y la raíz

    raíz = 1 ( +1 sino 0 )

    nivel = 2

    ...

    Como construyo un árbol ordenando de claves con el menor peso posible.

    Ej. : Palabras de C If , else , do , etc. , primero cogemos las palabras de dos en dos

    do else if

    5 10 15

    do else En el primer árbol según el peso

    cuesta más buscar.

    else do

    5 x 1 + 10 x 2 = 25 10 x 1 + 5 x 2 = 20

    else if

    else if

    if else

    10 x 1 + 15 x 2 = 40 15 x 1 + 10 x 2 = 35

    de tres en tres

    do do else if if

    else if do if do else

    if else else do

    Se cumple el principio de optimalidad , un árbol es óptimo si sus subárboles son óptimos.

    Peso do else if

    35 do if 20

    5x1 + 35 + (10+15) = 65 5x2 + 10x1 + 15x2 = 50 15 + 20 + (5+10) = 50

    hay que sumar uno más de cada porque ha cambiado la profundidad

    Quedan dos árboles iguales , else o if de raíz.

    9-3-98

    4 2 1 3 5 2 1

    A B C D E F G

    Letras ordenadas , los números son las frecuencias de esas letras o claves , árbol que busque esas claves empleando el mínimo coste , para ello las claves de mayor coste estarán en la raíz , se calcula el coste o peso del árbol.

    Peso =  fi ( di + 1 )

    Se cumple el principio de optimalidad.

    Tabla de 6 x 6

    B C D E F G

    A

    B

    C

    D

    E

    F

    i,j

    coste [ i ][ j ] = peso opt ( ki ... ki+j ) , árboles que tengan como raíz cualquier nodo

    kl si es óptimo sus subárboles también

    ki ... kl-1 kl-1 ... ki+j

    desde l ! i hasta i + j

    si coste [ i ] [ j ] > coste [ i ] [ l - 1 ] + coste [ l + 1 ] [ j ] +  fi

    Empezamos por árboles de dos nodos :

    A B

    B A

    4 x 1 + 2 x 2 4 x 2 + 2 x 1 Peso

    8 10

    C D

    D C

    1 x 1 + 3 x 2 1 x 2 + 3 x 1

    7 5

    Tres nodos :

    A B C B C D

    BC A C AB CD B D DC

    1x4 + 4+ 2 + 1 2x1 + 4x2 + 1x2 8 + 4 +2 + 1x1 5+2+1+3 2x1+2x1+3x2 4+2+1+3

    11 12 15 11 12 10

    Se suma al bajar el valor de los nodos que han bajado.

    Cuatro nodos :

    A B C D

    BCD A CD AB D ABC

    10 + 4 + 2 + 1 + 5 4x2 + 2x1 + 5 + 3 + 1 8 + 4x2 + 1x1 + 2x3 11 + 4 + 2 + 1 + 3x1

    20 19 24 21

    C D E F

    DEF C EF CD F CDE

    15 1 + 9 5 + 2 14

    Arboles de cinco nodos , solo tres :

    A B C D E

    BCDE A CDE AB DE ABC E ABCD

    20 4 + 14 8 + 11 11 + 5 19

    Con seis nodos :

    A B C D E F

    BCDEF A CDEF AC DEF ABC EF ABCD F ABCDE

    26 4 + 18 8 + 15 11 + 9 19 + 2 31

    Con siete nodo :

    D D D

    ABC EFG A EFG A E

    BC B F

    C D

    El árbol ABC ! raíz A ! BC ! B

    Arbol Claves ( f : array [ 1.. N ] de enteros ) : array [ 1 .. N+1 , 1 .. N+1 ] de enteros

    Var

    coste , mejor : array [ 1 .. N + 1 , 1 .. N + 1 ] de enteros

    Inicio

    desde i ! 1 hasta N hacer / * inicializar el triángulo superior * /

    desde j ! i + 1 hasta N + 1 hacer coste [ i , j ] ! MAXINT

    fin desde

    desde i ! 1 hasta N hacer coste [ i , i ] ! f [ i ] / * inicializo la diagonal con su * /

    desde j ! 1 hasta N-1 hacer / * frecuencia * /

    desde i ! 1 hasta N - j hacer

    desde k ! 1 hasta i + j hacer

    t ! coste [ i , k - 1 ] + coste [ k + 1 , i + j ] / * coste de subárboles * /

    Si t < coste [ i , i + j ] entonces / * encontrar el menor * /

    coste [ i , i + j ] ! t

    mejor [ i , i + j ] ! k

    fin si

    fin desde

    t ! 0

    desde k ! i hasta i + j hacer / * árbol de menor peso * /

    t ! t + f [ k ]

    fin desde

    coste [ i , i + j ] ! coste [ i , i + j ] + t

    fin desde

    fin desde

    devolver mejor

    fin

    f ! array de frecuencias claves ( ordenadas )

    j ! dos nodos , 3 , etc.

    i ! todos los posibles árboles dentro de dos nodos , 3 , etc.

    k! raíces posibles en cada posibilidad , encontrar el menor

    i " raíz k " i + j

    k

    i .. k - 1 k + 1 ... i + j

    Complejidad n³.

    9.8. Investigación Operativa

    Tenemos una empresa alimenticia , tiene que recoger la materia prima de un territorio dividido en partes A , B , C , D . Lo recoge a base de camiones , decide comprar 6 camiones más , pero un camión no puede recorrer dos zonas.

    ¿ Como asignamos los 6 camiones a las cuatro zonas maximizando el beneficio adquirido ?.

    El beneficio de un camión en cada zona :

    columnas - zonas

    filas - beneficio según los camiones a cada zona

    R - rendimiento

    R1 R2 R3 R4

    A B C D

    0 0 0 0 0

    1 4 2 6 2

    2 6 4 8 3

    3 7 4 8 4

    4 8 8 9 5

    5 8 9 9 6

    6 10 10 10 6

    Otro nombre del problema es de la decisión en n etapas

    D1 D2 D3 D4

    x0 x1 x2 x3 x4 = 0

    6 A B C D

    r1 r2 r3 r4

    cada decisión es casi independiente de las demás

    ! - número de camiones

    D1 - decisión zona ( 1 - zona1 )

    x1 = x0 - D1

    x2 = x1- D2

    x3 = x2 - D3

    x4 = x3 - D4 x3 = D4

    x4 = 0

    Las D las tomo en función de los beneficios ( tabla ).

    r1 = R1 ( x0 - D1 )

    D! mayor beneficio posible = ganancia g

    g4 ( x0 ) = max ( R1 ( x0 , D1 ) + R2 ( x1 , D2 ) + R3 ( x2- D3 ) + R4 ( x3 - D4 ) )

    D1 D2 D3 D4

    x1 depende de D1 , de lo anterior

    g4 ( x0 ) = max { R1 ( x0 , D1 ) + g4 ( x1 ) }

    D1

    g4 - mayor rendimiento para D1 D2 D3 D4

    g3 - mayor rendimiento para las últimas etapas

    g3 ( x1 ) = max { R2 ( x1 , D2 ) + R3 ( x2- D3 ) + R4 ( x3 - D4 ) }

    D2 D3 D4

    g3 ( x1 ) = max { R2 ( x1 , D2 ) + g2 ( x1 - D1 ) }

    D2 x2

    g2 ( x2 ) = max { R3 ( x2- D3 ) + R4 ( x3 - D4 ) }

    D2 D1

    g2 ( x2 ) = max { R3 ( x2 , D3 ) + g2 ( x3 ) }

    D3 x2 - D3

    g2 ( x3 ) = max { R4 ( x3 , D4 ) } / * última columna de la tabla * /

    Recursivo g4 , g3 , g2 , g1

    gk ( xn-k ) = opt { Rk ( xk-1 , Dk ) + gk ( xn-k + 1 ) }

    Dn-k ... Dn

    Dinámica empiezo por g1

    16-3-98

    El esquema anterior se llama Formulación Delantera ( primero etapa 1 , luego etapa 2 , etc. ).

    D1 D2 D3 D4

    x0 x1 x2 x3 x4 = 0

    6 A B C D

    r1 r2 r3 r4

    Esto se llama ahora Formulación Trasera ( primero la última y al final la primera ).

    g4 ( x0 ) = max { R4 ( x4 , D4 ) + R3 ( x3 , D3 ) + R2 ( x2 , D2 ) + R1 ( x1 , D1 ) }

    D1 D2 D3 D4

    g3 ( x3 ) = max { R3 ( x3 , D3 ) + R2 ( x2 , D2 ) + R1 ( x1 , D1 ) }

    D1 D2 D3

    g2 ( x2 ) = max { R2 ( x2 , D2 ) + R1 ( x1 , D1 ) }

    D1 D2

    g1 ( x1 ) = max { R1 ( x1 , D1 ) }

    D1

    g0 ( x0 = 0 )

    rescribo g4

    g4 ( x4 ) = max { R4 ( x4 , D4 ) + g3 ( x3 ) }

    D4 x3 = x4 - D4

    g3 ( x3 ) = max { R3 ( x3 , D3 ) + g2 ( x2 ) }

    D3 x2 = x3 - D3

    g2 ( x2 ) = max { R2 ( x2 , D2 ) + g1 ( x1 ) }

    D2 x1 = x2 - D2

    g1 ( x1 ) = max { R1 ( x1 , D1 ) + g0 ( x0 ) }

    D1

    g0 ( x0 ) = g0 ( 0 ) = 0

    g4 ! g3 ! g2 ! g1 ! g0

    g0 ! g1 ! g2 ! g3 ! g4

    La formulación trasera nos indica que es mejor empezar por la última etapa.

    El problema es que no se la entrada de la última etapa , para ello uso tablas , g1 quedara en función de x1 , g2 de x2 , etc.

    g1 - D1 = área D

    g1 ( x1 ) = max { R1 ( x1 , D1 ) } ; x1 entrada en la etapa filas de la tabla

    D1

    x1 \ D1 0 1 2 3 4 5 6

    0 0

    1 2

    2 3

    3 4

    4 5

    5 6

    6 6

    x1 - entradas x1 x0 = x1 - D1

    D - decisiones x1 = D1

    Rellenamos la tabla con los valores de suma ( el valor de la casilla es beneficio rx ) , si nos dejan 0 camiones beneficio 0.

    D1 - número de camiones que cogemos ; g1 - ganancia

    D1 g1

    0 0

    1 2

    2 3

    3 4

    4 5

    5 6

    6 6

    g2 D2 D1

    x2 x1 x0 = 0

    C D

    r2 r1

    0 1 2 3 4 5 6 D1 g1

    0 0+0 0 0

    1 0+2 6+0 1 2

    2 0+3 6+3 8+0 2 3

    3 0+4 6+3 8+3 8+0 3 4

    4 0+5 6+4 8+3 8+2 9+0 4 5

    5 0+6 6+5 8+4 8+3 9+2 9+0 5 6

    6 0+6 6+6 8+5 8+4 9+3 9+2 10+0 6 6

    g2 - guarda las etapas g2 y g1 juntas

    D2 g2

    0 0

    1 6

    1,2 8

    2 10

    2 11

    2 12

    2 3

    g3

    g3 ( x3 ) = max { (R3 (x3 , D3 ) + g2 ( x3 - D3 ) }

    D2

    0 1 2 3 4 5 6 D1 g1

    0 0+0 0 0

    1 0+6 2+0 0 6

    2 0+8 2+6 4+0 0,1 8

    3 0+10 2+8 4+6 6+0 0,1,2 10

    4 0+11 2+6 4+8 6+0 8+0 1,2,3 12

    5 0+2 2+11 4+10 6+8 8+0 9+0 2,3,4 14

    6 0+10 2+12 4+11 6+0 8+8 8+6 0 3,4 16

    g4 D4 D3

    g4 x3

    A B

    r4 r3

    g4 ( x4 ) = max { (R4 (x4 , D4 ) + g3 ( x4 - D4 ) }

    6 D4

    0 1 2 3 4 5 6 D4 g4

    6 0+16 4+14 6+12 7+10 8+8 9+8 10+6 1,2 18

    Como lo repartimos , según el algoritmo una o todas

    A B C D

    1 2 2 1

    1 3 1 1

    1 3 2 0

    1 4 1 0

    2 2 1 1

    2 2 2 0

    Todos beneficios 18

    Camiones ( R : array [ 0 .. M , 1.. N ] ; g , D : array [ 0..M , 1..N] )

    Inicio

    desde i ! 0 hasta M hacer

    g [ i , 1 ] ! R [ i , N ] / * lleno la primera etapa que es la 1ª columna copiada de la

    D [ i , 1 ] ! i / * última columna de R a la 1ª de g * /

    fin desde

    desde j ! 2 hasta N hacer / * etapas * /

    desde i ! 0 hasta M hacer / * desde 0 hasta 6 filas * /

    maxg ! MAXINT

    desde k ! 0 hasta i hacer / * mejor entrada posible * /

    si R [ k , N-j+1 ] + g [ i-k , j-1 ] > maxg entonces / * suma * /

    maxg ! R [ k , N-j+1 ] + g [ i-k , j-1 ]

    maxk ! k

    fin si

    fin desde

    g [ i , j ] ! maxg

    D [ i , j ] maxk

    fin desde

    fin desde

    devolver g [ M , N ]

    i ! M

    desde j ! N hasta 1 paso -1 hacer / * como se forma esa solución * /

    escribir ( ` ETAPA ` , ; ,' - ` , D [ i , j ] )

    i - = D [ i , j ]

    fin desde

    fin

    R N - número de etapas ( columnas )

    M - valor de la entrada ( filas )

    Ej. : Tenemos una empresa y queremos hacer una reestructuración , pedimos a tres consultoras que nos asesoren A , B y C . Sabemos que estas tres no son perfectas tienen un porcentaje de que se equivoquen al hacer el estudio :

    A B C

    40% 60% 80%

    Cual es la probabilidad de que se equivoquen las tres a la vez 0.4 * 0.6 * 0.8 = 0.19 casi un 20% , como podemos mejorar , contratamos a un empresa Americana y otra Japonesa para asesorar a esas tres , pero solo pueden asesorar a unas de las tres ( que las una asesore a A o B o C o las 2 a 1 ).

    Probabilidad de que se equivoquen aun siendo asesorada por los USA y los Japoneses.

    A B C

    0 40% 60% 80% No le asesora ninguna

    1 20% 40% 50% le asesora una

    2 15% 20% 30%

    Dos recursos ( asesorías extranjeras ) entre dos empresas.

    Formulación Delantera 1-A , C-3.

    D1 D2 D3

    x0 = 2 x1 x2 x3 = 0

    A B C

    r1 r2 r3

    g - tasa de error

    Fuerza bruta

    g3 ( x0 ) = MIN { R1 ( x0 , D1 ) * R2 ( x1 , D2 ) * R3 ( x2 , D3 ) }

    D1 D2 D3

    Recursivo

    g2 ( x1 ) = MIN { R2 ( x1 , D2 ) * R3 ( x2 , D3 ) }

    D2 D3

    g1 ( x2 ) = MIN { R3 ( x2 , D3 ) }

    D3

    Formulación trasera

    D3 D2 D1

    x3 x2 x1 x0

    A B C

    r3 r2 r1

    g3 ( x3 ) = MIN { R3 ( x3 , D3 ) * R2 ( x2 , D2 ) * R1 ( x1 , D1 ) }

    D3 D2 D1

    g2 ( x2 ) = MIN { R2 ( x2 , D2 ) * R3 ( x3 , D3 ) }

    D2 D1

    g1 ( x1 ) = MIN { R1 ( x1 , D1 ) }

    D1

    g3 ( x3 ) = MIN { R3 ( x3 , D3 ) * g2 (x3 - D3 ) }

    23-3-98

    D1

    x1

    0 1 2 Decisión Ganancia Etapa

    0

    1

    2

    Etapa C D1 \ x1

    0 1 2 D1 g1

    0 0.80 0 0.80

    1 0.50 1 0.50

    2 0.30 2 0.30

    Si no asesora ninguna empresa la tasa de error es la misma 80%.

    Etapa B D2 \ x2

    0 1 2 D1 g1 D2 g2

    0.60 * 0 0.80 0 0.48

    0 0.80 = 1 0.50 1 0.30

    0.48 2 0.30 2 0.16

    0.60 * 0.40 *

    1 0.50 = 0.80 =

    0.30 0.32

    0.60 * 0.40 * 0.20 *

    2 0.30 = 0.50 = 0.80 =

    0.18 0.20 0.16

    Etapa A D3 \ x3

    0 1 2 D3 g3

    0.15 * 0.20 * 0.15 * 1 0.06

    2 0.16 = 0.30 = 0.48 = Menor tasa de error que podemos conseguir

    0.064 0.060 0.072

    La asignación óptima

    A B C

    1 0 1

    # define M 3

    # define N 3

    float R [ ] [ ] = { { 0.4 , 0.6 , 0.8 } ,

    { 0.2 , 0.4 . 0.5 } ,

    { 0.15 , 0.2 , 0.3 } } ;

    main ( ) {

    int i , j , k , mink ;

    float g [ M ] [ N ] , ming ;

    int D [ M ] [ N ] ;

    for ( i = 0 , i < M , i++ ) { / * Etapas * /

    g [ i ] [ 0 ] = R [ i ] [ N-1 ] , D [ i ] [ 0 ] = i };/*ganancia última columna del inicio*/

    for ( j = 1 , j < N , j++ ) { / * Resto etapas * /

    for ( i = 0 , i < M , i ++ ) {

    ming = MAXINT ;

    for ( k = 0 , k " i , k ++ ) / * Encontrar el menor * /

    if ( R [ k ] [ N-j-1 ] * g [ i-k ] [ j-1 ] < ming ) { / * valor mínimo * /

    ming = R [ k ] [ N-j-1 ] * g [ i-k ] [ j-1 ] ;

    mink = k ; }

    g [ i ] [ j ] = ming ;

    D [ i ] [ j ] = mink ;

    }

    printf ( “ Probabilidad de error total : %f \n “ , g [ M-1 ] [ N-1 ] ) ;

    i = M-1 ;

    for ( j = N-1 ; j > = 0 ; j -- ) {

    printf ( “ Empresa %c %d \n “ , j + ` A ` , D [ i ][ j ] );

    i -= D [ i ] [ j ] } ;

    M - número de etapas

    N - número de valores

    Matrices D y C guardan los resultados de cada etapa.

    Ej. : una distribución de comestibles tiene un capital disponible de 10 Millones de que va a usar en tres zonas de expansión A , B , C .

    Los planes de expansión diseñadas vienen descritos por la siguiente tabla ( coste y beneficio del plan ).

    Plan \ Coste 0 2 4 Millones

    A 0 5 6

    0 5 6 8

    B 0 6 9 12

    0 1

    C 0 3

    Distribuir los 10 Millones de empresa entre las tres zonas.

    Ej. : Tengo 2 cadenas de caracteres

    C1

    C2

    Encontrar el número mínimo de caracteres mínimo que tengo que quitar en las dos cadenas para que queden las dos cadenas iguales.

    TEMA 11 : ALGORITMOS PROBABILISTICOS

    Para problemas en los que no sabemos encontrar la solución o es muy difícil entonces probamos a utilizar esta técnica.

    Tenemos una función que recibe un número/s como parámetro y genera un número al azar ( pseudoaltorio ) int uniforme ( int ) ;

    Cuatro tipos :

  • Algoritmos NUMERICOS - usa la probabilidad , solución aproximada a base de probar.

  • MONTECARLO - no nos valen soluciones aproximadas , solo las exactos el algoritmo nos da respuestas que a veces son correcta , incorrectas o no sabemos.

  • Respuesta verdadera y falsas

  • LAS VEGAS - se diferencia de la de MONTECARLO en que las respuestas que dan son siempre verdaderas o no hay respuesta.

  • SHERWOOD - problemas en que sabemos que tienen una complejidad diferente en función de cómo entren los datos de entrada.

  • Pueden estar los datos ordenados en el caso mejor o peor.

    Intercambio los datos de manera que quedan en el caso.

    11.1. Numéricos

    11.1.1. Area de un Círculo

    El círculo esta en un cuadrado de lado 2r , genero puntos de forma aleatorio y miro los que están dentro del círculo.

    Area del Círculo Número de Puntos dentro

    =

    Area Cuadrado Número de Puntos Totales

    Número de Puntos Dentro

    Area Círculo = * ( 2 r )² ( Area del cuadrado )

    Número de Puntos Totales

    Circulo ( n )

    k ! 0

    desde i ! 1 hasta n hacer

    x ! uniforme ( -r , r )

    y ! uniforme ( -r , r )

    si ( x² + y² ) " r² entonces k ! k + 1

    fin desde

    devolver ( k * 4 r² ) / n

    fin

    n ! puntos que se generan

    k ! puntos que caen dentro

    Esto se puede aplicar a cualquier otra integral.

    1 f ( x )

    f ( x ) dx

    0 1 se encierra la curva en un rectángulo ( altura > f ( x ) ) y se generan puntos aleatoriamente , se supone que será uniforme por todo el área ).

    1 número puntos dentro

    f ( x ) dx = * ( 1 * f ( x )max )

    0 número puntos totales

    Para calcular integrales

    Integral 1 ( n )

    k ! 0

    desde i ! 1 hasta n hacer

    x ! uniforme ( 0 , 1 )

    y ! uniforme ( 0 , f ( x )max )

    si y " f ( x ) entonces k ++

    fin desde

    devolver ( k * f ( x )max ) / n

    fin

    Otra interpretación de la integral es que esta es una suma de rectángulos muy pequeños

    1 1

    f ( x ) dx = lim  f ( x ) * Ax

    0 x! 0 x = 0

    base del rectángulo muy pequeña , sus sumas son el área.

    Integral 2 ( n )

    suma ! 0

    desde i ! 1 hasta n hacer

    x ! uniforme ( 0 , 1 )

    suma ! suma + f ( x )

    fin desde

    devolver 1 * ( suma / n )

    fin

    Hay un problema especial , contar elementos de un conjunto muy grande ( es muy lento ).

    Contar ( C : conjunto )

    k ! 0 ;

    s ! 0 ;

    a ! uniforme ( c ) ; / * parámetro un conjunto * /

    repetir

    k ! k + 1

    s ! S " { a }

    a ! uniforme ( c )

    hasta que a " s / * elemento que ya pertenece a k * /

    devolver 2 k² / 

    2 k² / 

    Complejidad O ( " n ) veces que se repite el bucle

    Lineal O ( n )

    30-3-98

    11.2. Sheerwood

    Algoritmo ( como una caja negra ) que realiza una función

    f ( )

    Es un algoritmo aceptable para el caso medio y muy malo para el caso peor , queremos que este caso no nos moleste al aparecer ( lo evitamos con un algoritmo ).

    UNIFORME

    y f ( y )

    x u (x) f ( ) v (y) f (x)

    Los datos se pasan antes por una función u ( ) que modifica los datos según un método aleatorio , luego deshacemos la modificación con otra función v ( y ).

    Ej. : ordenar una lista , v ( y ) no hará nada ya que sale ordenada y solo hay una solución . u ( x ) cambiara el orden de los datos ( puede ocurrir que quede ordenada al revés ).

    11.2.1. Listas Ordenadas por Punteros

    Tenemos una lista de claves de siete elementos :

    1 2 3 4 5 6 7

    valor 2 3 13 1 5 21 8

    Usamos un segundo array como punteros

    Ptr 2 5 6 1 7 0 3 ! 0 fin , último elemento

    El array puntero indica la posición en la cual esta

    siguiente elemento ordenado.

    cabeza [ ] ! donde esta el primer elemento de la lista ( 4 ).

    valor [ ptr [ i ] ] ! pregunta donde esta el siguiente elemento.

    Busca un elemento de la lista valor

    buscar1 ( x : clave , i : índice ) : índice

    Inicio

    mientras x > valor [ i ] hacer

    i ! ptr [ i ] ;

    fin mientras

    devolver i

    fin

    La primera llamada seria ( supongo que la cláusula esta en la lista ) :

    buscar1 ( x , cabeza ) ;

    Otra forma de realizar la búsqueda

    buscar2 ( x : clave ) : entero ;

    i ! cabeza

    max ! val [ i ]

    desde j ! 1 hasta raizCuad ( n ) hacer

    y ! valor [ j ] / * primer elemento de la lista * /

    si max < y " x entonces / * elemento es menor al límite * / Elemento más cerca

    i ! j / * nuevo límite * / de la cabeza

    max ! y / * nuevo límite * /

    fin si

    fin desde

    devolver buscar ( x , i )

    fin

    Complejidad O ( " n ) ! el caso medio en bueno

    Vamos a quitar los casos peores . En lugar de buscar desde la cabeza elige uno al azar desde 1 a n.

    buscar3 ( x : clave )

    Inicio

    i ! aleatorio ( 1.. n )

    y ! val [ i ]

    si x < y entonces / * me he pasado * /

    devolver buscar ( x , cabeza ) / * si , busco desde el principio * /

    sino

    si x > y entonces

    devolver buscar1 ( x , ptr [ i ] ) / * no , busco ese elemento * /

    fin si

    fin si

    fin

    Elección al azar para disminuir la aparición del caso malo.

    11.3. Las Vegas

    Algoritmos que son poco eficientes o no sabemos resolverlos , cuando nos den la solución es correcta , lo probamos hasta que nos den la solución o nos cansemos.

    Ej. : ocho reinas

    Reinas ( V ( ) : booleano )

    Inicio

    col ! diag 45 ! diag 135 ! { 0 }

    k ! 0 ;

    repetir

    nb ! 0

    desde i ! 1 hasta 8 hacer

    si ( i " col ) && ( 1-k " diag 45 ) && ( i + h " diag 135 ) entonces

    nb ! nb + 1

    si ( uniforme ( 1 , nb ) = = 1 ) entonces

    j ! i

    fin si

    fin si

    fin desde

    si nb > 0 entonces

    intento [ k + 1 ] ! j

    col ! col " { j } / * ocupada la columna * /

    diag 45 ! diag 45 " { j - k } / * ocupada la diag 45º * /

    diag 135 ! diag 135 " { j + k } / * ocupada la diag 135 * /

    k ! k + 1 / * siguiente reina * /

    fin si

    hasta ( nb = 0 ) || ( k == 8 )

    return ( nb > 0 )

    fin

    • Tres conjuntos :

    - col - columnas ocupadas

    - diag 45 - diagonal 45º ocupados

    - diag 135 - diagonal 135º ocupados

    • k - reinas colocadas en el tablero

    • nb - número de posiciones libres en la fila considerado.

    • La posición i pertenece a una col ocupada y a una diagonal de 45 grados ( todos los elementos tienen el mismo valor la resta de la fila y de la columna ) , sino esta libre la casilla.

    nb lo incremento en 1.

    Coloco la reina , si el número uniforme ( entre 1 y el número de casillas libres ) responde uno entonces la reina j ! i y sigo buscando una casilla libre.

    La primera reina se coloca en la primera fila ( entre 1 y 1 )

    1 2 3 4 5 6 7 8

    1  el azar elige si la segunda reina la coloco en

    2 la columna 1 , 5 , 6 , 7 , 8 de la segunda fila

    • Dos bucles que como mucho se ejecutan 8 veces cada uno

    8 * 8 = 64

    11.4. Montecarlo

    Son p correctos si hay una posibilidad p de que nos de la solución correcta , algunos son consistentes si da la misma entrad dan la misma solución correcta.

    Ej. : encontrar el elemento mayoritario de un array , es el elemento que se repite en más de la mitad de las posiciones del array.

    if { i " [ 1 .. n ] / T [ i ] = x } " n / 2

    mayoritario ( T [ 1 .. n ] , x ) : booleano

    k ! 0

    desde j ! 1 hasta n hacer

    si T [ j ] ! x entonces

    k ++

    fin si

    fin desde

    devolver ( k " n / 2 )

    fin

    Función que dado un array nos diga si un elemento es mayoritario

    buscarM1 ( T [ 1 .. n ] ) : elemento

    inicio

    desde i ! 1 hasta n hacer

    si mayoritario ( T , i ) entonces

    devolver i

    fin si

    fin desde

    fin

    Si esta recorre la mitad del array , si no hay recorre todo el array

    buscarM2 ( T [ 1 .. n ] ) : elemento

    Inicio

    x ! T [ uniforme ( 1 .. n ) ]

    si mayoritario ( T , x ) entonces

    devolver x

    fin si

    fin

    50% de posibilidad de acertar , algoritmo 0,5 correcto.

    buscarMC ( T [ 1 .. n ] )

    devolver T [ uniforme ( 1 .. n ) ]

    50% o 0,5 correcto , Tasa de error = 1 / 2

    Mejorándolo

    buscarMC2 ( T [ 1 .. n ] )

    inicio

    si no mayoritario ( T [ uniforme ( 1 .. n ) ] ) entonces

    Devolver T [ uniforme ( 1 .. n ) ]

    fin si

    fin

    Busco dos veces , 75% o 0.75 de que sea correcto , Tasa de Error = 1 / 4

    Puedo fijar la tasa de error repitiendo x veces el algoritmo

    E > 2 k - número de veces en repetir la búsqueda log2 ( 1 / E )

    E - tasa de error

    buscarMC3 ( T [ 1 .. n ] , E : real ) : elemento

    inicio

    k ! log2 ( 1 / E ) / * k - tasa de error * /

    desde i ! 1 hasta k hacer / * lo hago hasta k * /

    x ! T [ uniforme ( 1 .. n ) ]

    si mayoritario ( T , x ) entonces

    devolver x

    fin si

    fin desde

    devolver x

    fin

    O ( n log2 ( 1 / E ) )

    24 - 4 - 98

    TEMA 13 : VERIFICACION FORMAL DE PROGRAMAS

    Que la programación sea un técnica.

    Cuando conseguimos hacer un programa vemos si la salida es lo que esperamos , Validación Externa , pero los programas pueden tener infinitas combinaciones de los datos.

    Necesitamos un método mejor , sean cual sean los datos obtener la salida esperada Verificación Interna.

    COMPILACION ! SINTAXIS , lo normal al terminar un programa

    Nosotros necesitamos saber si el programa funciona como se espera , la SEMANTICA.

    Construimos un lenguaje especial que nos indica como funciona el programa Especificación.

    Especificación - como funciona el problema , descripción de la semántica o significado o como funciona el programa.

    ESPECIFICACION DERIVACION VERIFICACION

    FUNCIONAL AUTOMATICA FORMAL

    ABSTRACTA DE PROGRAMAS

    Dada un especificación se pueda construir un programa , que la construcción sea automática ( todavía no hay ninguna herramienta que lo realice todo ).

    Verificación Formal - que el programa funcione ( proceso ).

    13.1. Especificación

    Hay muchos lenguajes especializados ( Ej. Lenguaje z , etc. ).

    Una especificación debe tener las siguientes características :

    • Claridad - estar claro lo que la especificación pide.

    • Conciso - breve.

    • Precisión - sin ambigüedades.

    • Restrictivo - tiene que dejar fuera todas las implementaciones que no cumplan las especificaciones.

    • Generalidad - libertad para poder hacer el programa ( no se hace de una sola manera ).

    ESPECIFICACION NORMAL

    Sintaxis :

    < NONMBRE > ................................

    < DATOS > .......................................

    < SALIDA > ......................................

    < MODIFICACIONES > ..................

    < CONDICIONES PREVIAS > ........

    < EFECTO > .....................................

    < EXCEPCIONES > .........................

    Son etiquetas que preceden a una explicación

    < NONMBRE > nombre

    < DATOS > entrada

    < SALIDA > salida

    < MODIFICACIONES > datos de entrada modificados

    < CONDICIONES PREVIAS > conjunto permitido de datos de entrada

    < EFECTO > funcionamiento

    < EXCEPCIONES > posibles condiciones y mensajes de error

    Ej. : Programas que de la división entre dos números

    < NONMBRE > División

    < DATOS > a , b enteros

    < SALIDA > c entero

    < MODIFICACIONES >

    < CONDICIONES PREVIAS > b " 0

    < EFECTO > c = a / b

    < EXCEPCIONES > / * sin condición previa , si b = 0 mensaje de error */

    ESPECIFICACION FORMAL PRE-POST

    Determinar el conjunto permitido de datos de entrada " PRE-CONDICION

    Determinar el conjunto permitido de datos de salida " POST-CONDICION

    Que lenguaje usamos Lógica de Primer Orden , para especificar la PRE y POST CONDICION.

    LOGICA DE PRIMER ORDEN

    Necesitamos saber :

    TIPOS DE DATOS

    Elementos básicos , conjunto de valores y operaciones que pueden hacerse con esos valores :

    • VALORES - abstracciones matemáticas ( 5 , no se lo que es un 5 si lo que representa ).

    • OBJETOS - donde están los datos , entidad que cambia en el espacio y tiempo y contiene valores . Tipos :

    • Constante.

    • Variables.

    Un objeto es una posición de memoria.

    • OPERACIONES - función matemática sobre valores y objetos . Se identifican porque tiene :

    Rango

    Dominio

    Las instrucciones son funciones matemáticas.

    Nos basaremos en programación procedimental.

    SINTAXIS

    Conjunto de reglas del lenguaje , necesitamos :

    • ALFABETO DE SIMBOLOS

    • CONSTANTES - valores , 5 “ A “ “ cadena ”.

    • VARIABLES - objetos , x i.

    • FUNCIONES - operaciones aritméticas hasta los nombres para funciones.

    • DIFERENCIAS ENTRE FUNCIONES Y PREDICADOS

    Predicado - operaciones que da un resultado booleano. ( = ).

    • TERMINOS - construidos a partir del alfabeto.

    • Constantes son términos.

    • Las variables son términos.

    • Si t1 , t2 ... tn son términos y f es una función de n argumentos.

    f ( t1 , t2 ... tn ) es un término.

    y + 3 * x

    • FORMULAS - construidas con términos

    • Se construyen utilizando los predicados n - arios.

    Si t1 ... tn son términos y P predicado entonces P ( t1 , t2 ... tn ) es una fórmula atómica.

    Símbolos lógicos , si  y  son fórmulas entonces ¬ ,  "  ,  "  ,  !  ,  ! .

    • Hasta aquí Lógica de Primer Orden , para la Lógica de orden 1

    Si x es una variable y  es una fórmula entonces " x y " x  son fórmulas ( cuantificadores ).

    SEMANTICA

    A partir del concepto de estado :

    ESTADO - función que asocia a cada variable un valor del tipo a que pertenece.

    En un punto del programa vemos el estado de todas las variables.

    x ! x + 1 necesito saber el estado de una variable mediante una función

    que ocurre con la variable x y como funciona x = x + 1.

    s ( variable ) = valor actual de la variable

    s - función

    s ( x ) " 5

    s ( x ) " s ( y ) " s ( z ) " s ( x ) + s ( y ) / * verdad si se cumple * /

    "x s ( x ) " s ( y ) + s ( z )

    s ( z ) > s ( x ) + 7 ! s ( y ) + 5

     "{ x / s ( x ) > 5 } / * lo que significa la fórmula * / ASERCION = CONJUNTO DE

    ESTADOS DE UNA VARIABLE

    PRECONDICION  - conjunto de valores de las variables a la entrada.

    PROGRAMA

    POSTCONDICION  - conjunto de valores de las variables a la salida

    Es más corto de escribir

     P 

    PRE POST

     " { s ( a ) " 0 " s ( b ) > 0 }

     = { s ( c ) = s ( a ) / s ( b ) }

    Sirve para cada instrucción de un programa y nos indica que hace esa instrucción.

    1

    I1

    1 ! la Postcondición de la primera instrucción es la Precondición de la segunda

    I2

    2

    Ej. : No sabemos que hace el programa dado a continuación , tenemos que mirar las variables y sus estados para ver lo que hacen

    s ( a ) = 7 s ( b ) = 8

    Inicio s ( x ) = 0 s ( y ) = 0

    x ! a s ( x ) = 7

    y ! b s ( x ) = 7 " s ( y ) = 8

    mientras y > 0 hacer

    x ! x + 1

    y ! y - 1

    fin mientras

    fin

    Si quiero ver el programa para todos los valores de x e y positivos

    { s ( a ) > 0 " s ( b ) > 0 } PRECONDICION

    { s ( x ) = s ( a ) " s ( y ) = s ( b ) }

    En una iteración del bucle { s ( x ) + s ( y ) = s ( a ) + s ( b ) }

    Finalizado el bucle { s (x ) = s ( a ) + s ( b ) " s ( y ) = 0 } POSTCONDICION

    Son fórmulas que expresan el conjunto de estados ( valores de las variables ) , visión interna del programa , no lo hace la máquina . No hemos tomado valores concretos.

    El problema se basa en la fórmula de Aserción , fórmula de lógica de primer orden que describe el conjunto de los estados posibles de las variables de un programa en un instante del mismo.

    S ( x ) = 7

    { x = 7 } / * Aserción que describe un estado * /

    x ! 7 / * instrucción que realiza algo sobre x * /

    27-4-98

    Forma Normal de HOARE

    Inicio { a > 0 " b > o }

    x ! a

    y ! b { x = a " y = b }

    mientras y > 0 hacer

    x ! x + 1

    y ! y + 1 { x + y = a + b }

    fin mientras { x = a + b " y = 0 }

    fin

    Todas las fórmulas se meten entre llaves , son conjuntos de valores le puedo dar nombre a estas fórmulas.

     = { x = a " y = b }

     x = fórmula que resulta de sustituir  donde pone x poner t

     = { "x ( x > 7 + y " z = x + 3 }

     x = { "t ( t > 7 + y " z = t + 3 }

    Puede ocurrir colisiones de variables al cambiarla

     x = { "x+1 ( x + 1 > 7 + y " z = x + 1 + 3 } No es igual a los anteriores

    Dos fórmulas que describen el mismo conjunto se llaman equivalentes la una y la dos son equivalentes pero no la tercera.

    { x = 4 " y = 16 } fuerte

    { x² = y } débil

    No son equivalentes , pero la primera describe un solo estado que esta incluido en el conjunto de estados de la segunda , el primero es Fuerte y el segundo Débil.

    Fórmula :

    • Más Fuerte - cuanto menor es el número de estados que permite . Impone más restricciones.

    • Débil - conjunto de estados más grande.

    Buscamos un sistema que deduzca lo que haga el problema , automatizar.

    aserción precondición

    instrucción = instrucción

    aserción postcondición

    Tengo que construirlo como un axioma

    { x > 0 }

    x ! 7 ; Axioma , se como funciona la instrucción y que esta bien

    { x = 7 }

    Axiomas

    {  x } x ! t ; {  } x - variable

    Pre Post t - término

    { x > 0 } ; x ! 7 ; { x = 7 }

    postcondición

    { x = x } para que cumpla el axioma y que sea verdadera la fórmula más débil.

    x t 

    Ej. : { x + y = 10 } x ! x + y { x = 10 } AA ! es verdad coincide con el axioma de

     x  la condición

    x + y = 10

    { true } x ! y ; { x = y }

    true - forma más débil de todas , caven todos los estados.

     x y = y AA

    x t 

    { " j ( i = 2 ) z - i ; { " j [ z = 2 ] } AA

    potencia derecha

     x = Pz = { " j ; [ i = 2 ] )

    x t 

    Ej. : { true } x ! x + y { x = x + y }

     x = x + y ! x + y + y { x + y = x + y }/ * No es una aserción es el efecto de una

    { 0 = y } es verdad instrucción * /

    13.2. Métodos de Deducción

    Indican si el programa es correcto o no

  • Regla de la Composición Secuencial ( RCP )

  • {  } I1 { 1 } , { 1 } I2 { 2 }

    {  } inicio I1 , I2 fin { }

    {  } I1 { 1 } , { 1 } , I2 { 2 } ... {  n-1 } In {  }

    {  } Inicio I1 ; I2 ; ... In {  }

    Para poder deducir varias instrucciones encima de la raya son premisas y después de la raya esta la conclusión.

    Si se cumplen las premisas se cumplen la condición

    Premisas

    Conclusión

    Si todas se cumplen la precondición del bloque es la de la primera y la postcondición es la de la última instrucción.

    Ej. : Es correcto el siguiente programa

    Un programa es correcto Parcialmente si cumpliéndose la precondición y ejecutándose el programa se cumple la postcondición.

    Un programa es totalmente Correcto si además de ser parcialmente correcto todos sus bucles terminan.

    Ej. : Es parcialmente el siguiente programa

    { x = a " y = b }

    Inicio

    aux ! x

    x ! y

    y ! aux

    fin

    { x = a " y = b }

    Al ser secuencial no indica usar la regla RCP.

    Numero los pasos

  • { x = a " y = b } aux ! x ; { x = a " y = b } AA

  •  aux = x = a ; y = b 

    es verdad por el Axioma de Asignación

  • { a " x = a " y = b } y ! x ; { aux = a " x = b } AA Si una postcondición no la usas

  • y = b la pones

     x = { aux = a " y = b }

  • { aux = a " x = b } y ! aux { x = a " y = b } AA

  •  y = { aux = a " x = b }

    Cogiendo las 3

    1 , 2 , 3

  • { x = a " x = b } inicio ... fin { x = a " x = b } , es verdad porque usando como premisas 1 , 2 , 3 y usando la RCP lo demuestran.

  • 2. Regla de la Consecuencia ( RCN )

     ! 1 , { 1 } I { 1 } , 1 ! 

    {  } I {  }

    A veces no coincide la precondición y la postcondición.

    Si puedo demostrar con una instrucción / es puedo encontrar una precondición y una postcondición entonces son las nuevas  y 

    Ej. : { x > y } x ! x - y ; { x " 0 }

    x - y

     x = { x - y " 0 }

    ( x " y ) ! ( x - y " 0 ) / * esto es verdad * /

     ! 1

    { x - y " 0 } x ! x - y ; { x " 0 } ! coincide con la que necesito

    Ej. : { 1 " i < n } i ! i + 1 { 1 " i " n }

     i " { 1 " i+1 " n } no es igual símbolo a símbolo a la precondición

    { 1 " i < n } ! { 1 " i " n } / *  ! 1 primera parte RCN * /

    n = 4

    i = 3

    transformación de la pre y postcondición.

    3. Regla de la Condición ( RCD )

    Interpretar los bloques si - entonces y si - sino {  }

    {  " B } I1 {  } , {  " ¬ B } I2 {  } si no

    {  } si B entonces I1 sino I2 fin si {  } B

    I1 I2

    {  }

    {  " B } I , {  } ;  " ¬ B !  / * esta ya cumple la precondición * /

    {  } si B entonces I1 finsi {  }

    B

    si no

    I1

     ( precondición ) y  ( postcondición ) deben ser igual para las dos ramas.

    Ej. : Demostrar que le programa es parcialmente correcto

    { true }

    si x " y entonces

    z ! x - y

    sino

    z ! y - x

    fin si

    { z = ø x - y ø }

    Lo más externo es un si , regla RCP

  • ( x " y ) ! ( x - y " 0 ) / * lo transformo porque no saldría * /  " B z ! x - y 

  • { x " y " 0 } z ! x - y { x - y " 0 " z = x - y }

  •  z = x - y " 0 " x - y = x - y en la postcondición

    true se puede quitar

  • { x - y " 0 " z = x - y } ! ( z = | x - y | )

  • { x " y } z ! x - y ( z = | x - y | ) 1 , 2 , 3 RCN

  • 1,2,3 RCN

    4

    Con la otra rama

     " ¬ B I2 

    x < y z = ( x - y )

  • ( x < y ) ! { y - x " 0 }

  • { y - x " 0 } z ! y - x { y - x " 0 " z = y - x } AA

  • 

     z y - x " 0 " y - x = y - x

    true

  • ( y - x " 0 " z = y - x ) ! ( z = | x - y | )

  • { x " y } z ! y - x ; { z = | x - y | } 5 , 6 , 7 RCN

  • ¬ ( x " y )

    5,6,7 RCN

    8

  • { true } si ... fin si { z = | x - y | } 4 , 8 RCD

  • 1,2,3 5,6,7

    4 8

    9

    Ej. : Demostrar que le siguiente programa es correcto

    { x = a " y = b }

    si x < y mientras

    inicio

    aux ! x

    y ! x max - mayor dos números ( x ! mayor , y ! menor )

    y ! aux min

    fin

    fin si

    { x = max ( a , b ) " y = min ( a , b ) }

    4-5-98

    4. Regla del Bucle Mientras RWH

     ! INV , { INV " B } I { INV } , INV " ¬B ! 

    {  } mientras B hacer I fin mientras {  }

    

    INV

    INV -

    B

     " B + INV " ¬B

    I

    INV

    

    INV - invariante , aserción que se cumple al final de cada iteración de un bucle , describe el efecto bucle.

    Antes de empezar el bucle se cumple la precondición , al pasar la condición del bucle se cumple la precondición y el bucle  " B o INV " B ( precondición de las instrucciones ).

    INV se deduce de la precondición ( considera también las variables al inicio del bucle ). El invariante se construye mirando la postcondición y quitando la condición del bucle.

    Ej. : Corrección parcial de

    inicio { true }

    i ! 1

    m ! A [ 1 ]

    mientras i " n hacer

    i ! i + 1

    si m < A [ i ] entonces m ! A [ i ]

    fin mientras

    fin { " j ( 1 " j " n ! m " A [ j ] " " j ( 1 " j " n ! m = A [ j ] ) }

  • { true } i ! 1 { i = 1 } AA

  • { i = 1 } m ! A [ 1 ] { i = 1 " m = A [ 1 ] } AA

  • INV " { " j ( 1 " j " i ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ j ] ) "

    1 " i " n }

  • { i = 1 " m = A [ 1 ] }! ( " j ( 1 " j " i ! m " A [ j ] ) "  ! INV

  • " j ( 1 " j " i ! m = A [ j ] ) " 1 " i " n )

  • { INV " i " n } ! ( " j ( 1 " j " i ! m " A [ j ] ) " / * precondición 1ª

  • " j ( 1 " j " i ! m = A [ j ] ) " 1 " i " n ) / * sentencia bucle * /

    i ! i + 1

  • ( " j ( 1 " j " i ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ j ] ) " 1 " i " n ) "

  • " j ( 1 " j " i + 1 ! m = A [ j ] " 1 " i + 1 " n )

  • { " j ( 1 " j " i ! m " A [ j ] ) " " j ( 1 " j " i + 1! m " A [ j ] }

  • i ! i +1 { " j ( 1 " j " i - 1! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ j ] ) " 1 " i " n } AA

    i + 1 - 1 = i

  • Si m " A [ i ]

  • " j ( 1 " j " i - 1 ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ i ] ) " 1 " i " n "

    m " A [ j ] ! ( " j ( 1 " j " i ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ i ] ) "

    1 " i " n )

  • { " j ( 1 " j " i ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ i ] ) " 1 " i " n }

  • m ! A [ i ]

    INV [{" j ( 1 " j " i ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ j ] ) " 1 " i " n }] AA

  • El otro lado del si ( no se cumple ).

  • ( " j ( 1 " j " i - 1 ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ j ] ) " 1 " i " n "

    m " A [ 1 ] )

    ! INV

    Interior del bucle 5 INV " i " n

    ...

    8 7 INV

  • { " j ( 1 " j " i - 1 ! m " A [ j ] ) " " j ( 1 " j " i ! m = A [ j ] ) " 1 " i " n }

  • Si m < A [ i ] entonces m ! A [ i ] 7 , 8 , 9

    { INV } 7 , 8 , 9 RCD 10 RCD

  • Resumen desde el quinto paso

  • { INV " i " n }

    inicio i ! i +1 ... fin mientras

    { INV } 5 , 6 , 10 RCP , RC ( Regla de Composición )

    11 - salida del bucle.

  • ( INV " i " n ) ! " j ( 1 " j " n ! m " A [ j ] )

  • " j ( 1 " j " n ! m = A [ j ] )

    / * Podría meter 1 " i " n pero ya da * /

    4 , 11 , 12

    RWH

  • { i = 1 " m = A [ 1 ] }

  • mientras ... fin mientras

    {  } A , 11 , 12 RWH

  • { true } inicio .. fin {  } 1 , 2 , 13 RCP

  • 5. Regla del Bucle Repetir

    {  } I { INV } , { INV " ¬B } I { INV } , INV " B ! 0

    {  } repetir I hasta B {  }

    

    INV " ¬B

    I

    INV

    - +

    B

    INV " ¬B INV " B

    

    Ej. : Es correcto parcialmente

    { n " 1 }

    inicio

    S ! 0 ;

    x ! 0 ;

    repetir / * La primera vez  , el resto INV " ¬B * /

    x ! x + 1

    S ! S + x²

    hasta que x = n

    fin

    n

    { s =  i² }

    i = 1

  • { n " 1 } S ! 0 { n " 1 " S = 0 } AA

  • { n " 1 " S = 0 } x ! 0 { n " 1 " S = 0 " x = 0 } AA

  • x

  • ( n " 1 " S = 0 " x = 0 ) ! (n " 1 " S =  i² " x + 1 " n ) / * precondición 1º I * /

  • i = 1

    x

  • { S =  i² " x + 1 " n } x ! x + 1

  • i = 1

    x

    { S =  i² " x " n }

    i = 1

    x - 1 x -1

  • { S =  i² " x " n } ! ( S + x² =  i² + x² " x " n )

  • i = 1 ! i = 1 ! / * x² a ambos lados de la ecuación * /

    x x

  • { S + x² =  i² + x² " x " n } S ! S + x² { S =  i² " x " n }

  • i = 1 i = 1

  • { n " 1 " S = 0 " x = 0 } x ! x + 1 ; S ! S + x² { INV } 3 , 4 , 5 , 6 RCP RCD

  • x

  • INV " ( x " n ) ! ( S + ( x + 1 )² =  i² + ( x + 1 )² " x + 1 " n ) INV " ¬B

  • ! i = 1 !

    INV x " n x + 1 podría ser igual

    x < n

    x " n

    x+1

  • { S + ( x + 1 )² =  i² " x + 1 " n } x ! x + 1

  • i = 1

    x

    { S + x² =  i² " x " n } AA

    i = 1

    x x

  • { S + x² =  i² " x " n } S ! S + x² { S =  i² " x " n } AA

  • i = 1 i = 1

  • { INV " ( x " n ) } x ! x + 1 ; S ! S + x² { INV } 8 , 9 , 10 RCP RCD

  • Segunda premisa de salida

  • n

    { INV " ( x = n ) } ! { S =  i² } 

    i = 1

    n

  • { n " 1 " S = 0 " x = 0 } repetir hasta x = n { S =  i² } 7 , 11 , 12 RPT

  • i = 1

    n

  • { n " 1 } inicio ... fin { S =  i² } 1 , 2 RCP

  • i = 1

    Ej. : Es correcto

    { n " 1 }

    inicio

    S ! 0 ;

    x ! 0 ;

    mientras x < n

    x ! x + 1

    S ! S + x²

    fin mientras

    fin

    n

    { s =  i² }

    i = 1

    11-5-98

    13.3. El Problema de la Terminación

    { true } { true }

    Inicio Inicio

    r ! 0 r ! 0

    z ! x z ! x

    mientras z " y hacer mientras z < y hacer

    z ! z + 1 z ! z + 1

    r ! r + 1 r ! r + 1

    fin mientras fin

    fin { r = y - x } { r = y - x }

    Los dos programas cumplen la misma postcondición y no tienen precondición.

    Vemos si los programas terminan.

  • Hay valores de y que no hacen terminar el programa , si termina no cumple la postcondición.

  • Para valores de y no termina , no cumple la postcondición si los hace.

  • Para que un bucle termine se tiene que cumplir :

  • Que el bucle modifique las variables de terminación del bucle.

  • Que los cambios no sean infinito , que cambie la condición.

  • Bucle de carácter general

    mientras B hacer

    I

    fin mientras

    I tiene que modificar algo de B en un número finito de veces.

    Para que un bucle termine :

    ORDEN BIEN FUNDADO - consta de un conjunto S y una relación binaria " ( un símbolo ) tales que :

  • La relación es un orden parcial en S , orden parcial es reflexivo , antisimétrico y transitivo.

  • Reflexivo - x "S x " x

    Antisimétrico - x " y " y " x

    Transitivo - x " y y " z ! x " z

  • No hay cadenas descendentes infinitas

  • serie

    " < xi " S / i " N >

    x0 > x1 > x2 > ... > xn > ...

    x > y ! y " x " y " x hay un elemento mínimo del conjunto , no es infinito.

    ( N , " )

    relación de orden 15 , 9 , 7 , 6 ...... 0 acaba sola si no la paro yo

    orden bien fundada

    ( Z , " )

    15 , 9 , 7 , 6 , 3 , -1 , -4 , ... No es un orden bien formado , cadena infinita

    Ej. : Ordenes bien fundadas

    ( N² , << )

    ( x , y ) << ( u , v )

    ( x < u ) " ( x = u " y < v ) orden parcial y también orden bien fundado , elemento

    mínimo posible ( 0 , 0 ).

    ( p ( c ) , " - estar incluido o coincide

    p - conjunto de los subconjuntos de C ( que es finito ).

    Luego tendré finitos subconjuntos , en cada uno esta incluido en el anterior.

    Si tengo un bucle y quiero saber si termina

    mientras B hacer

    I

    fin

    modifica a B en un número finito de pasos , buscamos una expresión que nos de una serie con elementos que este bien fundado , que pertenezca a un orden bien fundado.

    e expresión tal que INV " B ! e " S

    cada vez que se ejecuta el bucle { INV " B " e = v } I { e " v " INV }

    Ej. : Inicio

    x ! a INV = { x + y = a + b " y " 0 }

    y ! b

    mientras y > 0 hacer

    x ! x + 1

    y ! y - 1

    fin mientras

    fin

    ( N , " ) y - decrece siempre

    e " y

    { INV , y > 0 " y = v } + { y < v } ! orden bien fundada , termina con lo cual el bucle también termina.

    { INV " y > 0 " y = v } y ! y - 1 { y + 1 = v " INV }

    y = y - 1 + 1 y - 1 + 1

    y + 1 = v ! y = v - 1 - y < v

    En cada iteración y disminuye , cadena finita . La expresión " N.

    Ej. : programa que manipula una matriz

    var A : array [ 1..n , 1..n]

    inicio { n " 1 " m " 1 }

    x ! 1 ;

    j ! 1 ;

    mientras i " n hacer

    tratar A [ i , j ]

    si j < m entonces

    j = j + 1 ;

    i ! i + 1 ! j - 1

    sino

    i ! i + 1

    fin si

    fin mientras

    fin { P ( A , n + 1 , m ) }

    Instrucción que diga cuantos elementos de la matriz quedan

    e : ( n - i , m - j ) número de filas f ( N ²² , << )

    Cuando se ejecuta el bucle la expresión disminuye.

    { INV " i " n " ( n - i ) n - 1 ) " ( u , v ) B

    Algoritmia 93 METODOLOGIA

    ______________________________________________________________________

    cadena a buscar

    cadena a sustituir

    estado al que ir

    2º estado a ir

    Cambiar la cadena “ab“ por 0

    S = bbb

    Estado final = bbb ( las cambio por a )

    E = aaabbbbb | 3 - 5 |

    0 ab 0 1

    1 ab 0 1 2

    2 b a 2 3

    3 0 0 3

    j j j aj bj

    T

    A - Alfabeto

    M - Movimientos

    Q - Estados

    C - Cinta

    i =1

    k

    t ( n ) =  Pi ( n ) ti ( n )

    n ! "

    g ( n )

    f ( n )

    Si existe lim = l , entonces se pueden dar tres casos :

    g " f y f " g

    = "

    100 n + 500

    2n² + n

    = lim

    n ! "

    g ( n )

    f ( n )

    lim

    1

    1 / n

    n ! "

    f " g y g " f

    = lim

    n ! "

    n

    Ln

    lim

    i =1

    n-1

    b +  ( a + 2b + b + ( n - i ) * ( 2a + 4b ) )

    i =1

    n-1

    

    ( n - 1 ) ( 2a + 4b ) +

    ( n - 2) ( 2a + 4b )

    ( n - 3 ) ( 2a + 4b ) +

    226

    150

    1000 9,97 seg 1msg 9,96 mseg 1 seg 16,6 min 1,1 * 10 años ........

    100 6,64 seg 100 seg 664,4 seg 10 mseg 1seg 4,02 *10²² años >10 años

    tiempo ( en seg )

    10 3,32 seg 10 seg 33,2 seg 100 seg 1 msg 1,024seg 3,63 seg

    n

    n log2 n n n log2 n n² n³ 2 n !

    k

    n = 2 ! log2 n = k

    Hay que hallar k para saber

    la complejidad.

    Hasta que nos quede

    un elemento.

    ¿ Hasta cuando ?

    ...

    n / 8

    n / 4

    = 1

    k

    2

    n

    n / 2

    fin

    n

    inicio

    Array que se

    devuelve.

    Mezcla

    División

    ...

    ...

    L2

    n / 2

    L1

    n / 2

    n

    i

    n = 2

    i

    n / 2 =1

    i

    i

    T (n) = 2 T ( n / 2 ) + i * n

    4

    4

    4

    T (n / b³) = a T (n / b ) + d (n / b³) = a T (n / b ) + a³ d (n / b³) + a² d (n /b²) +

    + a d (n/b) + d (n)

    i=0

    3

    i

    i

    4

    4

    a T (n / b ) +  a d ( n / b )

    i

    i+1

    i

    T (n / b ) = a T ( n / b ) + d ( n / b )

    i =0

    k - 1

    k

    k

    i

    i

    T (n ) = a T ( n / b ) +  a d ( n / b )

    k

    k

    logb n = k

    n = b

    n / b = 1

    i =0

    k - 1

    logb n

    i

    i

    T (n ) = a T ( 1 ) +  a d ( n / b )

    logb a

    logb a

    logb n

    T (n ) = a = n = O ( n )

    logb a

    logb a

    t

    Si d (n ) > n n = n

    n

    tn = x

    n-k

    n-2

    n-1

    n

    a0 x + a1 x + a2 x + ... + ak x = 0 Es un polinomio

    n-k

    k-2

    k-1

    k

    ( a0 x + a1 x + a2 x + ... + ak ) x = 0

    k-2

    k-1

    k

    a0 x + a1 x + a2 x + ... + ak = 0

    n

    n

    n

    T (n) = C1 r1 + C2 r2 + ... + Ck rk Solución

    i = 1

    k

    n

    tn =  ci ri = T (n)

    n

    tn = ri

    n

    tn = x

    n

    n - 2

    n - 1

    n

    x = tn

    x - 3x - 4 = 0

    x = 0

    n - 2

    h

    ( x - r1 ) (x - r2 ) ( x - rn-m ) = 0

    -2 / 2 = -1

    8 / 2 = 4

    2

    3 ± 5

    =

    2

    3 ± " 25

    =

    2

    x =

    3 ± " 9 + 16

    n

    n

    n

    T (n) = 1/5 4 - 1/5 ( -1 ) = O ( 4 )

    n

    n

    n

    T (n) = C1 4 + C2 ( -1 ) = O ( 4 )

    n

    n

    n

    x = C1 r1 + C2 r2

    n - 2

    n - 1

    n

    x - x - x = 0

    x = 0

    n - 2

    n - 2

    ( x² - x - 1 ) x = 0

    = 2

    = 1

    2

    1- " 5

    2

    1+ " 5

    r2 =

    r1 =

    2

    1± " 5

    =

    2

    1± " 1 + 4

    ri =

    n

    n

    n

    T (n) = C1 1 + C2 2 = O ( 1 )

    n

    n

    m - 1

    n

    n

    n

    T (n) = C1 r1 + C2 n r1 + C3 n² r1 + ... + Cm n r2 + ... + Ck rk-m

    n

    n

    n

    n

    T (n) = C1 2 + C2 n 2 + C3 1 = O ( n 2 )

    n

    3

    n

    3

    n

    3

    n

    3

    n +1

    3

    n +1

    n

    n

    T (n) = C1 2 + C2 3

    T (n) = 2 T ( n-1 ) + ( n+5 ) 3

    n

    3

    n

    3

    n +2

    n +2

    3

    n +1

    n +2

    n +1

    - 6 ( n + 6 ) 3 = -2 ( n + 6 ) 3

    n +2

    2 ( n + 6 ) 3

    n +2

    ( n+7 ) 3

    n +2

    ( n+5 ) 3

    n

    n

    T (n) = C1 T ( n-1 ) + C1 T ( n-1 ) + ... + Ck T ( n-k ) + P (n ) b d = grado de p

    n

    a0 tn + a1 tn-1 + a2 tn-2 + ... + ak t n-k = P (n ) b

    d+1

    k-1

    k

    ( a x + a1 x + ... + ak ) ( x - b ) = 0

    n

    n

    1

    n

    1

    n

    1

    n

    2

    n

    2

    n

    2

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n

    n - 1

    d1 + 1

    d2 + 1

    d m + 1

    n

    n

    n

    n

    n

    n

    n

    n + 1

    n

    n

    k

    k

    k

    2k-1

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k-2

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    k

    logb

    loga

    log2 3

    log2 3

    k

    logb

    loga

    log2 3

    log2 n

    n

    1 + j

    j =1

    C

    B

    A

    n-1

    4

    1

    1

    1

    1

    1

    1

    2

    2

    2

    2

    2

    3

    1

    3

    4

    B

    A

    C

    A

    B

    C

    A

    B

    C

    n / 2

    n / 2

    n / 2

    n

    n

    n / 2

    log2 3

    1'98

    Hemos reducido la complejidad

    n-2

    n-2

    n-2

    n

    log2 3

    n

    REC

    ...

    n/4

    n/4

    n/4

    n/2

    n/2

    n/2

    n

    k

    k

    2 ( n/2 )³

    2 ( n/2 )³

    2 ( n/2 )³

    2 ( n/2 )³

    A11 x B11 +

    + A12 x B21

    =

    B12

    B22

    B21

    B11

    X

    A22

    A21

    n/2 x n/2

    A12

    A11

    M1 + M2 + M4 + M5

    M1 + M2 + M5 + M6

    M1 + M2 + M3 - M7

    M2 + M3

    2,81

    4

    6

    6

    4

    2

    3

    4

    5

    4

    5

    3

    2

    7

    6

    5

    3

    4

    1

    2

    7

    6

    5

    3

    4

    1

    2

    j

    6

    4

    4

    1

    3

    4

    2

    3

    5

    2

    4

    2

    7

    6

    5

    3

    4

    1

    2

    2

    4

    3

    1

    2

    2

    B

    5

    6

    4

    7

    3

    2

    1

    n

    -k

    t

    t

    x +1

    t

    x + y

    t

    i

    j

    t

    i

    i

    t

    x

    y

    aux

    i+1

    x - y

    y - x

    f

    f

    y - 1




    Descargar
    Enviado por:Maria Luisa Moral
    Idioma: castellano
    País: España

    Te va a interesar