Repaso de Matemáticas discretas

Anuncio
Repaso de Matemáticas discretas
Andrés Becerra Sandoval
23 de julio de 2007
1.
Introducción
La matemática discreta en contraposición a la continua (como el cálculo) estudia entidades que no varían indefinidamente, como si lo hacen los números reales.
Sus temas son los números enteros, los conjuntos, los grafos, los lenguajes formales, entre otros. Esta matemática es fundamental para entender el funcionamiento
de los computadores, que son digitales, discretos, y para analizar los algoritmos
que ejecutamos en ellos.
Antes de empezar con las técnicas de análisis y diseño de algoritmos es muy
conveniente repasar varios temas que usaremos frecuentemente.
2.
Los Números Naturales y Enteros
Los números naturales N y los números enteros Z son muy útiles en programación, a menudo usamos varios hechos muy conocidos sobre ellos:
n
∑ i = 1+2+3+4...+n =
i=1
n(n+1)
2
n
∑ (2i − 1)2 = 12 + 22 + 32 . . . + (2i − 1) = n2
i=1
La primera formula fue obtenida por Gauss, dicen que cuando era niño era tan
inquieto que su profesor le ponía a sumar muchos números, por ejemplo todos los
números del 1 al 100:
1 + 2 + 3 + . . . + 100
1
Gauss descubrió que sumándolos dos veces en orden distinto:
1 + 2 + 3 . . . + 99 + 100
100 + 99 + 98 . . . + 2 + 1
101 + 101 + 101 . . . + 101 + 101
|
{z
}
Obtenía 100 veces la suma vertical 101, esto es 10100, que, al dividir por dos1 ,
da la suma correcta de los primeros 100 números naturales, 5050.
Si generalizamos éste ingenioso procedimiento de Gauss, llegamos a la formula:
n
∑i=
i=1
n(n + 1)
2
La segunda identidad fue descubierta por los griegos observando sucesiones
de cuadrados mas grandes:
b b
1 + 3 = 4 = 22
a
b


c c c
 b b c 
1 + 3 + 5 = 9 = 32
a b c


d d d d
 c c c d 


1 + 3 + 5 + 7 = 16 = 42
 b b c d 
a b c d
Estas dos geniales intuiciones de Gauss y de los griegos no prueban las formulas mencionadas pero nos permiten comprender porque son ciertas. Comprendemos porque vemos una analogía gráfica con algo que ya conocemos (sumas
verticales, o cuadrados), pero esto no es suficiente para probar las formulas. La
matemática es más exigente, una prueba debe ser más formal, debe garantizar
que para cualquier n la formula se cumple. Con los algoritmos tenemos la misma situación, la idea básica que nos permite comprender un algoritmo (alguna
analogía gráfica, algún invariante) no nos permite probar que éste va a entregar las
respuestas correctas para cualquier entrada.
Para probar que éstas formulas funcionan correctamente podemos usar el principio de inducción matemática sobre los números naturales.
1 ¿Por
que?
2
2.1.
Principio de Inducción matemática
Con la palabra principio de inducción matemática queremos expresar que es
un hecho evidente, un punto de partida, un axioma que no necesita ser demostrado.
La aritmética ha sido construida a partir de algunos axiomas básicos entre los
cuales se encuentra el de inducción matemática. Recordemos que los formalismos
matemáticos como la aritmética son modelos simbólicos autocontenidos (en la
medida de lo posible) que parten de ciertos axiomas o enunciados que se asumen
ciertos, y, por lo tanto, no hay necesidad de demostrar; éstos constituyen el punto
de partida de todas las demostraciones.
Si la afirmación es cierta para el número 1
Y, si asumiendo que la afirmación es cierta para un
número k>1, se puede probar que también se cumple
para el número k+1
Tenemos que la afirmación es cierta para cualquier n.
Si usamos el cálculo de predicados podemos expresar este principio de una
manera mas formal. Recuerde que en el cálculo de predicados ∀ significa “Para
todo”, y que → representa la implicación lógica.
P(1) es cierto
∀kP(k) → P(k + 1)
Tenemos que: ∀nP(n)
Por medio de éste principio podemos demostrar nuestras dos formulas. Para la
de Gauss tenemos que:
1
P(1) ≡ ∑ i =
1
n(n+1)
|n=1 = 1
2
k
(Esto, es substituyendo n por 1)
Si asumimos que P(k) ≡ ∑ i =
1
k
∑ i + (k + 1) =
1
k+1
∑ i=
1
k(k+1)
2
k(k+1)
2
k(k+1)
2
es cierta
+ (k + 1) (sumamos k+1 a ambos lados)
+ (k + 1) (metemos el termino k+1 dentro de la sumatoria)
3
k+1
∑ i=
1
k+1
∑ i=
1
k+1
∑ i=
1
k(k+1)+2(k+1)
2
(denominador común al lado derecho de la igualdad)
k2 +k+2k+2
2
k2 +3k+2
2
=
(k+1)(k+2)
2
Que equivale a afirmar que la formula se cum-
ple para k+1 !!
Como probamos P(1), y luego, asumiendo P(k) pudimos deducir P(k + 1),
tenemos que ∀nP(n)
La segunda se puede probar de manera similar (hágalo como ejercicio).
2.2.
Segundo principio de inducción matemática
El principio que viene a continuación puede resultar mas fácil de usar:
P(1) es cierto
∀k[P(r), 1 ≤ r ≤ k → P(k + 1)]
Tenemos que: ∀nP(n)
Cuya interpretación es: si la proposición se cumple para todos los números
desde 1 hasta un k preestablecido, y de allí podemos deducir que se cumple para
un k mayor (k+1); entonces la proposición es cierta para todo n. Es importante
resaltar que el primer principio de inducción matemática puede deducirse a partir
de éste segundo principio (Hágalo!).
También es importante recordar que los principios de inducción matemática
pueden deducirse del principio del buen ordenamiento:
Todo conjunto de números naturales no vacío tiene un elemento menor
La importancia de éste segundo principio puede mostrarse intentando demostrar que existen infinitos números primos. O, en una forma mas conveniente para
operar; que para n ≥ 2, n es un número primo o puede expresarse por un producto
de números primos.
Si intentamos el primer principio de inducción aquí tendremos algunos problemas:
4
Base: P(1) no se cumple!, tenemos que empezar desde P(2)
Paso inductivo: P(k) ≡ k es primo o k = ab el producto de dos f actores
¿Como llegamos a P(k + 1)? Es muy difícil. Si usamos el segundo principio
el problema se simplifica mucho.
Partamos asumiendo P(k) ≡ ∀k[P(r), 1 ≤ r ≤ k] En este contexto significa
todo número r entre 2 y k ó es primo o está compuesto por factores primos
Pongamos la meta a la que queremos llegar: P(k + 1) ≡ ∀k[P(r), 1 ≤ r ≤
k + 1] Que en este contexto significa que todo número r entre 2 y k+1 ó es
primo o está compuesto por factores primos
Para llegar a esta meta pensemos en k+1. Este número puede ser primo,
lo que haría a P(k + 1) cierta. Si no es primo lo podemos expresar como
k + 1 = ab. Como P(k) se cumple, tenemos que a y b ó son primos o están
compuestos por factores primos (porque 2 ≤ a ≤ k y 2 ≤ b ≤ k. Esto nos
permite deducir que P(k + 1) es cierta (pienselo bien!).
Una advertencia: para que k + 1 = ab nos permita deducir que 2 ≤ a ≤ k
y 2 ≤ b ≤ k, tenemos que imponer la restricción de que 1 < a < k + 1 y
1 < b < k, pero esto es natural!; quiere decir que los factores a y b no pueden
ser los valores triviales 1 y k+1.
Con estos dos principios de inducción se pueden probar propiedades y formulas
en los números naturales. Si el primer principio de inducción no se puede aplicar
directamente (porque del caso k no se puede llegar al k+1 de una manera sencilla),
se procede a usar el segundo principio.
2.3.
Inducción Estructural
El axioma de inducción matemática en la aritmética no es suficiente para probar todo lo que deseariamos—propiedades de grafos, árboles, programas, etc.—.
Necesitamos una forma general, mas computacional, que se pueda particularizar
para diferentes propósitos. Para lograr esto pensemos en que cualquier estructura
de datos puede definirse de manera recursiva, por ejemplo: una lista ó es vacía, o
es el resultado de añadir un elemento a una lista, un aŕbol o es vacío o es un nodo
que tiene un conjunto de subarboles. Asi como los dos principios de inducción se
pueden probar a partir del principio de buen ordenamiento que se presentó en
5
la sección anterior, en las estructuras definidas recursivamente tenemos siempre
un ordenamiento parcial, con el que se puede probar el siguiente principio de
inducción estructural:
P(base) la proposición se cumple sobre los casos
mínimos (base) de la estructura
Si, asumiendo que P se cumple para todas las
subestructuras de s, se puede probar
que P se cumple para s.
∀t ∈ sub(s)P(t) → P(s)
Tenemos que: ∀eP(e), la proposición se cumple para
todas las estructuras
Otra forma de verlo consiste en pensar en el “tamaño” de la estructura sobre
la que hacemos la inducción: Si, asumiendo que la proposición se cumple para
estructuras de un tamaño menor a k, podemos probar que se sigue cumpliendo
para un tamaño mayor a k, entonces la proposición es correcta.
Este principio se puede ilustrar demostrando que un árbol binario perfecto de
h niveles tiene 2h − 1 nodos:
Base: para el árbol vacío, 20 − 1 = 0 nodos, para un árbol con un solo nodo,
21 − 1 = 1 nodo.
Si asumimos que todo subarbol de A cumple la proposición, entonces, para
(Aizq , Ader ): 2hizq − 1 = nizq y 2hder − 1 = nder (con nizq y nder siendo los
números de nodos). Ahora, como el árbol es perfecto, hizq = hder , lo que
implica que nizq = nder .
Por ser perfecto, el número de nodos de A es, n = nder + nizq + 1 = (2hizq −
1) + (2hder − 1) + 1 = 2 · 2hizq − 1
Como Aizq es el hijo de A tenemos que hizq = h − 1
Luego n = 2 · 2h−1 − 1 = 2h − 1
Para probar programas que operan sobre estructuras de datos es muy conveniente
usar la inducción estructural. Por ejemplo, para invertir una lista:
6
I NVERTIR(m)
if m = NIL
then return NIL
else
return PEGAR(I NVERTIR(T(m)),H(m))
Donde PEGAR concatena dos listas. T retorna la cola de una lista (todos los
elementos, excepto el primero), y H retorna una lista con el primer elemento.
(Recuerde que éste tipo de listas está definido recursivamente: una lista ó es vacía,
o es el resultado de añadir un elemento a una lista). Nuestra demostración de
corrección por medio de inducción estructural sería:
Base: INVERTIR(NIL) funciona correctamente.
Paso inductivo: Si INVERTIR funciona correctamente para listas de tamaño menor o igual a k. Podemos inferir que cuando INVERTIR es llamado
con una lista de tamaño k, el llamado I NVERTIR(T(m)) invierte correctamente a T(m), porque esta lista tendría un tamaño menor a k. Como este
resultado se concatena al primer elemento de la lista, la función invertiría
correctamente a una lista de tamaño k. Luego I NVERTIR es correcta (asumiendo que pegar funciona correctamente).
Como ejercicio, escriba la función pegar, usando a CONS(a,l), una función que
dado un elemento a y una lista l, retorna una lista mas grande con a como primer
elemento y continuando con los elementos de l. Además, pruebe la corrección de
pegar por inducción estructural!
3.
Invariantes para probar algoritmos iterativos
Cuando se escribe un ciclo para calcular la sumatoria de los elementos de un
arreglo no vemos facilmente como usar la inducción matemática o la estructural
que ya hemos aprendido:
SUMATORIA (A)
1
2
3
4
5
suma ← 0
n ← length[A]
for i ← 1 to n
do suma ← A[i]
return suma
7
Aquí, la estrategia para demostrar la corrección del ciclo es distinta y se basa
en:
Demostrar que el algoritmo termina eventualmente.
Encontrar un invariante. Esto es, una relación entre las variables que controlan el ciclo y el resultado que arroja que no varía a través de las iteraciones.
Revisar el valor que toman las variables en la ultima iteración y el invariante.
Estos dos hechos deben garantizar el resultado que se espera del ciclo.
Para el sencillo ciclo anterior podemos proceder así:
Detención: el ciclo For va de 1 a n (el número de elementos del arreglo), asi
que eventualmente se detiene para cualquier arreglo A
i
Invariante: sum = ∑ A[ j] (Revise si esto se cumple antes y después de cada
j=1
iteración!)
En la última iteración el contador que controla el ciclo, i=n. Asi que el invan
riante al final es: sum = ∑ A[ j]. Lo que garantiza que el ciclo es correcto!
j=1
Encontrar invariantes no es una tarea fácil, de hecho, no es una tarea algorítmica.
No existe un algoritmo general que dado cualquier ciclo while produzca un invariante. Pero si usted está escribiendo un algoritmo a partir de una idea ó analogía,
como las intuciones de los griegos y la de Gauss que comentamos, encontrar un
invariante se reducirá a expresar su idea matemáticamente.
En la mayoría de las situaciones tenemos que la entrada debe cumplir ciertas restricciónes, esto es la precondición. Las restricciones que deben cumplir
después de la ejecución del ciclo las denominamos postcondición. En este caso,
cuando realizamos una demostración por medio de un invariante la corrección será parcial, algo así como: si los datos cumplen la precondición la ejecución del
ciclo garantizará la postcondición.
4.
Conteo
4.1.
El principio de multiplicación
¿Cuantos números de placa distintos pueden haber en colombia?
8
30
30
30
10
10
10
Tenemos 30 posibilidades para la primera letra, 30 posibilidades para la segunda letra, 30 posibilidades para la tercera letra. 10 posibilidades para el primer numero, 10 para el segundo y 10 para el último. Esto es 30 × 30 × 30 × 10 × 10 × 10.
Lo que se puede resumir:
Si hay n1 posibilidades para el primer evento, n2 para el
segundo,..., nm para el evento m, entonces hay n1 × n2 . . . ×
nm posibilidades para la secuencia de los m eventos.
Esto se puede aplicar a programas, por ejemplo, ¿cuantas multiplicaciones se
hacen en el siguiente ciclo?
MATRIX-MULTIPLY(A, B)
1 if columns[A] 6= rows[B]
2
then error "incompatible dimensions"
3
else
4
for i ← 1 to rows[A]
5
do for j ← 1 to columns[B]
6
do C[i, j] ← 0
7
for k ← 1 to columns[A]
8
do C[i, j] ← C[i, j] + A[i, k] × B[k, j]
9
return C
En este caso se puede afirmar que el primer ciclo For hace rows[A] iteraciones,
el segundo For hace columns[B] iteraciones y el tercero hace columns[A] iteraciones. Luego, la sentencia que multiplica un elemento de A y otro de B en la línea 8
se ejecuta rows[A] × columns[B] × columns[A] veces!
4.1.1.
Permutaciones
Si las posibilidades para los eventos van descendiendo de uno en uno llegamos
a las permutaciones. Por ejemplo, ¿cuantas claves distintas (que no repitan dígitos)
puede soportar un cajero electrónico?
La respuesta es 10 · 9 · 8 · 7 porque puedo tomar los diez dígitos para el primer
número, pero para el segundo dígito debo considerar solo 9 dígitos para no repetir
9
el primero, 8 para el tercero y 7 para el último. Si las claves tuvieran 10 dígitos
el número sería 10 · 9 · 8 · 7 · 6 · 5 · 4 · 3 · 2 · 1, que es 10!. Es decir, el factorial es un
caso particular del número de permutaciones en el que el número de posibilidades
(dígitos en nuestro ejemplo) es igual al número de eventos (el tamaño de la clave
en nuestro ejemplo).
Asi que los dos parámetros básicos para una permutación son:
número de eventos (r)
número de posibilidades para cada evento (n) [normalmente se asume que
r ≤ n]
Si generalizamos el conteo anterior, obtenemos la formula:
P(n, r) = n(n − 1)(n − 2) . . . (n − r + 1)
Aunque es mas general usar esta formula equivalente (chequeélo!):
P(n, r) =n Pr =
n!
(n − r!)
Recordando que 0! se define como 1, observe que que P(n, n) = n!. Además
P(n, 1) = n
En general P(n, r) significa el número de ordenes posibles para n objetos o
eventos posibles , tomando r cada vez, y prohibiendo repeticiones.
El siguiente algoritmo calcula el número de permutaciones (verifiquelo!):
PERM (n, r)
m←1
for i ← 1 to r
do m ← m × n
n ← n−1
return m
4.1.2.
Combinaciones
En las combinaciones estamos interesados en contar número de ordenes posibles para n objetos, tomando r cada vez (sin prohibir repeticiones). Por ejemplo,
10
¿cuantas manos de poker pueden obtenerse de un mazo de 52 cartas? (cada mano
tiene 5 cartas).
Una mano tiene 5 cartas, pero no importa el orden, el jugador puede organizarlas como desee, asi que 2-3-4-8-7 es la misma mano que 8-7-2-3-4. Observe que
el número de permutaciones de 52 cartas, tomando 5 a la vez no nos sirve, porque
discriminaría diferencias entre manos que, para los jugadores, son la misma. ¡El
número de permutaciones es mucho mas grande que el número de combinaciones!.
El número de combinaciones puede calcularse con el principio de la multiplicación de la siguiente forma. Si denotamos al número de combinaciones C(n, r),
para cada combinación existen r! formas de permutar los r objetos escogidos (por
ejemplo, 5 cartas pueden permutarse de 5! formas distintas). Entonces, el número
de permutaciones, en el que si importa el orden puede dividirse por r! para calcular
el número de combinaciones:
P(n, r)
n
n!
=
C(n, r) =
=
r
r!
r!(n − r)!
4.2.
El principio de la adición
Similarmente, si tenemos eventos disjuntos:
Si hay n1 posibilidades para el primer evento, n2 para el segundo,..., nm
para el evento m, entonces hay n1 + n2 . . . + nm posibilidades para la
secuencia de los m eventos.
Esto se puede aplicar en programas también, ¿dentro de la siguiente función
cuantas veces se hace un llamado recursivo a R ECURSIVE -B INARY-S EARCH)?
R ECURSIVE -B INARY-S EARCH(A, v, low, high)
if low > high
then return NIL
mid ← b(low + high)/2c
if v = A[mid]
then return mid
if v > A[mid]
then return R ECURSIVE -B INARY-S EARCH(A,v,mid+1,high)
else return R ECURSIVE -B INARY-S EARCH(A,v,low,mid-1)
11
La respuesta no es dos veces. Solo se hace un llamado recursivo, ya que los
dos llamados son eventos exclusivos, están controlados por la revisión que hace
el condicional entre v y A[mid]. Bueno, para ser precisos, en algunos casos la
respuesta también puede ser cero, cuando v=A[mid] la función retorna inmediatamente un valor y no hace recursión.
4.3.
El principio del palomar (pigeonhole principle)
Si mas de k palomas se acomodan en k casillas de un palomar, al menos
una casilla tendrá dos palomas
Aunque este principio es muy intuitivo, también es muy poderoso. Por ejemplo, puede ayudar a resolver las siguientes preguntas:
¿Cuantas personas tienen que haber en un salón para garantizar que al menos dos tengan apellidos con la misma inicial?
¿Cuantas veces hay que tirar un dado consecutivamente para obtener el mismo valor dos veces?
¿Que pasa en una tabla hash de tamaño máximo k, cuando insertamos mas
de k datos?
5.
Algebra y conjuntos
Todas las estructuras algebraicas que usamos en computación descansan sobre
la noción de conjunto. Es conveniente recordar algunos conceptos.
Relación: Una relación sobre varios conjuntos es un subconjunto del producto
cartesiano de estos
Relación binaria: Entre A y B, cualquier subconjunto de A × B.
Relación de equivalencia: Cuando en una relación binaria A = B decimos que
el conjunto A (ó el B) tiene una relación sobre si mismo. Si la relación
binaria es reflexiva, simétrica y transitiva, decimos que es una relación de
equivalencia.
12
Conjunto parcialmente ordenado: Un conjunto que tiene una relación de equivalencia sobre si mismo. Se es totalmente ordenado, entonces existe el
elemento mínimo y el elemento máximo.
Clase de equivalencia: Una de las particiones que tiene un conjunto parcialmente ordenado con respecto a una relación de equivalencia.
Función: Es una relación binaria entre A y B con una condición especial. Como
es subconjunto de A × B, es un conjunto de parejas (a, b) con a ∈ A y b ∈ B.
La condición que deben cumplir las funciones es que cada elemento de A
aparezca exactamente una vez como primer elemento de las parejas (a, b).
Se simbolizan: f : A → B, y decimos que A es el dominio y que B es el
codominio. Al conjunto de elementos de B que aparecen en la relación se
les denomina rango.
Función sobreyectiva: Una función cuyo rango es igual al codominio.
Función inyectiva: Una función sobreyectiva entre A y B en la que ningún elemento de B es la imagen de dos elementos distintos de A.
Función biyectiva: Una función sobreyectiva e inyectiva.
Algebra booleana: Un conjunto A con dos funciones binarias +, · y una función
unaria ¬ en la que hay dos elementos distintos 0 y 1. Se deben cumplir
ciertas propiedades conmutativas, asociativas, distributivas, de identidad y
de complemento.
Grupo: Un conjunto A con una función binaria · que es asociativa y que cumple
dos propiedades: existe un elemento identidad (o nulo) y cada elemento
tiene un inverso con respecto a ·. Si la operación binaria · es conmutativa el
grupo es conmutativo.
Cuerpo: Un conjunto A con funciones abstractas suma, resta, multiplicación y
división, que se comportan como éstas funciones sobre los números reales.
Espacio vectorial: Un conjunto de entidades denominadas vectores que tiene dos
funciones binarias sobre si mismo: la suma y el producto vectoriales. Estas operaciones deben cumplir varios axiomas. Los espacios vectoriales se
construyen sobre un cuerpo de entidades, denominadas escalares. Por ejemplo, los polinomios forman un espacio vectorial con respecto a la suma y
multiplicación polinomial; los escalares son los números reales.
13
6.
Estadística y Probabilidad
Algunos conceptos de estadística que utilizaremos:
Media: En una muestra de datos x1 , · · · , xn la media o promedio es:
1 n
1
x̄ = ∑ xi = (x1 + · · · + xn )
n i=1
n
Media ponderada: En una muestra de datos x1 , · · · , xn que tienen asignados unos
pesos w1 , · · · , wn la media o promedio ponderado es:
n
∑ xi wi
x̄ =
i=1
n
∑ wi
i=1
recuerde que así se obtiene su promedio semestral.
Orden estadístico: En una muestra de datos x1 , · · · , xn que están en orden ascendente, el 1er orden estadístico es x1 , el 2do es x2 ; y, en general, el orden
estadístico k es xk .
Algunos conceptos de probabilidad que usaremos:
Variable aleatoria: variable que representa las observaciones que podemos hacer a un evento no determinístico. Puede ser discreta o continua.
Valor esperado: Para una variable aleatoria discreta el valor esperado está dado
por
E(X) = ∑ pi xi
i
donde los pi son las probabilidades de los eventos con resultado xi . El valor
esperado cumple las siguientes propiedades:
E(X + c) = E(X) + c
E(X +Y ) = E(X) + E(Y )
E(aX) = aE(X)
donde a, c son constantes y X,Y son variables aleatorias.
14
7.
Conclusiones
Hemos hecho un muy breve repaso sobre varios temas de matemáticas discretas que usaremos bastante para analizar y diseñar algoritmos.
Por brevedad hay muy pocos ejemplos y las definiciones son muy sucintas,
si ha encontrado algo que no comprende o recuerde, tomése el tiempo de
hacer la búsqueda bibliográfica en un libro de matemáticas discretas, y, para
el concepto de espacio vectorial, en un libro de algebra lineal.
No menosprecie la importancia de recordar cada uno de los conceptos repasados, todos serán usados eventualmente en el curso.
15
Descargar