[Maple Metafile]

Matemática Discreta

Ingeniería Técnica en Informática

de Sistemas y Gestión

ESCET

Prácticas y problemas resueltos con Maple V

Práctica 1

Introducción a la
PROGRAMACIÓN EN MAPLE

Introducción

En la primera práctica de Bases de Matemáticas se han introducido los rudimentos de Maple (primeros comandos, sintaxis básica...), en esta práctica introduciremos las nociones elementales para poder programar con Maple.

El objetivo es que tras esta práctica y un poco de ejercicio por parte del alumno se puedan desarrollar los primeros y elementales procedimientos en maple.

Tipos de datos fundamentales

Para programar en Maple, es fundamental manejar los tipos básicos de datos, como son por ejemplo secuencia , lista  y conjunto , sus características y qué tipos de comandos se pueden aplicar a qué tipo de datos. No entraremos en otros tipos de datos como matrices y arrays. En la ayuda se puede leer la información sobre cada uno de los tipos de datos.

Secuencias

El tipo de datos más básico es la secuencia, una colección ordenada de objetos de Maple separados por comas .

>    sec1:=4,Pi,7.5,E,{1,2,3},x->3*x^2;

sec1 := 4, Pi, 7.5, E, {1, 2, 3}, proc (x) options operator, arrow; 3*x^2 end proc

Se puede introducir cualquier tipo de objetos en una secuencia. Observa que entre los datos de la secuencia de arriba hay números, símbolos, conjuntos...

Puedes acceder a sus elementos escribiendo el lugar que ocupan en la secuencia entre corchetes:

Así por ejemplo el segundo elemento de sec1  es pi.

>    sec1[2];

Pi

El quinto es un conjunto:

>    sec1[5];

{1, 2, 3}

El sexto parece una función:

>    sec1[6];

proc (x) options operator, arrow; 3*x^2 end proc

[Maple OLE 2.0 Object]  Mira ahora más detalles en la ayuda para secuencias.

Detente sobre la ayuda o vuelve sobre ella, es importante ir entendiendo bien los conceptos.

Continuar aquí

Como habrás visto en la ayuda, dos operadores importantes para la generación de secuencias son $  y seq :

Por ejemplo, para construir una secuencia de 10 ceros se puede escribir:

>    0$10;

0, 0, 0, 0, 0, 0, 0, 0, 0, 0

Para construir la secuencia de los 20 primeros números impares:

>    seq(2*i-1,i=1..20);

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39

O los 10 primeros múltiplos de 3:

>    seq(3*i,i=1..10);

3, 6, 9, 12, 15, 18, 21, 24, 27, 30

[Maple OLE 2.0 Object] Mira la ayuda para el comando seq .

Ejercicios.

Después de haber leído detenidamente  la ayuda para secuencias, deberías ser capaz de responder a las siguientes preguntas acerca de la siguiente secuencia:

>    sec1:=4,8,13,{Pi,E,I},seq([k,k+2],k=6..18);

sec1 := 4, 8, 13, {Pi, I, E}, [6, 8], [7, 9], [8, 10], [9, 11], [10, 12], [11, 13], [12, 14], [13, 15], [14, 16], [15, 17], [16, 18], [17, 19], [18, 20]
sec1 := 4, 8, 13, {Pi, I, E}, [6, 8], [7, 9], [8, 10], [9, 11], [10, 12], [11, 13], [12, 14], [13, 15], [14, 16], [15, 17], [16, 18], [17, 19], [18, 20]

(1) ¿ Qué comando te devuelve el séptimo elemento de sec1?

>   

>   

>   

(2)   Escribe un comando que devuelva una secuencia con once palabras `bien`.

>   

>   

>   

(3) Otra manera de hacer esto es....

>   

>   

>   

(4)   Haz una secuencia formada por los cubos X^3 de números naturales que verifican X^3<1000.

>   

>   

Listas

Una lista  es una secuencia contenida dentro de corchetes []. Tanto en secuencias como en listas se pueden repetir elementos, y el orden en el que se escriben los elementos es importante.

>    sec1:=seq(i^4,i=1..5);
lista1:=[seq(i^4,i=1..5)];

sec1 := 1, 16, 81, 256, 625

lista1 := [1, 16, 81, 256, 625]

Dada una lista, puedes acceder a la secuencia de sus elementos mediante el comando op :

>    op(lista1);

1, 16, 81, 256, 625

Para añadir elementos al final de una secuencia, basta escribir una coma y después los elementos que queremos añadir. Pr ejemplo podemos añadir dos a'es al final de la secuencia sec1 :

>    sec2:=sec1,a,a;

sec2 := 1, 16, 81, 256, 625, a, a

Para añadir elementos al final de una lista, hay que extraer la secuencia de sus elementos, añadir los elementos nuevos, y volver a hacer una lista del resultado:

>    lista2:=[op(lista1),muchos,mas];

lista2 := [1, 16, 81, 256, 625, muchos, mas]

Para acceder a los elementos de una lista, se hace de la misma manera que para secuencias. El número de elementos de una lista se puede contar con el comando nops.

>    lista2[2]; nops(lista2);

16

7

>   

Para sustituir elementos en una lista se usa el comando subsop

>    meses:=[enero, febrero, marzo, abril, mayo]:

>    subsop(2=junio,meses);

[enero, junio, marzo, abril, mayo]

>    subsop(3=febrero,meses);

[enero, febrero, febrero, abril, mayo]

Y sirve para borrar elementos de una lista, sustituyendo por NULL

>    subsop(1=NULL,meses);

[febrero, marzo, abril, mayo]

Ejercicios

Como en el caso de las secuencias, realiza los siguientes ejercicios sobre listas:

>    a:=seq(i,i=1..60):

>    s:=2,3,4,5,t,y,j,a,a,l^2;

s := 2, 3, 4, 5, t, y, j, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, ...
s := 2, 3, 4, 5, t, y, j, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, ...
s := 2, 3, 4, 5, t, y, j, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, ...
s := 2, 3, 4, 5, t, y, j, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, ...

(1) Determinar el número de elementos de la secuencia s :

>   

>   

(2) Construir la lista de los 30 primeros cuadrados (esto es, 1^2, 2^2, 3^2....)

>   

>   

( 3) Determinar el término que ocupa el lugar vigésimo en la lista [s].

>   

>   

Conjuntos

Un  conjunto es una secuencia contenida dentro de llaves{}. En un conjunto cada elemento sólo puede aparecer una vez y los datos no están ordenados.

[Maple OLE 2.0 Object] Echa una ojeada a la ayuda para conjuntos.

Podemos definir por ejemplo los conjuntos A y B siguientes. Observa que los elementos repetidos sólo se tienen en cuenta una vez y que el orden no es relevante:

>    restart;

>    A:={1,2,3,4,1,4,5};

A := {1, 2, 3, 4, 5}

>    B:={1,2,1,b,s,b,c,4};

B := {1, 2, 4, b, s, c}

Y se pueden hacer operaciones con conjuntos. Es posible hacer uniones (coleccionar los elementos de ambos conjuntos), intersecciones (coleccionar los elementos que pertenecen simultáneamente a ambos conjuntos) y complementos (tomar los elementos de un conjunto que no están en otro):

>    A union B;

{1, 2, 3, 4, 5, b, s, c}

>    A intersect B;

{1, 2, 4}

>    A minus B;

{3, 5}

Ejercicios.

Definimos los siguientes conjuntos, listas y secuencias:

>    s:={Luisa, Juan, Alicia, Pedro, Susana};

s := {Luisa, Juan, Alicia, Pedro, Susana}

>    t:={Pedro, Julian, Sebastian, Juan, Ana};

t := {Sebastian, Juan, Pedro, Julian, Ana}

>    lista:=[Lunes,Martes,Sabado,Jueves];

lista := [Lunes, Martes, Sabado, Jueves]

>    s1:=g,e,y,d,e,r,f,y,f,d,e,k,y,e,f,g,h,d,y;

s1 := g, e, y, d, e, r, f, y, f, d, e, k, y, e, f, g, h, d, y

>   

(1) ¿Cómo puedes obtener los elementos comunes a s  y t ? ¿Y los elementos de s que no están en t ?

>   

>   

>   

(2) Reemplaza el elemento S abado  por un nuevo elemento Miercoles en lista.

>   

>   

>   

(3) ¿Cómo puedes saber cuántos elementos tiene el conjunto cuyos elementos son los de s1?

>   

>   

>   

(4)   Genera la lista formada por la concatenación de los elementos   de lista   y lista2 (definida abajo)

>    lista2:=[elem1,elem2,elem3];

lista2 := [elem1, elem2, elem3]

>   

>   

>   

( 5) ¿Cuántos números menores que 1000 son a la vez el cuadrado y el cubo de un número entero?

>   

>   

Bucles y condicionales

Bucles

Una de las razones por las que los ordenadores a veces son útiles es su capacidad de repetir la misma tarea rutinaria una y otra vez sin equivocarse.

El elemento sintáctico que realiza estas repeticiones se llama bucle  y suele consistir de dos partes:

en primer lugar un comando o una serie de comandos que queremos ejecutar repetidamente, y luego un comando que controla cuántas veces se ejecuta el bucle.

Condicionales

Por otro lado están las condicionales  de la forma:

 

si  condición entonces  operación1 si no  operación 2

lo que significa que si se verifica la condición entonces se realiza la operación 1 y si no la operación 2. O de la forma:

mientras  condición operación

lo que significa que mientras se verifique la condición ha de realizarse la operación.

Y combinaciones de las mismas. Veremos algunos ejemplos.

Si se verifica la condición se realiza la operación 1, en caso contrario se realiza la operación 2 (si no se indica nada por defecto no se hace ninguna operación).

Generemos un procedimiento que calcula el máximo de dos números.

Los procedimientos en maple se denotan con proc  y se terminan con end . Las variables que se involucran en el procedimiento se definen como locales para que luego se puedan usar fuera de el procedimientos.

Las condicionales se empiezan por if y se terminan con fi.

if  condición then  operación1 else  operación 2 fi

Que significa que si se cumple la condición entonces se realiza la operación 1 y en caso contrario la operación 2. Después de else  pueden abrirse nuevas condicionales que se escriben else if  o de manera más abreviada elif .

Por ejemplo para calcular el máximo de dos números:

>    maximo:=proc(a,b)
local c:
if (a>b) then c:=a else c:=b fi: c;
end:

La primera línea de código asigna un nombre al procedimiento, digamos máximo e indica que va a actuar sobre dos números a  y b

La variable c  que va a ser la salida se define como una variable local, esto es, sólo se considera dentro del procedimiento.

La sentencia condicional es exactamente la elección del máximo.

Como c va seguida de un punto y coma, será lo que se vea en la pantalla, la asignación a la salida..

El comando end  termina el procedimiento.

 

>    maximo(2,4);

4

Veamos un procedimiento que indica el signo de un número real:

>    signo:=proc(a)
local s;
if a<0 then s:=menos elif a=0 then s:=0 else s:=mas fi:
s; end:

>    signo(27);

mas

>    signo(-23);

menos

>    signo(0);

0

>   

>   

El Bucle "for"

Como en muchos lenguajes de programación, los bucles for y while (mira la ayuda) sirven para la iteración de comandos, de manera parecida al comando seq.

En Maple, la forma general de un bucle es la siguiente:

for   variable   from   inicio  by   salto  to   final  while   expresión  do    operaciones  od

Cuando Maple encuentra este comando, primero asigna el valor inicio  a la variable. Si se cumple expresión ,  ejecuta las sentencias  entre do  y od . A continuación, se hayan ejecutado las  sentencias o no, incrementa la variable  por el valor del salto  (¡que puede perfectamente ser negativo!), y compara el nuevo valor de variable  con  final.
Si variable no es mayor (en el caso de ser salto positivo) respectivamente menor (si
salto  es negativo) que final, y se cumple la condición que señala el while , ejecuta otra vez sentencias,  y así sucesivamente.

Si omitimos algunas de estas cláusulas, Maple les asigna un valor por defecto:

inicio  ---->1

salto  ---->1

final   ----> + infinity

expresión  ---->true

Por ejemplo para sumar los números del 1 al 10000.

>    S:=0:
for i from 1 to 10^4 do
    S:=S+i:
od:
S;

50005000

Que coincide con el valor de la suma de los términos de una sucesión aritmética:

>    (10^4)*(10^4+1)/2;

50005000

Para sumar los elementos de una lista numérica:

>    a:=[1,2,3,4,5,6,7,8];

a := [1, 2, 3, 4, 5, 6, 7, 8]

>    S:=0:
for i from 1 to nops(a) do
S:=S+a[i]:
od:
S;

36

>   

>   

Primeros programas en Maple

Suma de los términos de una sucesión

En la sección anterior fuimos capaces de sumar los elementos de una lista, esto lo podemos hacer como un procedimiento y así poder llamarlo cuando lo necesitemos:

>    restart;

>    suma:=proc(A::list)
local S,i:
S:=0:
for i from 1 to nops(A)
  do
    S:=S+A[i]:
  od:
S;
end:

Se puede declarar el tipo de variables que usa el procedimiento y así hemos considerado A  como una lista. Esto ayuda a determinar los errores en un procedimiento pues si introducimos variables no adecuadas manda mensaje de error. Puedes consultar la ayuda para ver los distintos tipos de variables.

>    ?type;

>    suma(2,3,4,5,6,6);

Error, invalid input: suma expects its 1st argument, A, to be of type list, but received 2

Lo aplicamos a una sucesión aritmética cuyo primer término es a  y la diferencia entre dos consecutivos es d . La lista de los 50 primeros términos es:

>    L:=[seq(a+i*d,i=1..50)]:

Y su suma es:

>    suma(L);

50*a+1275*d

>   

Generar coordenadas de un rectángulo

Por ejemplo, queremos escribir una subrutina que tome como entrada un valor x y una altura h y que nos devuelva las coordenadas de un rectángulo cuyos lados estén paralelos a los ejes de coordenadas, que tenga anchura 0.5 y altura h ,  y cuyo borde inferior esté en el eje de las x  y centrado sobre el punto ( x ,0).

La primera línea de la subrutina especifica su nombre y los argumentos de entrada:

rectangulo:=proc(x,h::positive)

Esta línea de código informa a Maple que queremos escribir una subrutina  que se llama rectangulo y que toma como argumentos a x  y a h  . Si no se especifica el tipo de argumentos, maple acepta cualquiera. Especificamos h positivo.

El código que ejecuta la subrutina será el siguiente. No queremos nada más que la lista de las coordenadas de los extremos del rectángulo, las cuales a su vez consisten de listas de dos valores.  

>    rectangulo:=proc(x,h)
[[x-.25,0],[x+.25,0],[x+.25,h],[x-.25,h]]:
end;

rectangulo := proc (x, h) [[x-.25, 0], [x+.25, 0], [x+.25, h], [x-.25, h]] end proc

Después de acabar la definición de la subrutina mediante la palabra clave "end", Maple nos confirma el código que ha sacado en claro de nuestra entrada. Si no se quiere esta información se puede terminar el procedimiento con los dos puntos, esto es, end:

Probemos unos ejemplos:

>    rectangulo(-2,3);

[[-2.25, 0], [-1.75, 0], [-1.75, 3], [-2.25, 3]]

>    rectangulo(0,0);

[[-.25, 0], [.25, 0], [.25, 0], [-.25, 0]]

>   

Y se pueden representar gráficamente:

>    with(plots):
polygonplot(rectangulo(5,3));

Warning, the name changecoords has been redefined

[Maple Plot]

>   

>   

Búsqueda

Para buscar un elemento b en una lista a introducimos la lista y el elemento y vamos recorriendo la lista comparando con el elemento, continuando la ejecución del bucle si son distintos. Si el bucle se detiene antes de recorrer toda la lista la salida es sí y en caso contrario no. Desarrollaremos otros algoritmos de búsqueda.

>    busqueda:=proc(a::list,b::numeric)
local i,c:
c:=0:
for i from 1 to nops(a) while c=0
  do
     if a[i]=b then c:=1 fi:
  od:
if c=0 then c:=No else c:=Si fi:
c; end:

Veamos algunos ejemplos:

>    busqueda([1,2,3,4,7,8],8);

Si

>    busqueda([1,2,3,4,7,8],9);

No

>    busqueda([1,4,5,6,7,9,10],5);

Si

>    busqueda([1,3,4,5,2,3,4,8],4);

Si

>    busqueda([1,3,4,5,2,3,4,8],8);

Si

>   

>   

>   

Media aritmética  

La media aritmética no es más que el cociente entre la suma de los elementos de la lista y el número de elementos, entonces:

>    media:=proc(a::list)
local S,i:
S:=0:
for i from 1 to nops(a)
  do
     S:=S+a[i]
  od:
S/nops(a);
end:

>    media ([1,2,3,4,5,6]);

7/2

>   

Prueba con otros ejemplos.

>   

>   

Máximo

Podemos hacer un procedimiento para calcular el máximo de una lista de números. Sencillamente definimos una variable M donde inicialmente se almacena el valor del primer elemento de la lista y que se va comparando con cada elemento de la lista cambiando su valor por él si es necesario.

>    Maximo:=proc(a)
local c,i:
c:=a[1]:
for i from 2 to nops(a)
  do
    if c<a[i] then c:=a[i] fi:
  od:
c;
end:

Veamos algunos ejemplos.

>    Maximo([44,55,6,7,10]);

55

>    Maximo([45,789,10^6,45,6]);

1000000

Puedes probar con otros ejemplos.

>   

>   

Ejercicios

(1) Diseña un procedimiento para dada una lista L y dos enteros a  y b  tales que 0<a<b<nops( L ) calcular el producto de los elementos de L entre el a'ésimo y el b'ésimo.

>   

>   

(2) Diseña un procedimiento para saber qué lugares ocupa un elemento que está en una lista.

>   

>   

(3) Diseña un procedimiento para, dadas dos conjuntos A y B construir el producto cartesiano AxB.

>   

>   

Práctica 2

PRÁCTICA 2

 TEORÍA DE NÚMEROS  

[Maple OLE 2.0 Object]

1. Introducción

Instrucciones

1. Lee con atención el texto. Cuando aparezcan comandos o procedimientos de Maple (líneas en rojo), intenta averiguar para qué sirven (puedes emplear la ayuda de Maple) y después ejecútalos. Puedes ejecutarlos varias veces y cambiar en ellos lo que te parezca para entenderlo mejor o mejorarlo.

2. Párate cada vez que aparezca la señal [Maple OLE 2.0 Object]  y trata de responder a la cuestión propuesta.

3. Lee los puntos 1 y 2 de la práctica. Después realiza el test. El punto número 3, de aplicaciones, puedes leerlo fuera de horario de la práctica para ver distintas aplicaciones de lo estudiado.

Contenidos

Teóricos:

-   Aritmética modular

- Máximo común divisor y mínimo común múltiplo

- Teorema chino del resto

- Factorización de enteros

- Test de primalidad

- La función de Euler

Aplicaciones :

- Criptografía clásica

- Criptografía de clave pública

Maple dispone de un paquete de funciones específicas para la Teoría de Números , numtheory , que cargaremos con la instrucción:

>    with(numtheory):

Warning, the protected name order has been redefined and unprotected

>   

2. Fundamentos

2.1. Aritmética modular

Para calcular el resto de la división de dos números enteros a,b  se usa el comando mod.

>    5 mod 3;

2

>    10375378 mod 124903;

8429

Para resolver congruencias lineales en una indeterminada, podemos usar msolve   .

Por ejemplo, supongamos que queremos resolver el siguiente problema: ¿Por qué número debo multiplicar 3 para obtener 1 módulo 7 ?  

>    msolve(3*y=1,7);

{y = 5}

De esta forma hemos resuelto la congruencia puesto que:

>    3*5-1 mod 7;

0

Ahora resolvamos un problema similar cambiando 7 por 6:

>    msolve(3*y=1,6);

>   

Parece que Maple ha fallado, pero en realidad no ha aportado ninguna solución porque no existe.

Para comprobarlo observemos la lista de los distintos productos por 3 módulo 6 y veamos que ninguno es igual a 1.

>    seq(3*i mod 6,i=0..5);

0, 3, 0, 3, 0, 3

>   

[Maple OLE 2.0 Object] ¿Cuál es la razón de que no tenga solución esta ecuación y sin embargo sí la tenga la anterior?

2.2. Máximo común divisor. Mínimo común múltiplo

La función igcd  ( i nteger g reatest c ommon d ivisor) de Maple sirve para calcular el máximo común divisor de un conjunto de enteros. En clase hemos definido el máximo común divisor de dos números pero la definición se amplía naturalmente para definir el mcd(a1,...,a_n)  como el máximo del conjunto de divisores comunes a a1, ..., an.   

Veamos algunos ejemplos de uso de la función igcd  y otras funciones relacionadas:

>    igcd(3,6);

3

>    igcd(6,4,12);

2

Para calcular el máximo común divisor de todos los enteros entre 10 y 100 hacemos:

>    igcd(seq(i,i=10..100));

1

Y debe ser 1 porque entre el 10 y el 100 hay números primos.

La función ilcm  ( i nteger l east c ommon m ultiple) permite calcular el mínimo común múltiplo (el menor de los múltiplos comunes):

>    ilcm(101,13);

1313

>    ilcm(6,4,12);

12

>    ilcm(seq(i,i=10..100));

69720375229712477164533808935312303556800

>   

[Maple OLE 2.0 Object] Comprueba con varios ejemplos la relación que existe entre el máximo común divisor, el mínimo común múltiplo y el producto de dos números enteros :  

a.b = mcd(a,b). mcm(a,b).

El comando is de la línea siguiente determina si dos expresiones son iguales.

>    is(125*3490=ilcm(125,3490)*igcd(125,3490));

true

>   

>   

Recuerda que la verificación de una igualdad en unos cuantos ejemplos no es una demostración, sólo nos convence de que la fórmula parece verdadera, no demuestra su veracidad.

Las funciones gcd  y lcm  de Maple calculan el máximo común divisor y mínimo común múltiplo respectivamente de polinomios. También pueden usarse con números enteros, ya que éstos pueden considerarse polinomios, pero las funciones igcd  e ilcm  lo hacen de forma más eficiente.

El máximo común divisor de dos números se puede expresar como combinación lineal de éstos con coeficientes enteros (Lema de Bezout). Por ejemplo, el máximo común divisor de 3 y 5 , que es 1, se expresa como:  

>    2*3-1*5;

1

>   

Los coeficientes 2 y (-1) se obtienen del algoritmo de Euclides para calcular el máximo común divisor. La función igcdex  de Maple calcula estos coeficientes, si damos como parámetros los nombres de las variables a las que queremos que asigne dichos valores:

>    igcdex(3,5,a,b);

1

>    a,b;

2, -1

>   

Otro ejemplo:

>    igcd(324,779);

1

>    igcdex(324,779,x,y); x; y;

1

-113

47

>    324*x+779*y;

1

>   

2.3. Teorema chino del resto

Maple se puede usar para resolver sistemas de congruencias mediante el teorema chino del resto.

Observa el siguiente ejemplo:

Para resolver el sistema formado por las tres congruencias siguientes,

X = 2 (mod 3)

X = 3 (mod 5)

X = 2 (mod 7)

empleamos la función chrem  ( ch inese rem ainder theorem) del siguiente modo:

>    chrem([2,3,2],[3,5,7]);

23

>   

La primera lista contiene los segundos miembros de las igualdades y la segunda los módulos respectivos.

Utiliza esta instrucción para encontrar un entero que sea congruente con 5 módulo 2, con 4 módulo 7 y con 3 módulo 11.

>   

>   

2.4. Factorización de enteros

Para descomponer números enteros en sus factores primos debemos cargar el paquete numtheory  (si no lo hemos hecho antes).

>    with(numtheory);

[GIgcd, bigomega, cfrac, cfracpol, cyclotomic, divisors, factorEQ, factorset, fermat, imagunit, index, integral_basis, invcfrac, invphi, issqrfree, jacobi, kronecker, lambda, legendre, mcombine, mersen...
[GIgcd, bigomega, cfrac, cfracpol, cyclotomic, divisors, factorEQ, factorset, fermat, imagunit, index, integral_basis, invcfrac, invphi, issqrfree, jacobi, kronecker, lambda, legendre, mcombine, mersen...
[GIgcd, bigomega, cfrac, cfracpol, cyclotomic, divisors, factorEQ, factorset, fermat, imagunit, index, integral_basis, invcfrac, invphi, issqrfree, jacobi, kronecker, lambda, legendre, mcombine, mersen...
[GIgcd, bigomega, cfrac, cfracpol, cyclotomic, divisors, factorEQ, factorset, fermat, imagunit, index, integral_basis, invcfrac, invphi, issqrfree, jacobi, kronecker, lambda, legendre, mcombine, mersen...

La función ifactor  descompone un número entero en sus factores primos:

>    ifactor(100);

``(2)^2*``(5)^2

>    ifactor(12345);

``(3)*``(5)*``(823)

>    ifactor(39248675928359283654928364);

``(2)^2*``(233)*``(42112313227853308642627)

>    h:=2^33*3^55;

h := 1498507312194348653688681968009478144

>    ifactor(h);

``(2)^33*``(3)^55

>   

Los algoritmos de  factorización de números enteros son muy poco efectivos, números de tamaño muy grande hacen que el programa se quede bloqueado. Si quieres probar, graba primero lo que has hecho hasta ahora  e intenta factorizar, digamos, el número 1+2^200. Recuerda que la señal de STOP en la barra de instrucciones detiene un cómputo.

>   

>   

>   

 

2.5. Test de primalidad

Obtener números primos grandes es muy importante en criptografía como se puede ver en la sección de aplicaciones. Aquí mostraremos algunas de las capacidades de Maple para encontrar números primos. Hemos visto ya cómo factorizar un número entero en sus factores primos. En consecuencia, podríamos usar como test de primalidad de un número su descomposición en factores. Si al factorizar el número a  el resultado es el mismo número a, el número es primo. Esto constituye un test de primalidad:

>    with(numtheory):

>    Testprimo1:=proc(a)
local i,s,c:
s:=0:
for i from 2 to a-1 while s=0 do
   if a mod i = 0 then  s:=1 fi:  
od:
if i<a then c:=compuesto else c:=primo fi:
c;
end:

Veamos algunos ejemplos:

>    Testprimo1(9);

compuesto

>    Testprimo1(17);

primo

>    Testprimo1(34567890);

compuesto

>   

En cualquier caso, como decíamos antes, este método es muy  poco eficiente. Actualmente apenas se pueden factorizar números de 100 cifras, y factorizar un número de 200 cifras es impensable (se necesitarían millones de años de cálculo con los mejores computadores para hacerlo).

En consecuencia, en lugar de intentar emplear métodos directos de factorización, para averiguar si un número es primo se emplean métodos probabilísticos. La función isprime  de Maple está basada en éstos métodos. Cuando responde true  significa que el número evaluado es primo con una probabilidad muy alta, pero sin garantizar al 100% el que lo sea.

>    isprime(101);

true

>    isprime(2342138342111);

true

>    isprime(23218093249834217);

false

>   

[Maple OLE 2.0 Object] Como éste número no es muy grande, puedes comprobar factorizándolo que, en efecto, no es primo.

>   

>   

>   

>   

>   

La función ithprime  calcula el i -ésimo número primo. Esto es, el primo que ocupa el lugar i  en la lista creciente de los números primos. Los primeros números primos son 2, 3, 5, 7, 11, ... pero ¿cuál es el que ocupa el lugar 3000 en la lista de todos los primos?

>    ithprime(1);ithprime(2);ithprime(3);

2

3

5

>    ithprime(3000);

27449

>   

>   

Esta función puede usarse para generar números primos. También pueden utilizarse las funciones   nextprime  y prevprime  , que, como su nombre indica, calculan respectivamente el número primo más próximo mayor y menor al número dado.

>    nextprime(1000);

1009

>    prevprime(1000);

997

>    nextprime(13);

17

Observa que si el número es primo nextprime  te da el siguiente primo y prevprime  el primo anterior.

Conviene tener en cuenta que las funciones nextprime  y prevprime  están basadas en la función isprime , por lo que no podemos garantizar el resultado, aunque la probabilidad de que sea correcto es muy elevada.

Terminamos observando que la lista de números primos no se conoce, esto es, no hay una manera de determinar el primo enésimo. Es uno de los grandes problemas no resueltos de la matemática.

2.6. La función phi  de Euler

La función phi  de Euler phi(n)  (del paquete numtheory) computa el número de enteros positivos menores o iguales que n  y que son relativamente primos con n  (cuenta el 1  porque mcd(1,n)=1 ). Obsérvese que phi(n) = n-1  si y sólo si n  es primo. Así podemos determinar, mediante la función phi , la primalidad de n . Sin embargo, nuevamente, no es un test eficiente.

>    phi(1);

1

>    phi(2);

1

>    phi(10);

4

Este número, phi(10) , es exactamente el número de elementos del conjunto de números positivos menores que 10 y relativamente primos con 10, a saber, {1,3,7,9}.

>    is(phi(13)=12);

true

Esto indica que 13 es un número primo.

>    phi(5);

4

>    phi(10);

4

>    phi(107);

106

Así construimos otro test de primalidad:

>    Testprimo2:=proc(a)
local c:
if is(phi(a)=a-1)=true then c:=si else
c:=no fi: c; end:

Veamos algunos ejemplos:

>    Testprimo2(37);

si

>    Testprimo2(5);

si

>    Testprimo2(107);

si

>    Testprimo2(32);

no

Si queremos determinar todos los números naturales k  tales que phi(k) = n  , esto es, todos aquello números naturales k  con exactamente n  números a<k  primos con k , podemos usar la función invphi  de Maple. Por ejemplo,

>    invphi(2);

[3, 4, 6]

>   

Los únicos números cuyo valor de phi es 2 son el 3, el 4 y el 6.

>    phi(3),phi(4),phi(6);

2, 2, 2

>   

Otro ejemplo:

>    s:=invphi(6);

s := [7, 9, 14, 18]

>    p:=[]:
for i from 1 to nops(s) do
p:=[op(p),phi(s[i])]: od: p;

[6, 6, 6, 6]

>   

3. Aplicaciones

En esta sección veremos algunas aplicaciones de la aritmética modular y las congruencias.

3.1. Criptografía clásica

Vamos a emplear ecuaciones lineales en congruencias para cifrar y descifrar mensajes como lo hacía Julio César durante la guerra de las Galias.

Necesitamos convertir letras en números, para lo cual emplearemos la función letranumero.

Para asignar un número a cada letra definimos la función letranumero, antes debemos escribir la siguiente línea porque I y E tienen valores preasignados:

>    alias(I=I); alias(E=E);

Error, use interface(imaginaryunit=...) to set the imaginary unit

El alfabeto será:

>    alfabeto:=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","Ñ","O","P","Q","R","S","T","U","V","W","X","Y","Z"]:

Y la función letranumero es, en general:

>    letranumerogen:=proc(a::list)
local i:
for i from 1 to nops(a) do
letranumero(a[i]):=i-1;
od: end:

En nuestor ejemplo

>    letranumerogen(alfabeto): letranumero("U");

21

>   

También necesitamos convertir números en letras. Para ello emplearemos la función inversa numeroletra :

>    numeroletragen:=proc(a::list,b::list)
local i:
for i from 0 to nops(b) do
numeroletra(i):=a[i+1];
od: end:

En nuestro ejemplo:

>    numeroletragen(alfabeto,[seq(i,i=0..nops(alfabeto)-2)]):
numeroletra(21);

>   

Un encriptador afin clásico es de la forma:

f(p) = (ap + b) (mod 26)

donde (a,b)  es la clave de cifrado (que nadie más que el emisor y el receptor debe conocer). El entero p  es el número correspondiente a una letra, y el número f(p)  es el correspondiente a esa letra encriptada. Para poder desencriptar un mensaje es preciso elegir la clave de forma que la función f  sea biyectiva.

[Maple OLE 2.0 Object] ¿Cuál es la condición para que eso ocurra, esto es, para que f  tenga inversa?

Emplearemos una función auxiliar Encripletra  para encriptar una sola letra. La ayuda te puede aclarar sobre el tipo de datos string:

>    Encripletra:=proc(s::string,clave::[integer,integer])
 local factor,incremento;
 if not length(s) = 1 then
   ERROR(`el argumento debe ser una sola letra`);
 fi;
 factor:=clave[1];
 incremento:=clave[2];
 RETURN(numeroletra((letranumero(s)*factor+incremento) mod 26));
end:

>   

La función de encriptado aplica mediante un bucle la función Encripletra a cada letra de la palabra que se va a encriptar:

>    Encripta := proc(s::string, clave::[integer,integer])
 local i,textocifrado;
 textocifrado:=NULL;
 for i from 1 to length(s) do
  textocifrado:= cat(textocifrado,
         Encripletra(substring(s,i..i),clave));  
 od;
 RETURN(textocifrado);
end:

>   

Una prueba:

>    Encripletra("A",[3,5]);

>    Encripta("QUIENSABEDONDE",[3,7]);

>   

[Maple OLE 2.0 Object]

Una vez enviado el mensaje encriptado debemos desencriptarlo, calculando por la inversa de f  y la operación letra número la palabra de que proviene el mensaje anterior.

>   

>   

>   

3.2. Criptografía de clave pública

Veremos ahora cómo implementar con Maple el sistema RSA de encriptado, que se explica a continuación. Construiremos procedimientos de Maple para generar claves, para encriptar y para descifrar mensajes.

Haremos una simplificación para hacer más ágil la práctica: en lugar de emplear números primos grandes (para que el sistema sea seguro conviene emplear dos números primos de 100 cifras) lo haremos con números más pequeños, sino las operaciones tardarían mucho tiempo.

 

Generación de claves

En primer lugar debemos obtener dos números primos grandes p  y q  . Con ellos generamos la clave pública que consta de n = pq  , y el exponente e. Se genera también la clave privada que consta de n  , y el inverso de e  módulo phi(n) , donde phi es la función de Euler. El número e  no tiene relación con los números p  y q . Se puede generar de muchas maneras. Dos valores clásicos para e  en los sistemas reales son 13 y el cuarto número de Fermat F4 = 2^2^4 + 1 = 65537. En nuestro caso tomaremos e  = 13. A n le llamamos módulo.

>    Generaclaves:=proc(p::integer,q::integer)
 local n, #modulo
       e, #exponente
       d, #d*e=1 (mod phin)
    phin; #phi(n)=(p-1)(q-1)   

n:=p*q;   #calcula el modulo (publico)
phin:=(p-1)*(q-1);
e:=13;    #este numero se podria generar aleatoriamente

#calculamos d tal que e*d=1 (mod phin)
d:=op(1,op(Roots(e*x-1) mod phin));

RETURN([[n,e],[n,d]]);
end:

>   

Veamos un ejemplo:

>    Generaclaves(43,59);

[[2537, 13], [2537, 1]]

Efectivamente cumplen lo que deben:

>    is(2537=43*59); is(13*937 mod phi(2537)=1);

true

true

Función de cifrado y descifrado

Ahora que sabemos generar claves, vamos a ver el método RSA de encriptado. El código es sencillo:

>    RSA:=proc(key,msg::list(posint))
  local ct, #texto cifrado obtenido
        pe, #exponente (público)
        pm, #modulo (público)
         i; #índice del bucle
  pm:=key[1];
  pe:=key[2];
  ct:=[];
  for i from 1 to nops(msg) do
    ct:=[op(ct),msg[i]^pe mod pm];
  od;

  RETURN(ct);
end:

En la línea 10 del código del procedimiento RSA está la idea de la encriptación, toma el número que ocupa el lugar i  en el mensaje lo eleva a pe  y calcula el resto módulo 13.

El primer argumento del procedimiento RSA es la clave. El segundo argumento es el mensaje que queremos encriptar, en forma de lista de enteros positivos. Para ver cómo funciona se lo aplicamos a un ejemplo concreto.

 

Ejemplo

Veamos cómo utilizar el sistema RSA para transmitir un mensaje:

Primero debemos codificar el mensaje en forma de lista de enteros positivos. Para ello podemos asignar a cada letra del alfabeto un número de dos cifras (por ejemplo A-> 10 , B-> 11, etc.). A continuación troceamos la lista numérica obtenida en bloques de 4 dígitos cada uno. La lista de esos bloques constituye la entrada para el procedimiento RSA de encriptado. La elección de la longitud de los bloques ha de escogerse de forma que, después de la conversión, el entero mayor obtenido sea menor que el módulo n .

Primero asignamos a cada letra un número de dos cifras (empezaremos por el 10 por comodidad) y al

espacio en blanco otro número para separar palabras.

>    alias(I=I);
alias(E=E);
alfabeto:=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","Ñ","O","P","Q","R","S","T","U","V","W","X","Y","Z"," "]:
for i from 1 to nops(alfabeto) do
 letranumero(op(i,alfabeto)):=i+9:
od:

Error, use interface(imaginaryunit=...) to set the imaginary unit

>   

Ahora definimos un procedimiento para transformar el mensaje en una lista de enteros de cuatro cifras (el mensaje debe tener un número par de caracteres, es decir, letras mayúsculas o espacios en blanco),

>    bloques:=proc(msg::string)
 
 local i,listabloques;
 i:=1;listabloques:=[];
 while i < length(msg) do
   listabloques:=[op(listabloques),                     letranumero(substring(msg,i..i)) * 100 + letranumero(substring      (msg ,i+1..i+1))]:i:=i+2:
 od;
RETURN(listabloques);
end:

>   

>    bloques("HOLA QUE TAL");

[1725, 2110, 3727, 3114, 3730, 1021]

Ahora vamos a generar una clave para poder utilizarla (nadie debe saber qué números primos estamos usando para crearla):

>    Generaclaves(83,61);

[[5063, 13], [5063, 1]]

>   

Cuando alguien quiera enviarnos el mensaje "HOLA QUE TAL" de forma cifrada, debe usar nuestra clave pública, [5063, 13]

que previamente debemos comunicarle. La forma de hacerlo es la siguiente:

>    RSA([5063, 13],bloques("HOLA QUE TAL"));

[2780, 980, 2926, 3809, 119, 798]

>   

De esta forma, el mensaje que nos enviarán será: [2780, 980, 2926, 3809, 119, 798]

y no importa que nadie lo lea, porque no serán capaces de entenderlo.

Para desencriptar el mensaje, usamos nuestra clave privada, que es el segundo elemento de nuestra clave RSA, de la siguiente forma, aplicando nuevamente RSA:

>    RSA([5063, 757],[2780, 980, 2926, 3809, 119, 798]);

[1725, 2110, 3727, 3114, 3730, 1021]

>   

Como vemos esta lista se corresponde con el mensaje "HOLAQUETAL":

>    bloques("HOLA QUE TAL");

[1725, 2110, 3727, 3114, 3730, 1021]

>   

[Maple OLE 2.0 Object] Bueno, emplea los primos más próximos a 100 y a 200 por exceso para generar la clave con la que está encriptado el siguiente mensaje. Así podrás descifrarlo.

[14137, 9386, 5968, 14663, 5968, 13217, 4978, 19246, 14883, 19678, 12414, 18783, 9429, 9697, 5054, 14873, 14328, 9322, 4978, 902, 9322, 7574, 17915, 20189, 13557, 13652, 5269, 2068, 7436]
[14137, 9386, 5968, 14663, 5968, 13217, 4978, 19246, 14883, 19678, 12414, 18783, 9429, 9697, 5054, 14873, 14328, 9322, 4978, 902, 9322, 7574, 17915, 20189, 13557, 13652, 5269, 2068, 7436]

4. Test resuelto del curso 2000/2001

>   

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    igcd(5643,985798); igcdex(5643,985798,a,b): a; b;

11

40529

-232

>   

>   

>   

>    chrem([44,-8,25,0],[99,50,31,13]);

614042

La respuesta correcta es la b).

>   

>   

>   

>    [nextprime(10^6),nextprime(2*10^6),nextprime(3*10^6)];

[1000003, 2000003, 3000017]

La respuesta correcta es la c).

>   

4. Calcula cuántos números primos hay entre 100.000 y 200.000.

>   

>    c:=0; for i from 10^5 to 2*10^5 do
if isprime(i) then c:=c+1 fi; od; c;

c := 0

8392

La respuesta correcta es la b).

>   

5. Sea la función f(n)=n^17 mod 17. Señala la respuesta correcta:

>   

>    seq([n,n^(17) mod 17], n=0..16);

[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9], [10, 10], [11, 11], [12, 12], [13, 13], [14, 14], [15, 15], [16, 16]

La respuesta correcta es la a).

>   

>   

>   

>    restart; with(numtheory): c:=0; for i from 0 to 10^3 do
if isprime(i^2+i+41) then c:=c+1 fi; od; evalf(100*c/1001);

Warning, the protected name order has been redefined and unprotected

c := 0

58.14185814

La respuesta correcta es la c).

>   

7. Y en el conjunto {g(0),g(1),...,g(10.000)}, ¿cuál es el porcentaje de números primos?

>   

>    restart; with(numtheory): c:=0; for i from 0 to 10^4 do
if isprime(i^2+i+41) then c:=c+1 fi; od; evalf(100*c/10001);

Warning, the protected name order has been redefined and unprotected

c := 0

41.48585141

La respuesta correcta es la c).

>   

>   

>    (1513 mod 7, 1513 mod 13, 1513 mod 19);

1, 5, 12

>    (1206 mod 7, 1206 mod 13, 1206 mod 19);

2, 10, 9

La respuesta correcta es la c).

9. La función f(p)=77p+42 (mod 98) es:

>   

>    {seq(77*p+42 mod 98,p=0..97)};

{0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91}

La respuesta correcta es la c).

10. Los números menores que 1000 que tienen exactamente 100 números más pequeños que son relativamente primos con ellos:

>   

>    invphi(100);

[101, 125, 202, 250]

La respuesta correcta es la a).

>   

5. Test resuelto del curso 2001/2002

 

1.   Dados los números enteros 712504 y 985898 determinar el conjunto de divisores comunes a ambos y su mcd.

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    ifactor(712504);ifactor(985898); igcd(712504,985898);

``(2)^3*``(13)^2*``(17)*``(31)

``(2)*``(17)*``(107)*``(271)

34

>   

>   

>   

>    chrem([42,-8,25,0],[99,50,17,13]); 99*50*17*13;

841542

1093950

La respuesta correcta es la c).

>   

3. Determina el número de múltiplos de 13 que hay entre el 115218 y el 369214 (ambos inclusive).

>   

>    c:=0: for i from 115218 to 369214 do
if (i mod 13)=0 then c:=c+1 fi od: c;

19539

La respuesta correcta es la a).

>   

4. Calcula el porcentaje de números primos entre el 30.000 y el 40.000 (ambos inclusive)

>   

>    c:=0: for i from 3*10^4 to 4*10^4 do
if isprime(i) then c:=c+1 fi; od; evalf(c/10001);

.9579042096e-1

La respuesta correcta es la b).

>   

5. Sea la función del conjunto cociente de Z por la relación de congruencia módulo 13 en sí mismo dada por la fórmula f(n)=n^13+1 mod 13. Señala la respuesta correcta:

>   

>    seq([n,n^(13)+1 mod 13], n=0..12);

[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10], [10, 11], [11, 12], [12, 0]

La respuesta correcta es la b).

>   

6. Sean las congruencias 3x+1 congruente con 5 módulo 7 y 2x+3 congruente con 7 módulo 11.

>   

>    msolve(3*x+1=5,7); msolve(2*x+3=7,11);

{x = 6}

{x = 2}

>    {seq(7*i+6,i=1..100)}intersect{seq(11*i+2,i=1..100)};

{13, 90, 167, 244, 321, 398, 475, 552, 629, 706}

>   

>   

La respuesta correcta es la c).

>   

7. Determinar la cantidad de números enteros menores o iguales que 1000 relativamente primos con 1000.

>   

>    phi(1000);

400

La respuesta correcta es la a).

>   

>   

>    (1513 mod 11, 1513 mod 13, 1513 mod 17);

6, 5, 0

>    (1206 mod 11, 1206 mod 13, 1206 mod 17);

7, 10, 16

La respuesta correcta es la b).

9. El inverso de 7 módulo 5, el de 4 módulo 9 y el de 8 módulo 11 son:

>   

>    msolve(7*x=1,5);msolve(4*x=1,9);msolve(8*x=1,11);

{x = 3}

{x = 7}

{x = 7}

La respuesta correcta es la c).

10. El mcd(a,b,c) verifica que:

>   

>    igcd(14,67,89); igcd(14,igcd(67,89));

1

1

>    igcd(1445,6785,8900); igcd(1445,igcd(6785,8900));

5

5

>   

La respuesta correcta es la a).

>   

6. Test resuelto del curso 2002/2003

1.  Los números enteros 9755076 y 3489755:

a) Son relativamente primos entre sí.

b) No tienen divisores comunes.

c) Tienen 4 divisores comunes.

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    igcd(9755076,3489755);

1

>   

>   

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    ifactor(99);ifactor(52);99*52*17*19;

``(3)^2*``(11)

``(2)^2*``(13)

1662804

>    chrem([42,-8,25,0],[99,52,17,19]);

912228

La respuesta correcta es la b).

>   

>   

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    listaprimos:=proc(n)
local p,i,c;
i:=1;c:=[];
for p from 2 to n do
  if isprime(p) then c:=[op(c),p];
fi; od; c;
end:
listaprimos(100);nops(%);

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

25

La respuesta correcta es la a).

>   

>   

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    f:=n->4*n^32+4 mod 8;

f := proc (n) options operator, arrow; `mod`(4*n^32+4,8) end proc

>    seq([n,4*n^32+4 mod 8], n=0..7);

[0, 4], [1, 0], [2, 4], [3, 0], [4, 4], [5, 0], [6, 4], [7, 0]

La respuesta correcta es la b).

>   

5. Calcula la cantidad de números primos entre los números  del tipo 2^n-1 ,   2 <= n ,  menores que 100000.

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    solve(2^n-1<100000,n);

RealRange(-infinity,Open(ln(100001)/ln(2)))

>    floor(ln(100001)/ln(2));

16

También,

>    seq(2^n-1,n=2..16);2^17-1;

3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535

131071

>    c:=0:for i from 2 to  16
do if isprime(2^i-1) then c:=c+1: fi; od; c;

5

La respuesta correcta es la a).

>   

>   

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    ifactor(4536789);

``(3)*``(29)*``(52147)

>    phi(4536789);

2920176

La respuesta correcta es la b) porque los múltiplos de 3 no son relativamente primos con 4536789.

>   

7. Determinar cuántos números enteros mayores estrictamente que 10 y menores estrictamente que 1000 son, a la vez, primos y congruentes con 5 módulo 7.

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    solve(7*i+5<1000,i);floor(995/7);

RealRange(-infinity,Open(995/7))

142

>    c:=0:
for i from 1 to floor(995/7) do
if isprime(7*i+5) then c:=c+1 fi: od:
c;

28

La respuesta correcta es la a).

>   

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    chrem([1,1],[5,3]); chrem([1,1],[10,3]);

1

1

>   

La respuesta correcta es la c).

>   

>   

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    f:=n->a*n+2 mod 7;simplify(f(f(n))-n);

f := proc (n) options operator, arrow; `mod`(a*n+2,7) end proc

a^2*n+2*a+2-n

>    for a from 0 to 6 do
if simplify(f(f(n))-n)=0 then print(a); fi; od;

6

La respuesta correcta es la c).

>   

10. Los inversos de 3, 5 y 7 modulo 12 son respectivamente:

>   

>    restart; with(numtheory):

Warning, the protected name order has been redefined and unprotected

>    msolve(5*n-1,12); msolve(7*n-1,12);

{n = 5}

{n = 7}

La respuesta correcta es la a).

Práctica 3

PRÁCTICA 3

COMBINATORIA

1
1, 1
1, 2, 1
1, 3, 3, 1
1, 4, 6, 4, 1
1, 5, 10, 10, 5, 1
1, 6, 15, 20, 15, 6, 1

1, 7, 21, 35, 35, 21, 7, 1

Introducción a la Combinatoria con Maple

Instrucciones

1. Lee con atención el texto. Cuando aparezcan comandos o procedimientos de Maple (líneas en rojo), intenta averiguar para qué sirven (puedes emplear la ayuda de Maple) y después ejecútalos. Puedes ejecutarlos varias veces y cambiar en ellos lo que te parezca para entenderlos mejor o mejorarlos.

2. Realiza el test de evaluación (en un fichero aparte), ayudándote de los test de otros cursos.

Comandos de Maple

En el paquete combinat  de Maple se recogen comandos relacionados con la combinatoria. Para cargar el paquete procedemos como siempre con la instrucción:

>    with(combinat);

Warning, the protected name Chi has been redefined and unprotected

[Chi, bell, binomial, cartprod, character, choose, composition, conjpart, decodepart, encodepart, fibonacci, firstpart, graycode, inttovec, lastpart, multinomial, nextpart, numbcomb, numbcomp, numbpart...
[Chi, bell, binomial, cartprod, character, choose, composition, conjpart, decodepart, encodepart, fibonacci, firstpart, graycode, inttovec, lastpart, multinomial, nextpart, numbcomb, numbcomp, numbpart...
[Chi, bell, binomial, cartprod, character, choose, composition, conjpart, decodepart, encodepart, fibonacci, firstpart, graycode, inttovec, lastpart, multinomial, nextpart, numbcomb, numbcomp, numbpart...

>   

Hay otro paquete de funciones más avanzadas, combstruct , que no emplearemos en esta práctica.

Cardinales de conjuntos

Comenzamos con las funciones que presenta Maple para trabajar con conjuntos finitos y calcular sus cardinales.

Recordamos que los conjuntos se definían con llaves.

>    A:={1,2,3,4};

A := {1, 2, 3, 4}

Y que la operación nops  calculaba el número de elementos, es decir, el cardinal del conjunto A:

>    nops(A);

4

>    C:={seq(n^2,n=-10..10)}; nops(C);

C := {0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100}

11

Las operaciones habituales de conjuntos, como son la unión, la intersección, la diferencia de conjuntos y el producto cartesiano se pueden efectuar con Maple.

>    B:={1,a,b,c};

B := {1, a, c, b}

>    A union B;

{1, 2, 3, 4, a, c, b}

>    A intersect B;

{1}

>    A minus B;

{2, 3, 4}

Podemos hacer un procedimiento simple para construir el conjunto producto cartesiano:

>    cartesiano:=proc(A::set,B::set)
local i,j,C:
C:={}:
for i from 1 to nops(A) do
   for j from 1 to nops(B) do
   C:=C union {[[op(A)][i],[op(B)][j]]}
  od:
od: C; end:

Veamos unos ejemplos:

>    cartesiano({1,2},{l,m});

{[1, l], [1, m], [2, l], [2, m]}

>    cartesiano({maria,juana,luisa},{pedro,pepe,juan});

{[maria, pedro], [maria, pepe], [maria, juan], [juana, pedro], [juana, pepe], [juana, juan], [luisa, pedro], [luisa, pepe], [luisa, juan]}

>   

Aplicamos la teoría de conjuntos para responder la siguiente cuestión: ¿cuántos números enteros positivos menores o iguales que 1000 son a la vez el cuadrado de un  número entero y múltiplos de 4?.

Definimos el conjunto de los cuadrados menores que 1000.

>    evalf(sqrt(1000));

31.62277660

>    32**2;

1024

 

>    F:={seq(n^2,n=1..31)};

F := {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961}
F := {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961}

Definimos el conjunto de los múltiplos de 4 menores o iguales que 1000.

>    G:={seq(4*n,n=1..250)}:

Por tanto debemos calcular el cardinal de la intersección.

>    nops(F intersect G);

15

Los números enteros que cumplen ambas condiciones son exactamente:

>    F intersect G;

{4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784, 900}

>   

En efecto todos ellos son múltiplos de 4 y el cuadrado de un número entero.

Permutaciones

Comenzamos ahora a estudiar los comandos que tiene Maple para el cálculo de variaciones, permutaciones y combinaciones.

Aunque siguiendo el orden de los apuntes deberíamos empezar con las variaciones de m  elementos tomadas de n en  n  vamos a comenzar sin embargo con las permutaciones. Maple no tiene implementada una función para calcular las variaciones, pero sí que la tiene para permutaciones y combinaciones, de modo que con ellas podremos definir las variaciones.

El número de permutaciones de m elementos se calcula con numbperm :

>    numbperm(6);

720

También se puede usar el símbolo !  o la expresión factorial para calcular el factorial de un número:

>    6!; factorial(6);

720

720

La función numbperm  se puede aplicar a un conjunto en lugar de a su cardinal:

>    numbperm({a,b,c,d,e,f});

720

Para generar todas las permutaciones de un conjunto, esto es, las distintas maneras de ordenarlo, empleamos permute :

>    permute({a,b,c});

[[a, c, b], [a, b, c], [c, a, b], [c, b, a], [b, a, c], [b, c, a]]

Observad que el resultado es una secuencia.

Y para generar aleatoriamente una permutación de los elementos de un conjunto usamos la función randperm :

>    randperm({a,b,c,d,e,f});

[d, e, a, f, b, c]

Si queremos introducir repeticiones , entonces debemos dar los datos con una secuencia:

>    permute([c,o,c,o,d,r,i,l,o]):

>    numbperm([c,o,c,o,d,r,i,l,o]);

30240

La línea en que enumeran las permutaciones de la palabra cocodrilo la hemos terminado con dos puntos para no llenar pantallas con las 30240 permutaciones distintas de la palabra.

Y podemos verificar que es correcto según las fórmulas de clase:

>    9!/(2!*3!);

30240

También la función multinomial  permite calcular las permutaciones con repetición. Mediante la función convert  podemos ver exactamente la fórmula que desarrolla multinomial:

>    multinomial(9,2,3,1,1,1,1);
convert(multinomial(n,a,b,c,d),factorial);

30240

n!/a!/b!/c!/d!

De esta manera las permutaciones con repetición se pueden calcular por estos dos caminos:

>    is(numbperm([c,o,c,o,d,r,i,l,o])=multinomial(9,2,3,1,1,1,1));

true

>   

Combinaciones

Para calcular el número de combinaciones de n elementos (por ejemplo 2 elementos) escogidos entre los elementos de un conjunto (por ejemplo el conjunto {María , Juan , Eva , Luis , Teresa, Pablo} ), esto es, sus subconjuntos de n  elementos, empleamos la función numcomb,

>    numbcomb({Maria, Juan, Eva, Luis, Teresa, Pablo},2);

15

Aunque también se puede hacer empleando los números combinatorios m sobre n  que son los coeficientes en el binomio de Newton.

>    binomial(6,2);

15

Para ver la fórmula con la que trabaja binomial  podemos usar de nuevo convert .

>    convert(binomial(m,n),factorial);

m!/n!/(m-n)!

Si lo que queremos es obtener la lista de todas las combinaciones empleamos choose :

>    ### WARNING: combinat[choose] with numeric first parameter now returns a sorted list rather than a set
choose({Maria, Juan, Eva, Luis, Teresa, Pablo},2);

{{Maria, Pablo}, {Maria, Teresa}, {Maria, Eva}, {Maria, Luis}, {Maria, Juan}, {Pablo, Teresa}, {Pablo, Eva}, {Pablo, Luis}, {Pablo, Juan}, {Teresa, Eva}, {Teresa, Luis}, {Teresa, Juan}, {Eva, Luis}, {E...
{{Maria, Pablo}, {Maria, Teresa}, {Maria, Eva}, {Maria, Luis}, {Maria, Juan}, {Pablo, Teresa}, {Pablo, Eva}, {Pablo, Luis}, {Pablo, Juan}, {Teresa, Eva}, {Teresa, Luis}, {Teresa, Juan}, {Eva, Luis}, {E...

Obsérvese que el resultado es un conjunto.

Si a las funciones numbcomb  y choose   no se les da el segundo argumento, hacen el cálculo correspondiente a todos los valores desde cero hasta el número de elementos del conjunto.

>    numbcomb({Maria, Juan, Eva, Luis, Teresa, Pablo});

64

Que es el cardinal del conjunto partes de {María , Juan , Eva , Luis , Teresa, Pablo}  formado por todos sus subconjuntos.

>    2^6;

64

Este conjunto es:

>    ### WARNING: combinat[choose] with numeric first parameter now returns a sorted list rather than a set
choose({Maria, Juan, Eva, Luis, Teresa, Pablo});

{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...
{{Juan}, {Maria, Pablo, Juan}, {Maria, Teresa, Juan}, {Pablo, Teresa, Juan}, {Maria, Pablo, Teresa, Juan}, {Maria, Eva, Juan}, {Pablo, Eva, Juan}, {Maria, Pablo, Eva, Juan}, {Teresa, Eva, Juan}, {Maria...

>   

Podemos generar una combinación de forma aleatoria con randcomb

>    randcomb({chocolate,vainilla,fresa,limon},2);

{limon, fresa}

>    randcomb(5,3);

{1, 3, 4}

>   

En el último caso se eligen al azar tres números del conjunto {1,2,3,4,5} .

De nuevo, como en el caso de las permutaciones,  si queremos que haya elementos repetidos los datos deben introducirse como una secuencia.

>    ### WARNING: combinat[choose] with numeric first parameter now returns a sorted list rather than a set
choose([a,b,a],2);

[[a, a], [a, b]]

>    numbcomb([a,b,a],2);

2

Observa que éstas no son las combinaciones con repetición de 2 elementos tomadas de dos en dos, que son por la fórmula vista en clase:

>    binomial(2+2-1,2);

3

Ya que en las combinaciones elegidas arriba, falta la pareja (b,b) .

Se puede introducir una función en dos variables que permita calcular el número de combinaciones con repetición de m elementos tomadas de n  en n .

>    CR:=(m,n)->binomial(m+n-1,n);

CR := proc (m, n) options operator, arrow; binomial(m+n-1,n) end proc

>    CR(2,2);

3

>   

Variaciones

Vamos a construir una fórmula para las variaciones y para las variaciones con repetición.

Como las combinaciones de m  elementos tomadas de n  en n  son el cociente de las variaciones de  m  elementos tomadas de n  en n  por las permutaciones de n , la fórmula oportuna será:

>    V:=(m,n)->binomial(m,n)*n!;

V := proc (m, n) options operator, arrow; binomial(m,n)*n! end proc

>    V(3,5);

0

>    V(3,3);

6

O como un procedimiento:

>    V2:=proc(m,n)
local s,i:
if n>m then s:=0 else
s:=1:
for i from 0 to n-1 do
s:=s*(m-i):
od:
fi:
s; end:

>    V2(5,3);
V2(5,10);

60

0

Y también podemos construir una fórmula para las variaciones con repetición:

>    VR:=(m,n)->m^n;

VR := proc (m, n) options operator, arrow; m^n end proc

>    VR(2,3);

8

Y dado un conjunto de m  elementos podríamos diseñar un procedimiento que construyera primero todas las combinaciones de n  elementos con el comando choose , y luego hiciera todas las permutaciones para cada una de estas combinaciones. El resultado es el conjunto de todas las variaciones de m  elementos tomados de n  en n , esto es, las listas ordenadas de n  elementos en un conjunto de m  elementos.

>    variaciones:=proc(A,n)
local C,D,i:
### WARNING: combinat[choose] with numeric first parameter now returns a sorted list rather than a set
C:=[op(choose(A,n))]:
D:={}:
for i from 1 to nops(C) do
D:= D union {op(permute([op(C[i])]))}: od:
D; end:

Veamos algunos ejemplos:

>    variaciones({a,b,c,d},3);

{[a, c, b], [a, b, c], [c, a, b], [c, b, a], [b, a, c], [b, c, a], [a, d, b], [c, d, b], [c, b, d], [d, a, b], [d, b, a], [b, a, d], [b, d, a], [d, c, b], [d, b, c], [b, c, d], [b, d, c], [a, b, d], [a...
{[a, c, b], [a, b, c], [c, a, b], [c, b, a], [b, a, c], [b, c, a], [a, d, b], [c, d, b], [c, b, d], [d, a, b], [d, b, a], [b, a, d], [b, d, a], [d, c, b], [d, b, c], [b, c, d], [b, d, c], [a, b, d], [a...

En efecto, se han obtenido todas:

>    is(nops(variaciones({a,b,c,d,e},3))=V(nops({a,b,c,d,e}),3));

true

Otros ejemplos:

>    variaciones({1,2,3},2);

{[1, 2], [1, 3], [2, 3], [3, 1], [3, 2], [2, 1]}

>    variaciones({p,q,r,s,t,u,v},7):

>    is(nops(%)=7!);

true

>   

Otras funciones combinatorias

Las funciones partition, numbpart  y randpart  sirven para calcular el número de formas distintas en que se puede descomponer un número natural en suma de otros, para hallar todas las posibles descomposiciones y para hallar una de ellas al azar respectivamente. Veamos un ejemplo:

>    partition(10);

[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, ...
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, ...
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, ...
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, ...
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 2, 2], [1, 1, 1, 1, 2, 2, 2], [1, 1, 2, 2, 2, 2], [2, 2, 2, 2, 2], [1, 1, 1, 1, 1, 1, 1, 3], [1, 1, 1, 1, 1, 2, 3], [1, ...

Es decir, ha encontrado todas las maneras en que 10 se puede poner como suma de números naturales menores o iguales que 10.

Para contarlas se usa:

>    numbpart(10);

42

Y en efecto calcula el cardinal del conjunto anterior:

>    nops(partition(10));

42

De igual manera si se quiere conseguir una partición aleatoriamente:

>    randpart(10);

[1, 1, 2, 6]

Observa que si se repite el comando anterior:

>    randpart(10);

[1, 1, 1, 1, 2, 4]

>   

Como la elección es aleatoria, es demasiada casualidad que  haya salido igual.

Test resuelto curso 2000/2001

1.-Sea un experimento de Bernoulli con probabilidad de éxito p=1/3. Entendiendo que las repeticiones del experimento son sucesos independientes. Calcula la probabilidad de obtener exactamente 3 éxitos al repetir el experimento 154 veces. La respuesta es:

>   

>    with(combinat):

>    evalf(binomial(154,3)*(1/3)^3*(2/3)^(151));

.5685394534e-22

>   

>   

>    evalf(add(binomial(154,i)*(1/3)^i*(2/3)^(154-i),i=0..75));

.9999711222

La respuesta correcta es la c).

3.  Con  el mismo enunciado del primer problema, calcula el mínimo número de veces que se ha de repetir el experimento para que la probabilidad de obtener al menos 1 éxito sea mayor que 0.75:

>   

>    seq([n,evalf(1-(2/3)^n)],n=1..10);

[1, .3333333333], [2, .5555555556], [3, .7037037037], [4, .8024691358], [5, .8683127572], [6, .9122085048], [7, .9414723365], [8, .9609815577], [9, .9739877051], [10, .9826584701]
[1, .3333333333], [2, .5555555556], [3, .7037037037], [4, .8024691358], [5, .8683127572], [6, .9122085048], [7, .9414723365], [8, .9609815577], [9, .9739877051], [10, .9826584701]

La respuesta correcta es la a).

 4.- Sea el experimento aleatorio extraer una bola de un bombo con bolas numeradas del 1 al 100 todas ellas iguales. Dada una variable aleatoria X definida sobre el espacio muestral de este experimento de forma que X(s)=s^2, su valor esperado (o esperanza matemática) es:

>   

>    evalf(add(s^2/100,s=1..100));

3383.500000

La respuesta correcta es la a).

>   

 5.- La probabilidad de extraer un número primo en una urna que contiene los números enteros entre el 1 y el 5000 es:

>   

>    c:=0; for i from 1 to 5000 do
if isprime(i) then c:=c+1 fi; od; evalf(c/5000);

c := 0

.1338000000

La respuesta correcta es la c).

 6.- Sea el conjunto de pares de palabras (p,q) donde la palabra p es una palabra de 9 letras que se obtiene permutando las letras de la palabra cocodrilo  y la palabra q es una palabra de 11 letras obtenida permutando las letras de la palabra abracadabra . ¿Cuál es la probabilidad de que al elegir una de ellas sea justamente la palabra (cocodrilo,abracadabra)?:

>   

>    evalf(1/(numbperm([c,o,c,o,d,r,i,l,o])*numbperm([a,b,r,a,c,a,d,a,b,r,a])));

.3976525141e-9

La respuesta correcta es la b).

7.- De cuantas maneras se pueden sentar 11 personas en dos mesas, una de 6 comensales y otra de 5 comensales, teniendo en cuenta tanto la distribución en las dos mesas, como el orden en cada mesa:

>   

>    binomial(11,6)*6!*5!;

39916800

La respuesta correcta es la c).

8.- ¿Cual es el menor valor de n para el cual la probabilidad de que dos personas en un grupo de n personas cumplan los años el mismo día es mayor que 0.75?

>   

>    f:=n->1-(binomial(365,n)*n!/365^n);

f := proc (n) options operator, arrow; 1-binomial(365,n)*n!/(365^n) end proc

>    seq([n,evalf(f(n))],n=30..40);

[30, .7063162427], [31, .7304546337], [32, .7533475278], [33, .7749718542], [34, .7953168646], [35, .8143832389], [36, .8321821064], [37, .8487340082], [38, .8640678211], [39, .8782196644], [40, .89123...
[30, .7063162427], [31, .7304546337], [32, .7533475278], [33, .7749718542], [34, .7953168646], [35, .8143832389], [36, .8321821064], [37, .8487340082], [38, .8640678211], [39, .8782196644], [40, .89123...

>   

>   

>    A:={seq(i^2,i=1..100)}: B:={seq(i^3,i=1..100)}: nops(A intersect B);

4

La respuesta correcta es la a).

10.- De los números naturales menores o iguales que 10.000 cuántos múltiplos de 5 no son múltiplos de 7.

>   

>    restart; C:={seq(5*n,n=1..2000)}: E:={seq(7*n,n=1..2000)}: nops(C minus E);

1715

La respuesta correcta es la c).

Test resuelto curso 2001/2002

1.-Determinar cuántos números naturales menores que 10000 son múltiplos de 7 pero no son pares ni múltiplos de 3:

a) 477

b) 476

c) 478

>    evalf(10000/7);

1428.571429

>    A:={seq(7*i,i=1..1428)}:

>    B:={seq(2*i,i=1..5000)}:

>    C:={seq(3*i,i=1..3333)}:

>    nops(A minus B minus C);

476

>   

La respuesta correcta es la b)

>    restart: with(combinat):

Warning, the protected name Chi has been redefined and unprotected

2.- Determinar cuántos subconjuntos de menos de 5 elementos (de 0 a 4 elementos) tiene el conjunto

>    E:={a,b,c,d,f,e,r,t,y,n,l}:

>   

a) 432

b) 554
c) 562

>    nops(E);

11

>    c:=binomial(11,0):
for i from 1 to 4 do
c:=c+binomial(11,i): od: c;

562

>   

La respuesta correcta es la c).

3.- Dado un conjunto de 54 personas hay que elegir un delegado, un subdelegado y un vocal. De entre los restantes hay que elegir a 3 personas para que les acompañen. Determinar cuántas posibles delegaciones hay.

a) 3099889800

b) 3099259800

c) 3099889800

>    54*53*52*binomial(51,3);

3099259800

>   

La respuesta correcta es la b).

4.- Sea una urna que contiene los números del 1 al 10000. Se extraen dos bolas consecutivamente, reintroduciendo en la urna la bola extraída. Determinar la probabilidad de que ambas bolas sean números primos.

a) 0.02145

b) 0.01510

c) 0.01234

>    c:=0:
for i from 1 to 10000 do
if isprime(i) then c:=c+1: fi:
od: c;

1229

>    evalf((1229/10^4)^2);

.1510441000e-1

>   

La respuesta correcta es la b).

5.- Sea un conjunto de 357 personas. Sea el experimento aleatorio: seleccionar tres personas. Sea el suceso S: las tres personas son rubias. Determinar el número mínimo de personas que han de ser rubios para que la probabilidad de S sea mayor o igual que 1/3.

a) 248

b) 348

c) 249

>    restart: with(combinat):

Warning, the protected name Chi has been redefined and unprotected

>    p:=n->binomial(n,3)/binomial(357,3);

p := proc (n) options operator, arrow; binomial(n,3)/binomial(357,3) end proc

>    i:=0:
while(evalf(p(i))<1/3) do
i:=i+1: od: i;

248

>    evalf(p(247)); evalf(p(248)); evalf(p(249));

.3299526172

.3339928534

.3380659369

>   

La respuesta correcta es la a).

6.- Determinar el número de palabras que se pueden construir permutando las letras de la palabra semaforos.

a) 90721

b) 91720

c) 90720

>    numbperm([s,e,m,a,f,o,r,o,s]);

90720

>   

La respuesta correcta es la c).

7.- Sean los conjuntos A y B descritos abajo. Determinar cuántos subconjuntos de 3 elementos comparten A y B.

a) 120

b) 130

c) 134

>    A:={1,2,3,4,5,e,r,t,y,u,i,o,p}: B:={1,2,3,4,5,e,r,t,g,y,u,h,j,l}:

>    ### WARNING: combinat[choose] with numeric first parameter now returns a sorted list rather than a set
### WARNING: combinat[choose] with numeric first parameter now returns a sorted list rather than a set
nops(choose(A,3) intersect choose(B,3));

120

>    ### WARNING: combinat[choose] with numeric first parameter now returns a sorted list rather than a set
nops(choose(A intersect B,3));

120

>   

La respuesta correcta es la a).

8.- Cuántos números se pueden representar en el sistema binario con 10 dígitos.

a) Menos de 1000

b) Más de 1500 y menos de 2000

c) Más de 1000 y menos de 1100

>    2**10;

1024

>   

La respuesta correcta es la c).

9.- Sea un alfabeto con 27 letras. Determinar cuántos códigos alfanuméricos (formados por números y letras) de 7 símbolos se pueden establecer, sabiendo que los dos primeros símbolos han de ser letras y los dos últimos han de ser números.

a) 13662633690

b) 4061864070

c) 3692603700

>    27*27*37*37*37*10*10;

3692603700

>   

La respuesta correcta es la c).

10.- Dados dos números naturales m y n   decimos que m es ascendente de n si se verifica que

>    m**3=n**2;

m^3 = n^2

por ejemplo 1 es ascendente de 1 y 4 es ascendente de 8. Determinar la probabilidad de que al escoger aleatoriamente un número m menor o igual que 1000 exista n menor o igual que 1000 tal que m sea ascendente de n .

a) 0.01

b) 0.11

c) 0.21

>    c:=0:
for m from 1 to 1000 do
for n from 1 to 1000 do
if m^3=n^2 then c:=c+1: fi:
od:
od: evalf(c/1000);

.1000000000e-1

>   

>   

>   

La respuesta correcta es la a).

Test resuelto curso 2002/2003

1)  En un taller hay 10 coches que necesitan reparaciones. Calcular de cuantas formas distintas se pueden

elegir y ordenar los primeros 4 coches que se van a arreglar.

a)   210

b) 420

c) 5040

>    restart;with(combinat):V:=(m,n)-> binomial(m,n)*n!;

Warning, the protected name Chi has been redefined and unprotected

V := proc (m, n) options operator, arrow; binomial(m,n)*n! end proc

>    V(10,4);

5040

La respuesta correcta es la c).

>   

2)  Determinar el número de palabras que se pueden construir permutando las letras de la palabra ALESSANDRA.

a) 90720

b) 60480

c) 302400

>    restart;with(combinat):
numbperm([A,L,E,S,S,A,N,D,R,A]);

Warning, the protected name Chi has been redefined and unprotected

302400

La respuesta correcta es la c).

>   

3) Determinar cuantos posibles resultados pueden acontecer al lanzar 25 monedas simultáneamente.

a) 16777216

b) 300
c) 26

>    restart;with(combinat):
binomial(26,25);

Warning, the protected name Chi has been redefined and unprotected

26

La respuesta correcta es la c).

>   

4) Sea un alfabeto con 27 letras. Determinar cuantas contraseñas alfanuméricas (formadas por números y letras, distinguiendo mayúsculas y minúsculas) de 8 símbolos se pueden establecer, sabiendo que los tres primeros símbolos han de ser letras y los

dos últimos han de ser números.

a) 515978035200

b) 4127824281600

c) 417942208512

>    54*54*54*64*64*64*10*10;

4127824281600

La respuesta correcta es la b).

>   

5)  Sean S y S' dos sucesos de un mismo espacio muestral tales que: p(S)=0.5, p(S')=0.8 y p(S|S')=0.6.

Se verifica que:

a)  la probabilidad de S intersección con S' es 0.4

b)  S y S' no son sucesos independientes.

c)  S y S' son sucesos independientes.

Si S y S' fuesen independientes,  p(S|S') sería igual a p(S)  y la probabilidad de S intersección con S' sería igual a

>    0.5*0.8;

.40

Pero p(S|S') no es igual a p(S).

La respuesta correcta es la b).

>   

6) Calcular la probabilidad de que un número natural menor o igual a 10000 sea un cubo de un número natural y

congruente con 3 módulo 5.

a)   1/2500

b)   2017/10000

c)   17/10000  

>    restart;with(combinat):

Warning, the protected name Chi has been redefined and unprotected

>    floor(10^(4/3));

21

>    A:={seq(i^3,i=1..21)}:nops(A);

21

>    solve(3+5*k<=10^4,k);

RealRange(-infinity,9997/5)

>    floor(9997/5);

1999

>    B:={seq(3+5*k,k=0..1999)}:nops(B);

2000

>    nops(A intersect B)/10^4;

1/2500

>   

7) Tomamos una urna con bolas de distintos colores. Si la urna contiene 32 bolas y extraemos 5 bolas, determinar el número mínimo de bolas rojas en la urna para que la probabilidad de que las cinco bolas extraídas sean todas rojas sea al menos 1/5.

a) 24

b) 34

c) 25

>    restart: with(combinat):

Warning, the protected name Chi has been redefined and unprotected

>    p:=n->binomial(n,5)/binomial(32,5);

p := proc (n) options operator, arrow; binomial(n,5)/binomial(32,5) end proc

>    i:=0:
while(evalf(p(i))<1/5) do
i:=i+1: od: i;

24

>    evalf(1/5);evalf(p(23)); evalf(p(24));

.2000000000

.1670953838

.2110678532

La respuesta correcta es la a).

>   

8)  Sea el experimento aleatorio consistente en el tirar dos dados consecutivamente. Calcular la probabilidad

que la suma de los resultados de ambos dados sea 7.

a)   1/6

b) 1/7

c) 1/8

>   

>    restart;with(combinat):
suma:=partition(7);

Warning, the protected name Chi has been redefined and unprotected

suma := [[1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 2], [1, 1, 1, 2, 2], [1, 2, 2, 2], [1, 1, 1, 1, 3], [1, 1, 2, 3], [2, 2, 3], [1, 3, 3], [1, 1, 1, 4], [1, 2, 4], [3, 4], [1, 1, 5], [2, 5], [1, 6], [7]]
suma := [[1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 2], [1, 1, 1, 2, 2], [1, 2, 2, 2], [1, 1, 1, 1, 3], [1, 1, 2, 3], [2, 2, 3], [1, 3, 3], [1, 1, 1, 4], [1, 2, 4], [3, 4], [1, 1, 5], [2, 5], [1, 6], [7]]

>    c:=0:
suma2:=[]:
for i from 1 to nops(suma) do
  if nops(suma[i])=2 then suma2:=[op(suma2),suma[i]]: c:=c+1; fi: od;
c;suma2;

3

[[3, 4], [2, 5], [1, 6]]

>   

>    p:=6/36;

p := 1/6

La respuesta correcta es la a).

>   

9)  Sea un experimento de Bernoulli con probabilidad de éxito p=1/4.

Calcula la probabilidad de obtener exactamente 53 éxitos al repetir el experimento 200 veces.

La respuesta es:

>   

>    restart;with(combinat):

Warning, the protected name Chi has been redefined and unprotected

>    evalf(binomial(200,53)*((1/4)^53)*((3/4)^(147)));

.5668085443e-1

La respuesta correcta es la b).

>   

10) La probabilidad de extraer un número relativamente primo con 567 de una urna que contiene los números enteros

entre el 1 y el 567 es:

>   

>    restart;with(combinat):with(numtheory):

Warning, the protected name Chi has been redefined and unprotected

Warning, the protected name order has been redefined and unprotected

>    phi(567)/567;

4/7

La respuesta correcta es la b).

>    #fin

(Libro de referencia:   "EXPLORING DISCRETE MATHEMATICS WITH MAPLE"   de K.H.Rosen,   McGraw Hill 1997 )

Práctica 4

Matemática Discreta

PRÁCTICA 4

GRAFOS y ÁRBOLES

[Maple Plot]

Instrucciones

1. Lee con atención el texto. Cuando aparezcan líneas de input de comandos intenta averiguar para qué sirven (puedes emplear la ayuda de Maple) y después ejecútalos. Puedes ejecutarlos varias veces y cambiar en ellos lo que te parezca para entenderlos mejor o mejorarlos.

2. Haz los ejercicios propuestos, pues los necesitarás para la resolución de las preguntas del test de evaluación.

Grafos con Maple

Comandos básicos

Maple tiene una librería de comandos relacionados con la teoría de grafos denominada networks:

>    restart; with(networks);

[acycpoly, addedge, addvertex, adjacency, allpairs, ancestor, arrivals, bicomponents, charpoly, chrompoly, complement, complete, components, connect, connectivity, contract, countcuts, counttrees, cube...
[acycpoly, addedge, addvertex, adjacency, allpairs, ancestor, arrivals, bicomponents, charpoly, chrompoly, complement, complete, components, connect, connectivity, contract, countcuts, counttrees, cube...
[acycpoly, addedge, addvertex, adjacency, allpairs, ancestor, arrivals, bicomponents, charpoly, chrompoly, complement, complete, components, connect, connectivity, contract, countcuts, counttrees, cube...
[acycpoly, addedge, addvertex, adjacency, allpairs, ancestor, arrivals, bicomponents, charpoly, chrompoly, complement, complete, components, connect, connectivity, contract, countcuts, counttrees, cube...
[acycpoly, addedge, addvertex, adjacency, allpairs, ancestor, arrivals, bicomponents, charpoly, chrompoly, complement, complete, components, connect, connectivity, contract, countcuts, counttrees, cube...
[acycpoly, addedge, addvertex, adjacency, allpairs, ancestor, arrivals, bicomponents, charpoly, chrompoly, complement, complete, components, connect, connectivity, contract, countcuts, counttrees, cube...

Para definir un grafo, definimos en primer lugar una variable con su nombre. Terminamos la sentencia con dos puntos, porque si ponemos un punto y coma la salida es larga y no aporta nada (puedes comprobarlo tú mismo).

>    G1:=new():

A continuación añadimos los vértices al grafo, por ejemplo:

>    addvertex({Mostoles,Alcorcon,Fuenlabrada,Vicalvaro,Pozuelo},G1);

Mostoles, Alcorcon, Fuenlabrada, Vicalvaro, Pozuelo

Ahora añadimos las aristas como subconjuntos de dos elementos y entonces estamos trabajando con grafos simples . El programa las asigna ciertos nombres de la forma ei :

>    addedge({{Mostoles,Alcorcon},{Mostoles,Fuenlabrada},{Alcorcon,Fuenlabrada},{Fuenlabrada,Vicalvaro},{Alcorcon,Pozuelo},{Vicalvaro,Pozuelo},{Alcorcon,Vicalvaro}},G1);

e1, e2, e3, e4, e5, e6, e7

Para saber cuáles son las aristas de nuestro grafo utilizamos el comando ends o  edges :

>    ends(G1);
edges(G1);

{{Mostoles, Fuenlabrada}, {Alcorcon, Fuenlabrada}, {Fuenlabrada, Vicalvaro}, {Alcorcon, Pozuelo}, {Vicalvaro, Pozuelo}, {Alcorcon, Vicalvaro}, {Mostoles, Alcorcon}}
{{Mostoles, Fuenlabrada}, {Alcorcon, Fuenlabrada}, {Fuenlabrada, Vicalvaro}, {Alcorcon, Pozuelo}, {Vicalvaro, Pozuelo}, {Alcorcon, Vicalvaro}, {Mostoles, Alcorcon}}

{e2, e3, e4, e5, e6, e7, e1}

Y para representar gráficamente el grafo utilizamos el comando draw :

>    draw(G1);

[Maple Plot]

Para saber si dos vértices son los extremos de una arista y recuperar la notación con la que se las denomina, se emplea el comando edges :

>    edges({Mostoles,Alcorcon},G1);
edges({Pozuelo, Alcorcon},G1);
edges({Mostoles,Pozuelo},G1);

{e7}

{e4}

{}

También podemos pintar el grafo con unos vértices a la izquierda y los demás a la derecha (como si se tratara de un grafo bipartido) usando el siguiente comando Linear([...], [...]):

>    draw(Linear([Mostoles,Alcorcon],[Fuenlabrada,Vicalvaro,Pozuelo]),G1);

[Maple Plot]

El comando vertices  se emplea para recuperar los vértices del grafo:

>    vertices(G1);

{Mostoles, Alcorcon, Fuenlabrada, Vicalvaro, Pozuelo}

El comando vdegre  nos permite obtener el grado de cualquier vértice:

>    vdegree(Mostoles,G1);

2

Si quisiéramos trabajar con digrafos, las aristas deben ser un conjunto de pares ordenados:

>    D1:=new():
addvertex({Mostoles,Alcorcon,Fuenlabrada,Vicalvaro,Pozuelo},D1):
addedge({[Mostoles,Alcorcon],[Mostoles,Fuenlabrada],[Alcorcon,Fuenlabrada],[Fuenlabrada,Vicalvaro],[Alcorcon,Pozuelo],[Vicalvaro,Pozuelo],[Alcorcon,Vicalvaro],[Vicalvaro,Alcorcon]},D1):
vertices(D1);
edges(D1);
ends(D1);

{Mostoles, Alcorcon, Fuenlabrada, Vicalvaro, Pozuelo}

{e2, e3, e4, e5, e6, e7, e1, e8}

{[Mostoles, Alcorcon], [Mostoles, Fuenlabrada], [Alcorcon, Fuenlabrada], [Fuenlabrada, Vicalvaro], [Alcorcon, Pozuelo], [Vicalvaro, Pozuelo], [Alcorcon, Vicalvaro], [Vicalvaro, Alcorcon]}
{[Mostoles, Alcorcon], [Mostoles, Fuenlabrada], [Alcorcon, Fuenlabrada], [Fuenlabrada, Vicalvaro], [Alcorcon, Pozuelo], [Vicalvaro, Pozuelo], [Alcorcon, Vicalvaro], [Vicalvaro, Alcorcon]}

El dibujo no muestra la orientación de las aristas, ni si hay dos aristas uniendo los mismos vértices:

>    draw(D1);

[Maple Plot]

Para introducir aristas múltiples , tanto en grafos dirigidos como no dirigidos, basta cambiar el tipo de datos de las aristas: de conjunto a lista. Para introducir lazos  basta escribirlos.

>    M1:=new():
addvertex({Mostoles,Alcorcon,Fuenlabrada,Vicalvaro,Pozuelo},M1):
addedge([{Mostoles,Mostoles},{Mostoles,Alcorcon},{Mostoles,Alcorcon},{Mostoles,Fuenlabrada},{Alcorcon,Fuenlabrada},{Fuenlabrada,Vicalvaro},{Alcorcon,Pozuelo},{Vicalvaro,Pozuelo},{Alcorcon,Vicalvaro}],M1):
vertices(M1);
edges(M1);
ends(M1);

{Mostoles, Alcorcon, Fuenlabrada, Vicalvaro, Pozuelo}

{e2, e3, e4, e5, e6, e7, e1, e9, e8}

{{Mostoles, Fuenlabrada}, {Alcorcon, Fuenlabrada}, {Fuenlabrada, Vicalvaro}, {Alcorcon, Pozuelo}, {Vicalvaro, Pozuelo}, {Alcorcon, Vicalvaro}, {Mostoles}, {Mostoles, Alcorcon}}
{{Mostoles, Fuenlabrada}, {Alcorcon, Fuenlabrada}, {Fuenlabrada, Vicalvaro}, {Alcorcon, Pozuelo}, {Vicalvaro, Pozuelo}, {Alcorcon, Vicalvaro}, {Mostoles}, {Mostoles, Alcorcon}}

De nuevo el dibujo no es ilustrativo:

>    draw(M1);

[Maple Plot]

Maple ya lleva incorporados algunos grafos especiales  como los grafos completos, los ciclos, los n-cubos, el grafo de

Petersen (no visto en clase, mira cómo es más abajo), los bipartidos completos, etc.

>    draw(complete(5));

[Maple Plot]

>    draw(cycle(7));

[Maple Plot]

>    draw(cube(3));

[Maple Plot]

>    draw(petersen());

[Maple Plot]

>    draw(complete(2,6));

[Maple Plot]

>    draw(complete(2,5));

[Maple Plot]

>    draw(Linear([1,2],[3,4,5,6,7]),complete(2,5));

[Maple Plot]

A lo largo del tema hemos visto varias formas de representar un grafo. Para recuperar una matriz de adyacencia  y una matriz de incidencia  de un grafo se pueden utilizar los siguientes comandos:

>    adjacency(complete(4));

Matrix(%id = 2975916)

>    incidence(complete(4));

Matrix(%id = 3174528)

>    adjacency(G1);

Matrix(%id = 3160396)

Conexión

El comando components  permite recuperar las componentes conexas de un grafo. Al emplearlo, podemos observar fácilmente si dos vértices dados están conectados o no por un camino: deben pertenecer a la misma componente conexa.

>    G2:=new():

>    addvertex({v1,v2,v3,v4,v5,v6,v7,v8,v9},G2):

>    addedge({{v1,v2},{v1,v3},{v5,v6},{v6,v7},{v7,v8},{v8,v9}},G2):

>    components(G2);

{{v1, v2, v3}, {v4}, {v5, v6, v7, v8, v9}}

>    draw(G2);

[Maple Plot]

También se podría diseñar un procedimiento que usa la matriz de adyacencias para saber si el grafo es o no conexo. Esto lo proponemos como ejercicio al final de la práctica.

Grafos eulerianos y hamiltonianos

Según sabemos, un grafo con todos los vértices en la misma componente conexa es euleriano si y solo si todos sus vértices tienen grado par. Teniendo en cuenta este hecho, podemos crear un procedimiento que nos permita averiguar si un grafo conexo es, o no, euleriano.

Dado un grafo la función degreeseq da la lista de los grados de sus vértices:

>    degreeseq(G2);

[0, 1, 1, 1, 1, 2, 2, 2, 2]

Entonces podemos crear un procedimiento para saber si un grafo conexo es euleriano:

>    Euleriano:=proc(G::graph)
local c,i,r:
c:=degreeseq(G):i:=1:
while i<nops(c)+1 do
if (c[i] mod 2)<>0 then i:=nops(c)+2: else i:=i+1: fi: od:
if i=nops(c)+2 then r:="no euleriano": else r:="euleriano": fi: r; end:

Analicemos algunos ejemplos:

>    Euleriano(cycle(5));

>    Euleriano(complete(4));

>    Euleriano(complete(5));

>   

Como ya comentamos en clase, no tenemos una caracterización de los grafos hamiltonianos. El problema es complicado computacionalmente hablando, incluso para grafos relativamente pequeños. Aún así, cabría pensar en utilizar "la fuerza bruta" creando un algoritmo que vaya construyendo todos los posibles circuitos hamiltonianos, utilizando para ello todas las posibles permutaciones de los vértices.

Grafos etiquetados

Para definir con Maple un grafo en el que cada arista tiene asignado una etiqueta (tiempo, distancia, coste, etc.) se emplea la opción weights  del comando addedge .

Observa que las aristas deben entrar como una lista:

>    new(G3):
addvertex({a,b,c,d,y,z},G3);
addedge(
   [{a,b},{a,d},{b,c},{b,y},{c,z},{d,y},{y,z}],
   weights=[4,2,3,3,2,3,1],
G3);

a, y, c, b, d, z

e1, e2, e3, e4, e5, e6, e7

Al pintarlo no señala las etiquetas.

>    draw(G3);

[Maple Plot]

Pero el comando eweight  (edge weight) recupera el peso de cada una de sus aristas.

>    eweight(e1,G3);

4

>   

El algoritmo de Dijkstra

El algoritmo de Dijkstra  permite hallar el camino más corto (en el sentido de que la suma de los pesos de las aristas que recorre es mínima) entre dos vértices de un grafo en el que cada arista tiene asociado un peso (que representa la distancia, el tiempo, el coste... entre los vértices que une). Este algoritmo está implementado en el comando shortpathtree  y  calcula, para cada vértice, la longitud del camino mínimo entre este vértice y el resto de los vértices, asignando este valor (la longitud del camino mínimo entre el vértice fijado y cada uno de los demás) como peso a cada vértice. Por ello, para obtener la distancia mínima entre dos vértices de un grafo etiquetado, emplearemos el  comando vweight  (vertex weight).

>    A1:=shortpathtree(G3,a):
draw(A1);

[Maple Plot]

>   

Ahora, para hallar la distancia mínima entre cualquier vértice y el vértice a  utilizaremos el comando vweight :

>    vweight(z,A1);

6

>    vweight(y,A1);

5

>    vweight(d,A1);

2

Matrices

Para trabajar con matrices Maple presenta la librería linalg  sobre la que se abundará en la asignatura de Álgebra. De momento nos vamos a iniciar en los rudimentos para poder trabajar con las matrices de adyacencia e incidencia de un grafo.

>    with(linalg):

Warning, the names charpoly and rank have been redefined

Warning, the protected names norm and trace have been redefined and unprotected

Para definir una matriz se utiliza el comando matrix  y la entrada se forma como una lista de listas (la lista de las filas de la matriz) :

>    A:= matrix([[1,-alpha,2/3],[-1,0,1],[beta/3,2,-1]]);

A := matrix([[1, -alpha, 2/3], [-1, 0, 1], [1/3*beta, 2, -1]])

Que también se puede escribir señalando primero el tamaño de la matriz:

>    matrix(3,3,[1,-alpha,2/3,-1,0,1,beta/3,2,-1]);

matrix([[1, -alpha, 2/3], [-1, 0, 1], [1/3*beta, 2, -1]])

Podemos transponer  matrices:

>    transpose(A);

matrix([[1, -1, 1/3*beta], [-alpha, 0, 2], [2/3, 1, -1]])

Podemos sumar y restar  matrices. Para que la matriz resultado se escriba en pantalla se usa evalm .

>    B:= matrix([[1,2,1],[1,1,0],[-1,0,1]]);

B := matrix([[1, 2, 1], [1, 1, 0], [-1, 0, 1]])

>    A+B;

A+B

>    evalm(A+B);

matrix([[2, -alpha+2, 5/3], [0, 1, 1], [1/3*beta-1, 2, 0]])

También es posible multiplicar  matrices utilizando Maple. Se puede usar el comando multiply  o el producto &* . Se reserva el símbolo * para producto por escalares .

>    C:= multiply(A,B);

C := matrix([[1/3-alpha, -alpha+2, 5/3], [-2, -2, 0], [1/3*beta+3, 2/3*beta+2, 1/3*beta-1]])

>    evalm(A&*B);

matrix([[1/3-alpha, -alpha+2, 5/3], [-2, -2, 0], [1/3*beta+3, 2/3*beta+2, 1/3*beta-1]])

>    evalm(A &* B - 1/3*C);

matrix([[2/9-2/3*alpha, -2/3*alpha+4/3, 10/9], [-4/3, -4/3, 0], [2/9*beta+2, 4/9*beta+4/3, 2/9*beta-2/3]])

Podemos hacer potencias de matrices:

>    evalm(A^3);

matrix([[-1/3+2*alpha+2/9*beta-1/3*beta*alpha, -(1+alpha+2/9*beta)*alpha-2*alpha, 2+2/3*alpha+4/27*beta], [-2/9*beta-3-alpha, -(1/3*beta-1)*alpha-10/3, 2/9*beta+3+alpha], [1/3*beta*alpha+1/3*(2/9*beta+...

>    F:=evalm(B^7);

F := matrix([[64, 128, 64], [64, 127, 63], [-64, -126, -62]])

Una matriz se almacena como una lista de listas. Para recuperar la entrada (i,j)  de la matriz C  escribiremos C[i,j] . Por ejemplo:

>    F[3,3];

-62

También es posible recuperar el número de filas y el número de columnas de una matriz, empleando los comandos rowdim  y coldim .

 Por ejemplo:

>    rowdim(F);coldim(F);

3

3

Hay muchas otras funciones en la librería de álgebra lineal pero las que hemos presentado son suficientes para realizar esta práctica.

>   

Ejercicios previos al test de evaluación

Proponemos algunos ejercicios simples que necesitaremos para resolver el test de la práctica. Algunos ejercicios los resolvemos como ejemplo.

>    restart; with(networks):

1. Grados de los vértices

1.1. ¿Cómo se puede calcular el número de aristas de un grafo? ¿Y el número de vértices?.

Si tenemos un grafo definido, las funciones vertices  y edges  obtienen el conjunto de vértices y aristas del grafo. Entonces basta contar el número de elementos de cada uno de los conjuntos:

>    G:=complete(9):

>    nops(vertices(G));

9

>    nops(edges(G));

36

1.2. Escribir un procedimiento que calcule la sucesión de los grados de un grafo.  

Recordar que esto lo hace la función degreeseq , aunque no necesariamente en el orden que hemos introducido los vértices:

>    H:=new():

>    addvertex({a1,a2,a3,a4,a5,a6,a7},H):

>    addedge({{a1,a2},{a1,a3},{a6,a7},{a5,a6}},H):

>    draw(H);

[Maple Plot]

>    degreeseq(H);

[0, 1, 1, 1, 1, 2, 2]

Si quisiéramos preestablecer un orden sobre los vértices, los convertimos en lista y tomamos la sucesión de los grados. Así sabemos exactamente a qué ordenación corresponde la sucesión de los grados:

>    L:=[op(vertices(H))]; vdegree(L[1],H);

L := [a2, a3, a1, a4, a5, a6, a7]

1

>    for i from 1 to nops(L) do c[i]:=vdegree(L[i],H):od: seq(c[j],j=1..nops(L));

1, 1, 2, 0, 1, 2, 1

>   

1.3. Escribir un procedimiento que calcule la suma de los grados de todos los vértices de un grafo.

Simplemente sumar los elementos de la lista que da degreeseq.

1.4.   Emplearlo para verificar que dicha suma es siempre el doble del número de aristas del grafo.

1.5. Escribir un procedimiento que calcule el número de vértices con grado impar de un grafo.

 

2. Matrices de adyacencia

2.1. Define un procedimiento que convierta una matriz cuadrada A  de ceros y unos en un grafo cuya matriz de adyacencia sea A .

Se trata de tomar la matriz de ceros y unos y construir un grafo que tiene como vértices un conjunto del tamaño de la matriz y donde {i,j}  es una arista si y solamente si A[i,j]=1 .

>    restart; with(linalg):with(networks):

Warning, the protected names norm and trace have been redefined and unprotected

Warning, the names charpoly and rank have been redefined

 Para construir los vértices se puede hacer el siguiente procedimiento que toma el tamaño n de la matriz y como conjunto de vértices {1,2,..., n} :

>    Vertices:=proc(A::matrix)
local L,i:
L:={}:
for i from 1 to rowdim(A) do
L:=L union {i}: od: L; end:

>    Vertices(matrix(2,2,[0,1,1,0]));

{1, 2}

Para construir las aristas:

>    Aristas:=proc(A::matrix)
local L,i,j:
L:={}:
for i from 1 to rowdim(A) do
    for j from 1 to coldim(A) do
       if A[i,j]=1 then L:=L union {{i,j}}: fi:
    od:
od: L; end:

>    Aristas(matrix(2,2,[0,1,1,0]));

{{1, 2}}

Para construir el grafo:

>    grafo:=proc(A::matrix)
local G:
G:=new():
addvertex(Vertices(A),G):
addedge(Aristas(A),G):
G; end:

>    draw(grafo(matrix(2,2,[0,1,1,0])));

[Maple Plot]

Veamos por ejemplo el grafo completo K5 . Su matriz tiene todas las entradas iguales a 1 salvo la diagonal:

>    M:=matrix(5,5,[0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0]);

M := matrix([[0, 1, 1, 1, 1], [1, 0, 1, 1, 1], [1, 1, 0, 1, 1], [1, 1, 1, 0, 1], [1, 1, 1, 1, 0]])

>    draw(grafo(M));

[Maple Plot]

Por ejemplo dada la matriz:

>    M:=matrix(4,4,[0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0]);

M := matrix([[0, 1, 0, 0], [1, 0, 1, 1], [0, 1, 0, 0], [0, 1, 0, 0]])

El grafo que la tiene como matriz de adyacencias es:

>    draw(grafo(M));

[Maple Plot]

>   

3. Conexión

3.1. Define un procedimiento Maple para averiguar si un grafo es conexo..

3.2. Haz lo mismo que en el ejercicio anterior, pero considerando ahora que el dato de entrada será la matriz de adyacencia del grafo.

Test curso 2000/2001

1.- Calcula el número de entradas no nulas de la matriz de adyacencias de Q[6] . (Se recomienda crear un procedimiento para contar las entradas no nulas de una matriz). Respuesta:

>   

>    with(networks):

>    M:=adjacency(cube(6)):

>    with(linalg): coldim(M);

Warning, the names charpoly and rank have been redefined

64

>    c:=0; for i from 1 to 64 do for j from 1 to 64 do c:=c+M[i,j] od; od; c;

c := 0

384

>   

>   

>    N:=incidence(cube(6)):

>    coldim(N); rowdim(N);

192

64

>    c:=0; for i from 1 to 64 do for j from 1 to 192 do c:=c+N[i,j] od; od; c;

c := 0

384

>   

>   

>    M:=adjacency(complete(3,3)):

>    with(linalg): coldim(M);

6

>   
c:=0; for i from 1 to 6 do for j from 1 to 6 do c:=c+M[i,j] od; od; c;

c := 0

18

>    384+18;

402

>   

>   

>    restart; with(linalg): A:=matrix([[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1], [1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1], [1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0], [1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0], [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0]]);

Warning, the protected names norm and trace have been redefined and unprotected

A := matrix([[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 1, 1, ...

>   

>   

Es conexo porque todos los vértices son adyacentes con el primero. Como todos los vértices son de grado par, es euleriano. La respuesta es la c).

 6.- Siendo G el grafo cuya  matriz de adyacencia es la matriz A de la cuestión número cuatro ¿Cuántos caminos de longitud 3 hay entre el primer y el tercer vértice?

>   

>    evalm(A^3)[1,3];

25

>   

>   

El primer vértice es adyacente con todos los demás por tanto hay 10 caminos no simples de longitud 3 de la forma (1a13). Por otro lado el tercer vértice es adyacente con otros 4 por tanto hay otros 4 caminos no simples de longitud 3 de la forma (13b3). Observar que no hay más caminos no simples y que (1313) está siendo contado 2 veces.

>    25-13;

12

>   

>   

>    with(networks): G:=new():

Warning, the names charpoly and rank have been redefined

>    addvertex({1,2,3,4,5,6,7,8,9},G);

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

>    addedge({{1,2},{1,3},{2,4},{2,5},{3,6},{3,7},{7,8},{7,9}},G);

e1, e2, e3, e4, e5, e6, e7, e8

>    draw(G);

[Maple Plot]

>   

>   

Es un árbol. Respuesta a).

10.- ¿Cuántos vértices de grado impar tiene la unión disjunta Q[4]   y K[4,4]   ?

>   

Los vértices de cada uno de los grafos del enunciado son de grado 4, por tanto respuesta c).

Test curso 2001/2002

>    restart: with(networks): with(linalg):

Warning, the names charpoly and rank have been redefined

Warning, the protected names norm and trace have been redefined and unprotected

>    M:=matrix([[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1], [0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1], [1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1], [1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0], [1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1], [1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0], [0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1], [0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1], [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1], [0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], [1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1], [1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0], [1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0], [1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0], [0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0], [1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1], [0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1], [1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0], [0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0], [1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0], [0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1], [1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1], [0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], [1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1], [1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1], [0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1], [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1], [0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0]]):

1.-Sea un grafo simple G una de cuyas matrices de ayacencias es M:

a) G tiene 50 vértices y 601 aristas.

b) G tiene 40 vértices y 550 aristas.

c) G tiene 50 vértices y 400 aristas.

El número de vértices de G es el número de filas (o de columnas) de M:

>    rowdim(M);

50

Para calcular el número de aristas recordamos que la suma de los grados de los vértices (esto es el número de unos en M) es el doble del número de aristas:

>    S:=0:
for i from 1 to 50 do:
for j from 1 to 50 do:
S:=S+M[i,j]: od: od: S/2;

601

>   

Por tanto tiene 601 aristas. La respuesta correcta es la a).

2.- Determinar el grado del vértice tercero en la ordenación de los vértices que define la matriz M.

a) 32

b) 54
c) 20

El grado del vértice tercero es la suma de los elementos de la fila (o columna) tercera

>    gr(3):=0:
for t from 1 to 50 do:
gr(3):=gr(3)+M[3,t]: od: gr(3);

20

>   

La respuesta correcta es la c).

3.- Determinar el número de caminos de longitud 3 que hay entre el vértice 40 y el 50 del grafo G.

a) 309

b) 291

c) 290

La matriz M^3 es la que contiene dicha información:

>    evalm(M^3)[40,50];

291

>    evalm(M^3)[50,40];

291

La respuesta correcta es la b)

4.- El grafo G verifica

a) es conexo

b) tiene dos componentes conexas

c) no se puede saber si es conexo o no

Tomamos la matriz al cuadrado, si no tiene entradas no nulas entonces todo par de vértices está unido por un camino de longitud 2 con lo que el grafo es conexo.

>    C:=evalm(M^2):

>    S:=0:
for z from 1 to 50 do
for t from 1 to 50 do
if C[z,t]=0 then S:=S+1: fi:
od: od: S;

0

>   

La respuesta correcta es la a).

5.- El grafo G verifica:

a) es un árbol

b) no es un árbol porque es no conexo

c) no es un árbol porque contiene ciclos

Como un árbol de n vértices tiene n-1  aristas y G es conexo (con 50 vértices y 600 aristas)

entonces la respuesta correcta es la c).

6.- El grafo completo K6 verifica .

a) es conexo tiene 6 vértices y 15 aristas, el grado de cada vértice es 6.

b) es conexo tiene 6 vértices y 15 aristas, el grado de cada vértice es 5.

c) es conexo tiene 6 vértices y 21 aristas, el grado de cada vértice es 5.

>    restart;with(networks):

>    nops(vertices(complete(6)));

6

>    nops(ends(complete(6)));

15

>    degreeseq(complete(6));

[5, 5, 5, 5, 5, 5]

>    components(complete(6));

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

La respuesta correcta es la b).

>    H:=new():

>    addvertex({seq(i,i=1..30)},H):

>    addedge({{1,2},{1,4},{3,2},{5,6},{21,12},{21,22},{4,20},{1,7},{8,9},{1,5},{1,20},{3,24},{21,3},{11,24},{15,26},{16,20},{10,20},{1,29},{21,6},{11,4},{13,22},{15,16},{17,19},{19,20},{14,7},{13,7}},H):

7.- Sea el grafo simple H definido arriba. Dicho grafo verifica:

a) es conexo

b) no es conexo porque tiene tres componentes conexas

c) no es conexo porque tiene ocho componentes conexas

>    draw(H);

[Maple Plot]

Vemos con el dibujo que es no conexo. Podemos computar el número de sus componentes conexas.

>    nops(components(H));

8

>   

La respuesta correcta es la c).

8.- El grado del vértice de mayor grado de H y el del de menor grado son respectivamente:

a) 6 y 0

b) 7 y 0

c) 5 y 0

>    degreeseq(H);

[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6]

>   

La respuesta correcta es la a).

9.- Sea el subgrafo L de H que forma la componente conexa con mayor número de vértices.

a) L es euleriano

b) L no es euleriano porque es no conexo

c) L no es euleriano

>    components(H);

{{1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 24, 26, 29}, {28}, {27}, {25}, {23}, {18}, {8, 9}, {30}}

Tomo la componente que tiene el mayor número de vértices. Construyo un nuevo grafo L con dichos vértices y con todas las aristas de H salvo la {8,9} que es la única que está en otra componente conexa. Este grafo L es por definición conexo.

>    L:=new():

>    addvertex({3, 26, 22, 24, 20, 21, 16, 17, 19, 13, 14, 15, 10, 11, 12, 6, 7, 1, 2, 4, 5, 29},L):

>    addedge({{1,2},{1,4},{3,2},{5,6},{21,12},{21,22},{4,20},{1,7},{1,5},{1,20},{3,24},{21,3},{11,24},{15,26},{16,20},{10,20},{1,29},{21,6},{11,4},{13,22},{15,16},{17,19},{19,20},{14,7},{13,7}},L):

>    degreeseq(L);

[1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6]

>   

>   

Como hay vértices de grado impar la respuesta correcta es la c).

10.- Determina el número de vértices de grado impar de L.

a) L tiene 10 vértices de grado impar

b) L tiene 11 vértices de grado impar

c) L tiene 12 vértices de grado impar

La respuesta correcta es la a).

>    S:=0:
for k from 1 to nops(vertices(L)) do
if degreeseq(L)[k] mod 2<>0 then S:=S+1: fi: od: S;

10

>   

>   

Test curso 2002/2003

>    restart: with(networks): with(linalg):

Warning, the names charpoly and rank have been redefined

Warning, the protected names norm and trace have been redefined and unprotected

Sea A la matriz definida por

>    A:=matrix([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]):

>   

1. Sea el grafo simple G=(V,E)  una de cuyas matrices de adyacencias es A.

a) G tiene 45 vértices y 506 aristas.

b) G tiene 60 vértices y 206 aristas.

c) G tiene 45 vértices y 1012 aristas.

>    rowdim(A);

45

>    s:=0:
for i from 1 to rowdim(A) do
for j from i to coldim(A) do
s:=s+A[i,j]:
od:
od:
s;

506

>   

La respuesta correcta es la a).

2. El grafo G verifica:

a) tiene 23 vértices de grado impar.

b) tiene 22 vértices de grado impar.

c) tiene 24 vértices de grado par.

>    for i from 1 to rowdim(A) do
g[i]:=add(A[i,j],j=1..rowdim(A)):
od: seq(g[i],i=1..rowdim(A));

23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22

>    s:=0:
for i from 1 to rowdim(A) do
if g[i] mod 2 =1 then s:=s+1 fi od:
s;

22

>   

La respuesta correcta es la b).

3. El número de caminos de longitud 27 uniendo el vértice 1 y el 22 del grafo G  es

a)   142546552694430788571794496737878016

b) 1

c) 0

>    evalm(A^27)[1,22];

0

>   

La respuesta correcta es la c).

4. Señalar la respuesta correcta:

a) el grafo G es conexo.

b) el grafo G tiene dos componentes conexas.

c) el grafo G tiene más de tres componentes conexas .

>    Vertices:=proc(A::matrix)
local L,i:
L:={}:
for i from 1 to rowdim(A) do
L:=L union {i}: od: L; end:

>    Aristas:=proc(A::matrix)
local L,i,j:
L:={}:
for i from 1 to rowdim(A) do
    for j from 1 to rowdim(A) do
       if A[i,j]=1 then L:=L union {{i,j}}: fi:
    od:
od: L; end:

>    grafo:=proc(A::matrix)
local G:
G:=new():
addvertex(Vertices(A),G):
addedge(Aristas(A),G):
G; end:

>    G:=grafo(A):

>    nops(components(G));

1

>   

La respuesta correcta es la a).

5. Determinar el número de caminos simples de longitud 3 entre el vértice 1 y el vértice 45 del grafo G.

a)  462

b)  506

c)  461

El número total de caminos de longitud 3 es:

>    evalm(A^3)[1,45];

506

Obsérvese que 1 y 45 son adyacentes:

>    A[1,45];

1

El número de caminos no simples de la forma 1a1(45) es el grado del vértice 1:

>    L:=seq(A[1,i],i=1..rowdim(A)):
g:=0:
for i from 1 to rowdim(A) do
g:=g+L[i]:
od:
g;

23

El número de caminos no simples de la forma 1(45)b(45) es el grado del vértice 45:

>    L:=seq(A[45,i],i=1..rowdim(A)):
g:=0:
for i from 1 to rowdim(A) do
g:=g+L[i]:
od:
g;

22

De esta forma, estamos contando el camino 1(45)1(45) dos veces: cuando a = 45 y cuando b=1.

El número de caminos simples es

>    506-23-22+1;

462

La respuesta correcta es la a)

>   

6. El grafo G

a) es bipartido no completo.

b) es bipartido completo.

c) no es bipartido.

La sucesión de los grados de los vértices de G es:

>    degreeseq(G);

[22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23]
[22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23]

Si G es bipartido completo, tiene que ser isomorfo a   K[22,23]   y  tener  

>    22*23;

506

aristas.

Para verificar si G es bipartido, ordenamos sus vértices

>    L:=[op(vertices(G))];

L := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]
L := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]

y definimos las sucesiones   s1  y s2  de los vértices de grado 22 y 23, respectivamente.

>    j:=1:
for i from 1 to 45 do
if vdegree(L[i],G)=22 then a[j]:=L[i];
j:=j+1;
fi;
od;

>    s1:=seq(a[i],i=1..23);

s1 := 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45

>    j:=1:
for i from 1 to 45 do
if vdegree(L[i],G)=23 then b[j]:=L[i];
j:=j+1;
fi;
od;

>    s2:=seq(b[i],i=1..22);

s2 := 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22

Finalmente, podemos dibujar G:

>    draw(Linear([s1],[s2]),G);

[Maple Plot]

>   

La respuesta correcta es la b).

>   

7. El grafo G

a) es Euleriano.

b) no es Euleriano.

c) no se puede saber si es o no Euleriano.

>   

>   

8. Supongamos que los vértices de G son numerados siguiendo el orden que marca la matriz de adyacencias A de G.  

Sea el grafo simple H=(W,F)  donde:

>    W:={3,5,9,45};

W := {3, 5, 9, 45}

>    F:={[3,5],[5,45],[9,45]};

F := {[3, 5], [5, 45], [9, 45]}

a) el grafo resultado de unir G  y H tiene 1 arista más que G.

b) el grafo resultado de unir G  y H tiene 3 aristas más que G.

c) el grafo resultado de unir G  y H tiene las mismas aristas que G.

>    A[3,5]; A[5,45]; A[9,45];

0

1

1

La respuesta correcta es la a).

>   

9. Sea el grafo completo K2. El producto cartesiano GxK2 tiene

a) 90 vértices y  506 aristas.

b) 45 vértices y 1012 aristas.

c) 90 vértices y 1057  aristas.

Como el conjunto de vértices del producto cartesiano es el producto de los correspondientes conjuntos de vértices, tiene 90 elementos.

Si G=(V,E),  el cardinal del conjunto de aristas del producto cartesiano es   2|E|+|G| :

>    2*506+45;

1057

La respuesta correcta es la c).

>   

10. El grafo G

a) tiene 45 vértices de corte

b) no tiene vértices de corte

c) tiene aristas de corte

La respuesta correcta es la b).

>    #fin

Práctica 5

Matemática Discreta

PRÁCTICA 5

RELACIONES

[Maple OLE 2.0 Object]

 Introducción

Instrucciones

En esta práctica emplearemos Maple para trabajar con relaciones binarias en un conjunto. Como sabemos, una relación binaria en un conjunto A es un subconjunto R del producto cartesiano AxA.

 Las relaciones se pueden representar de distintas maneras: mediante la definición, esto es, el par (A,R) formado por el conjunto A y la relación R subconjunto del producto cartesiano AxA; mediante una gráfica en un plano coordenado (donde cada eje está representando el conjunto A); mediante el grafo dirigido (A,R) asociado a la relación o mediante una matriz de adyacencias de dicho grafo.

Cada una de estas representaciones tendrá ventajas e inconvenientes a la hora de analizar propiedades de las relaciones. En esta práctica veremos cómo construir cada una de estas representaciones de las relaciones y cómo estudiar ciertas propiedades con dichas representaciones.

 Representación de relaciones

La primera de las representaciones de una relación que se ha comentado en la introducción es mediante una gráfica (lo que resulta muy habitual cuando hablamos de funciones). Para esta representación usaremos la función plot.

Sea por ejemplo la relación:

>    restart;
A:={a,b,c,d}; R:={[a,a],[b,b],[c,c],[d,d],[a,b],[b,c],[a,c]};

A := {b, c, d, a}

R := {[b, c], [a, c], [a, a], [b, b], [c, c], [d, d], [a, b]}

Para representarla mediante el comando plot, necesitamos valores numéricos por lo tanto hacemos la sustitución de las letras por números

>    N:=subs(a=1,b=2,c=3,d=4,R);

N := {[1, 3], [3, 3], [2, 3], [4, 4], [1, 2], [1, 1], [2, 2]}

Ahora mediante plot podemos representar la secuencia de los pares de N

>    plot([op(N)],x=0..4,y=0..4,style=point);

[Maple Plot]

Si queremos trabajar con la representación por el grafo dirigido asociado, sencillamente cargamos el paquete que permite trabajar con los grafos:

>    with(networks):

>    G:=new():

>    addvertex(A,G);

b, c, d, a

>    addedge(R,G);

e1, e2, e3, e4, e5, e6, e7

Recordamos que al pintar el grafo dirigido, maple no representa ni lazos, ni direcciones en las aristas, por lo que la representación gráfica de G no será muy ilustrativa:

>    draw(G);

[Maple Plot]

Tampoco la matriz de adyacencias de G recoge toda esta información.

>    adjacency(G);

Matrix(%id = 3119284)

Por tanto debemos diseñar un procedimiento que compute la matriz de adyacencias del digrafo G. Cargamos primero el paquete linalg, que contiene ciertos comandos para trabajar con matrices.

>    with(linalg):

Warning, the names charpoly and rank have been redefined

Warning, the protected names norm and trace have been redefined and unprotected

Como la matriz de adyacencias depende de una ordenación en el conjunto de los vértices (y para evitar ciertos problemas en cómo maple convierte un conjunto en una lista) el procedimiento se aplicará sobre un par formado por una lista y la relación. Obsérvese que estamos declarando el tipo de datos en el procedimiento.

>    MatrizRelacion:=proc(D::list,R::set([anything,anything]))
 local i,j,L;
 L:=[];
 for i from 1 to nops(D) do
   for j from 1 to nops(D) do
     if member([[op(D)][i],[op(D)][j]],R) then
       L:=[op(L),1] else L:=[op(L),0];
     fi;
   od;
 od;
 evalm(matrix(nops(D),nops(D),L));
end:

>    M:=MatrizRelacion([a,b,c,d],R);

M := matrix([[1, 1, 1, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 1]])

Observamos que si se toma el conjunto :

>    B:={2,a,3}:

Y hacemos una lista con los elementos del conjunto:

>    [op(B)];

[2, 3, a]

La lista no ha respetado el orden con que nosotros definimos el conjunto B y la matriz del digrafo puede llevarnos a confusión, por eso hemos elegido que el procedimiento funcione sobre listas en vez de sobre conjuntos.

Finalmente supongamos que tenemos un conjunto A ordenado y la matriz que representa una relación en A con esa ordenación entonces podemos recuperar la relación mediante el siguiente procedimiento:

>    RelacionMatriz:=proc(M::matrix(square))
  
local i,j,R;
  R:={};
  for i from 1 to coldim(M) do
   for j from 1 to coldim(M) do
     if(M[i,j]=1) then R:=R union {[i,j]};
     fi;
   od;
  od;
RETURN(R);
end:

>    S:=RelacionMatriz(M);

S := {[1, 3], [3, 3], [2, 3], [4, 4], [1, 2], [1, 1], [2, 2]}

Observamos que no aparece la relación tal y como la definimos sino sobre el conjunto {1,2,3,4} que es biyectivo con A mediante la aplicación que ha establecido la propia ordenación. Para recuperar entonces R

>    subs(1=a,2=b,3=c,4=d,S);

{[b, c], [a, c], [a, a], [b, b], [c, c], [d, d], [a, b]}

>   

>   

 Estudio de las propiedades de una relación

Propiedad reflexiva

Para comprobar si una relación R definida sobre un conjunto A es reflexiva hay que verificar que cada par (a,a) (con a un elemento de A) es un elemento de R.

Si miramos la representación gráfica   se trata de verificar si toda la diagonal está contenida en la gráfica, la gráfica p1 es laráfica de la diagonal cuya ecuación es y=x:

>    p1:=plot(x,x=0..4):

>    p2:=plot([op(N)],style=point):

>    plots[display](p1,p2);

[Maple Plot]

Si vemos la relación por la definición, esto es, como un subconjunto del producto cartesiano , se trata de ver si la diagonal está totalmente contenida en R.

>    Diagonal:={seq([[op(A)][i],[op(A)][i]],i=1..nops(A))};

Diagonal := {[a, a], [b, b], [c, c], [d, d]}

Para comprobar la inclusión tomamos el conjunto resultado de restar a la diagonal el conjunto R  y debe ser el conjunto vacío:

>    Diagonal minus R;

{}

Como así ocurre en efecto.

Para ver esta propiedad sobre el  grafo  se trata de comprobar si hay un lazo sobre cada vértice. Como la gráfica que presenta maple del digrafo no representa los lazos, no hay una manera de comprobar la propiedad reflexiva diferente de la conjuntista presentada en el párrafo anterior.

Para hacer el análisis sobre la matriz se trata de ver si la diagonal principal está formada por unos:

>    M := matrix([[1, 1, 1, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 1]]);

M := matrix([[1, 1, 1, 0], [0, 1, 1, 0], [0, 0, 1, 0], [0, 0, 0, 1]])

>    seq(M[i,i],i=1..nops(A));

1, 1, 1, 1

No es difícil diseñar un procedimiento que lo compruebe sobre una matriz:

>    Mref:=proc(M::matrix)
local j,S,r:
S:=0:
for j from 1 to coldim(M)
do S:=S+M[j,j]: od:
if S=coldim(M) then r:="reflexiva": else r:="no reflexiva":
fi:
r; end:

>    Mref(M);

>    Mref(matrix(2,2,[1,0,0,0]));

>   

Propiedad simétrica y antisimétrica

Sobre la representación gráfica se trata de observar si la nube de puntos es simétrica con respecto a la diagonal del primer cuadrante, esto es, si (a,b) es un punto de la gráfica, también lo es (b,a). Sea la relación:

>    A:={1,2,3,4,5}; R:={[1,2],[2,1],[1,3],[3,1],[4,4],[5,5]};

A := {1, 2, 3, 4, 5}

R := {[2, 1], [3, 1], [5, 5], [1, 3], [4, 4], [1, 2]}

La representamos mediante una tabla.

>    p1:=plot([op(R)],x=0..5,y=0..5,style=point):

>    p2:=plot(x,x=0..5):

>    plots[display]({p1,p2});

[Maple Plot]

Que es en efecto una gráfica simétrica. Para que sea antisimétrica  debe verificarse que el simétrico de cada punto de la nube que no esté sobre la diagonal no es un punto de la nube.

Para ver que la relación es simétrica mediante la definición como subconjunto del producto cartesiano  se trata de comprobar que el conjunto S formado por los pares (b,a) donde (a,b) es un elemento de la relación es igual que R.

>    S:={seq([op(R)[i][2],op(R)[i][1]],i=1..nops(R))};

S := {[2, 1], [3, 1], [5, 5], [1, 3], [4, 4], [1, 2]}

>    R minus S; S minus R;

{}

{}

Por tanto se tiene la simetría de la relación.

Para comprobar si es antisimétrica  el conjunto R intersección S debe estar contenido en la diagonal.

>    Diagonal:={seq([[op(A)][i],[op(A)][i]],i=1..nops(A))}:

>    (R intersect S) minus Diagonal;

{[2, 1], [3, 1], [1, 3], [1, 2]}

Como hay puntos de la intersección que no están sobre la diagonal, la relación no puede ser antisimétrica.

Sobre el digrafo se trataría de comprobar:

                  a) para la propiedad simétrica: que cada par de vértices distintos o no son adyacentes o están unidos por un par de aristas (cada una dirigida en un sentido);

                  b) para la propiedad antisimétrica que cada par de vértices distintos o no son adyacentes o están unidos por una única arista.

Como el gráfico de maple no presenta las direcciones de las aristas, no hay nada nuevo con respecto al párrafo anterior

Sobre la matriz, para la propiedad simétrica,  se trata de comprobar si es una matriz simétrica:

 

>    M:=MatrizRelacion([1,2,3,4,5],R);

M := matrix([[0, 1, 1, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]])

>    with(linalg): evalm(M-transpose(M));

matrix([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]])

Esto se puede escribir en un procedimiento:

>    Msim:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M-transpose(M)):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 then S:=1: fi: od: od:
if S=1 then r:="no simetrica" else r:="simetrica" fi:
r; end:

>    Msim(M);

>    Msim(matrix(2,2,[1,0,1,0]));

Para la propiedad antisimétrica se trata de comprobar que no hay ninguna entrada M[i,j]=M[j,i]=1 con i distinto de j.

>    Mantisim:=proc(M::matrix)
local N,S,i,j,r:
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if M[i,j]=1 and M[j,i]=1 and i<>j then S:=1: fi: od: od:
if S=1 then r:="no antisimetrica" else r:="antisimetrica" fi:
r; end:

>    Mantisim(M);

Si tomamos la matriz de una relación antisimétrica por ejemplo:

>    A:=matrix(4,4,[1,1,1,1,0,1,1,1,0,0,1,1,0,0,0,1]);

A := matrix([[1, 1, 1, 1], [0, 1, 1, 1], [0, 0, 1, 1], [0, 0, 0, 1]])

>    Mantisim(A);

>   

Propiedad transitiva

La representación gráfica  no aporta ningún método reseñable para comprobar la transitividad.

Diseñemos un procedimiento para comprobar la propiedad transitiva en la definición conjuntista . Los métodos que se han presentado para la propiedad reflexiva y para la simétrica se pueden escribir como un procedimiento que opere sobre relaciones y aporte una respuesta afirmativa o negativa a la pregunta sobre si una relación verifica o no una propiedad. En el libro de referencia se pueden encontrar todos estos procedimientos.

>    Transitiva:=proc(A::list,R::set)
 local u,v,w; for u from 1 to nops(A) do
   for v from 1 to nops(A) do
     for w from 1 to nops(A) do
      if(member([A[u],A[v]],R) and member([A[v],A[w]],R) and not member([A[u],A[w]],R))        then RETURN(false);
      fi;
     od;
    od;
   od;
   RETURN(true);
end:

>    A:=[a,b,c,d]; R:={[a,a],[a,b],[b,a],[b,c],[a,c]};

A := [a, b, c, d]

R := {[b, a], [b, c], [a, c], [a, a], [a, b]}

>    Transitiva(A,R);

false

Para preguntarnos sobre la transitividad de una relación mirando su matriz, recordamos que dicha matriz A debe cumplir que las entradas no nulas de A^2 son entradas no nulas de A.

Por tanto, para razonar sobre la matriz será útil un procedimiento que transforme una matriz M en otra matriz con un uno donde M tiene una entrada no nula y un 0 donde M tiene una entrada nula.

>    Matrizdeunosyceros:=proc(M::matrix)
  local i,j,Mat;
  Mat:=matrix(rowdim(M),coldim(M),0);
  for i from 1 to rowdim(M) do
   for j from 1 to coldim(M) do
    if(M[i,j]<>0) then Mat[i,j]:=1;
    fi;
   od;
  od;
RETURN(eval(Mat));
end:

>    M:=matrix(3,3,[1,1,1,2,1,3,0,9,4]);

M := matrix([[1, 1, 1], [2, 1, 3], [0, 9, 4]])

>    Matrizdeunosyceros(M);

matrix([[1, 1, 1], [1, 1, 1], [0, 1, 1]])

Por tanto dada la matriz de una relación:

>    M:=matrix(3,3,[1,1,1,0,1,0,0,1,1]);

M := matrix([[1, 1, 1], [0, 1, 0], [0, 1, 1]])

Calculamos la matriz de unos y ceros del cuadrado de M

>    Matrizdeunosyceros(evalm(M^2));

matrix([[1, 1, 1], [0, 1, 0], [0, 1, 1]])

Como son iguales la relación es transitiva.

Podemos escribir un procedimiento:

>    Mtrans:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M^2):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 and M[i,j]=0 then
S:=1: fi: od: od:
if S=1 then r:="no transitiva" else r:="transitiva":
fi:r; end:

>    Mtrans(M);

Si tomamos la siguiente matriz, cuyo cuadrado tiene entradas no nulas nuevas, el procedimiento debe indicar que no es transitiva:

>    A:=matrix(4,4,[1,1,1,1,0,0,0,0,1,0,1,0,1,0,0,0]);

A := matrix([[1, 1, 1, 1], [0, 0, 0, 0], [1, 0, 1, 0], [1, 0, 0, 0]])

>    Mtrans(A);

>    evalm(A^2);

matrix([[3, 1, 2, 1], [0, 0, 0, 0], [2, 1, 2, 1], [1, 1, 1, 1]])

Con, en efecto, entradas no nulas con respecto a A.

>   

 Clausuras

Recordamos que la clausura reflexiva, simétrica o transitiva de una relación R en un conjunto A es la mínima relación que contiene a R y verifica la propiedad que se necesite.

Clausura reflexiva

Sea una relación (A,R) la clausura reflexiva es por tanto el mínimo subconjunto de AxA que contiene a R y a la diagonal

{(a,a): a elemento de A}. Por tanto se trata simplemente de la unión de R y dicha diagonal.

>    A:={a,s,d,f}; R:={[a,s],[a,d],[d,d],[d,f],[s,f]};

A := {f, d, a, s}

R := {[a, d], [d, d], [a, s], [d, f], [s, f]}

>    Diagonal:={seq([op(A)[i],op(A)[i]],i=1..nops(A))};

Diagonal := {[a, a], [d, d], [f, f], [s, s]}

La clausura es la unión:

>    R union Diagonal;

{[a, d], [a, a], [d, d], [a, s], [d, f], [s, f], [f, f], [s, s]}

La matriz de la clausura reflexiva se construye completando la diagonal de la matriz de la relación con un uno en aquellos lugares en que la matriz tenga un cero. Es decir sumando la matriz identidad y luego computando la matriz de unos y ceros.

>    Q:=MatrizRelacion([a,s,d,f],R);

Q := matrix([[0, 1, 1, 0], [0, 0, 0, 1], [0, 0, 1, 1], [0, 0, 0, 0]])

>    I4:=diag(1,1,1,1);

I4 := matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])

>    Matrizdeunosyceros(evalm(Q+I4));

matrix([[1, 1, 1, 0], [0, 1, 0, 1], [0, 0, 1, 1], [0, 0, 0, 1]])

Clausura simétrica

Sea una relación (A,R) la clausura simétrica es por tanto el mínimo subconjunto de AxA que contiene a R y al conjunto simétrico de R {(b,a): donde (a,b) es un elemento de R}. Por tanto se trata simplemente de la unión de R y dicho conjunto simétrico S

>    A:={a,s,d,f}; R:={[a,s],[a,d],[d,d],[d,f],[s,f]};

A := {f, d, a, s}

R := {[a, d], [d, d], [a, s], [d, f], [s, f]}

>    S:={seq([op(R)[i][2],op(R)[i][1]],i=1..nops(R))};

S := {[d, a], [d, d], [f, s], [f, d], [s, a]}

La clausura simétrica es simplemente hacer la unión:

>    R union S;

{[d, a], [a, d], [d, d], [f, s], [f, d], [s, a], [a, s], [d, f], [s, f]}

Sobre la matriz se trata de sumar la matriz con su transpuesta y computar la matriz de unos y ceros de dicha suma.

>    Q:=MatrizRelacion([a,s,d,f],R);

Q := matrix([[0, 1, 1, 0], [0, 0, 0, 1], [0, 0, 1, 1], [0, 0, 0, 0]])

>    evalm(Q+transpose(Q));

matrix([[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 2, 1], [0, 1, 1, 0]])

>    C:=Matrizdeunosyceros(%);

C := matrix([[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 1, 1], [0, 1, 1, 0]])

Que es una matriz simétrica

>    evalm(C-transpose(C));

matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]])

Clausura transitiva

Sea una relación (A,R) la clausura transitiva es por tanto el mínimo subconjunto de AxA que contiene a R y verifica la propiedad transitiva.Vamos a centrarnos en los algoritmos que tienen como entrada la matriz de la relación.

El primer algoritmo que presentamos en clase es el que relaciona la transitividad con la conexión, de modo que para calcular la clausura transitiva de una relación de matriz M (de tamaño nxn) hay que tomar las sucesivas potencias de M hasta llegar a la potencia n-ésima, sumarlas todas y calcular su matriz de unos y ceros.

>    A:={a,s,d,f,g}; R:={[a,s],[a,d],[d,d],[d,f],[s,f],[f,g],[g,g]};

A := {g, f, d, a, s}

R := {[a, d], [d, d], [a, s], [d, f], [s, f], [f, g], [g, g]}

>    Q:=MatrizRelacion([a,s,d,f,g],R);

Q := matrix([[0, 1, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 1, 1, 0], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1]])

>    Matrizdeunosyceros(evalm(add(Q^n,n=1..5)));

matrix([[0, 1, 1, 1, 1], [0, 0, 0, 1, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1]])

El otro algoritmo que se presentaba es el Algoritmo de Warshall que reduce la complejidad:

>    Warshall:=proc(M::matrix)
  local i,j,k,W,n;
  W:=matrix(rowdim(M),coldim(M),[seq(seq(M[i,j],j=1...coldim(M)),i=1..coldim(M))]):
  n:=coldim(M);
  for k from 1 to n do
   for i from 1 to n do
    for j from 1 to n do
     W[i,j]:=W[i,j]+(W[i,k]*W[k,j]);
    od;
   od;
  od;
 Matrizdeunosyceros(W);
end:

>    Warshall(Q);

matrix([[0, 1, 1, 1, 1], [0, 0, 0, 1, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 1], [0, 0, 0, 0, 1]])

Test del curso 2000/2001

 Sea la siguiente relación.

>    restart; A:={a,b,c,d,e,f,g,h,i,j};

A := {h, i, j, e, f, g, a, b, c, d}

>    R:={[a,b],[a,c],[b,b],[c,b],[c,c],[a,f],[g,h],[h,i],[h,j],[j,i],[j,a],[a,a],[d,d],[j,f],[e,e],[f,j],[g,g],[j,j],[i,i],[e,b],[e,a],[f,f],[h,h]};

R := {[h, h], [f, j], [g, g], [j, j], [i, i], [e, b], [e, a], [f, f], [h, j], [j, a], [a, a], [d, d], [j, f], [e, e], [j, i], [a, b], [b, b], [c, b], [c, c], [a, f], [g, h], [h, i], [a, c]}
R := {[h, h], [f, j], [g, g], [j, j], [i, i], [e, b], [e, a], [f, f], [h, j], [j, a], [a, a], [d, d], [j, f], [e, e], [j, i], [a, b], [b, b], [c, b], [c, c], [a, f], [g, h], [h, i], [a, c]}

>   

>    with(linalg): MatrizRelacion:=proc(D::list,R::set([anything,anything]))
 local i,j,L;
 L:=[];
 for i from 1 to nops(D) do
   for j from 1 to nops(D) do
     if member([[op(D)][i],[op(D)][j]],R) then
       L:=[op(L),1] else L:=[op(L),0];
     fi;
   od;
 od;
 evalm(matrix(nops(D),nops(D),L));
end:

Warning, the protected names norm and trace have been redefined and unprotected

>   

>    Q:=MatrizRelacion([a,b,c,d,e,f,g,h,i,j],R);

Q := matrix([[1, 1, 1, 0, 0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, ...

>   

>   

>   

>    Matrizdeunosyceros:=proc(M::matrix)
  local i,j,Mat;
  Mat:=matrix(rowdim(M),coldim(M),0);
  for i from 1 to rowdim(M) do
   for j from 1 to coldim(M) do
    if(M[i,j]<>0) then Mat[i,j]:=1;
    fi;
   od;
  od;
RETURN(eval(Mat));
end:

>    M:=Matrizdeunosyceros(evalm(add(Q^n,n=1..10)));

M := matrix([[1, 1, 1, 0, 0, 1, 0, 0, 1, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [1, 1, 1, 0, 1, 1, 0, 0, 1, 1], [1, 1, 1, 0, 0, 1, 0, 0, 1, ...

>    c:=0; for i from 1 to 10 do for j from 1 to 10 do c:=c+M[i,j] od; od; c;

c := 0

45

>   

>   

>    seq(Matrizdeunosyceros(evalm(Q+transpose(Q)))[7,i],i=1..10);

0, 0, 0, 0, 0, 0, 1, 1, 0, 0

Luego la respuesta correcta es la b).

>   

 4.- Sea la matriz M definida abajo:

>   

>    M:=matrix(11,11,[0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,1,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,1,2,1,1,0,0,1,1,0,1,0,1,0,0,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,1,0,2,0,1,0,1,1,1,1,1,0,0,1,0,0,1,0,1,0,0,1,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0]);

M := matrix([[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0], [1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 1, 1, ...

>   

Como no es una matriz de unos y ceros no puede ser la matriz de una relación. La respuesta correcta es la c).

>   

 5.-  La relación (B,S) definida abajo:

>   

>    B:={1,2,3,4,5,6,7,8,9}; S:={[1,1],[1,2],[1,3],[1,4],[5,6],[5,7],[5,8],[1,5],[1,6],[1,7],[1,8],[1,9],[2,2],[2,3],[2,4],[2,8],[2,9],[3,3],[3,4],[3,5],[3,6],[3,7],[3,8],[3,9],[4,4],[4,5],[4,6],[4,7],[4,8],[4,9],[5,5],[5,9],[6,6],[6,7],[6,8],[6,9],[7,7],[7,8],[7,9],[2,5],[2,6],[2,7],[8,8],[8,9],[9,9]};

B := {1, 2, 3, 4, 5, 6, 7, 8, 9}

S := {[2, 2], [1, 1], [1, 2], [1, 3], [1, 4], [5, 6], [5, 7], [5, 8], [1, 5], [1, 6], [1, 7], [1, 8], [1, 9], [2, 3], [2, 4], [2, 8], [2, 9], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9], [4,...
S := {[2, 2], [1, 1], [1, 2], [1, 3], [1, 4], [5, 6], [5, 7], [5, 8], [1, 5], [1, 6], [1, 7], [1, 8], [1, 9], [2, 3], [2, 4], [2, 8], [2, 9], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9], [4,...
S := {[2, 2], [1, 1], [1, 2], [1, 3], [1, 4], [5, 6], [5, 7], [5, 8], [1, 5], [1, 6], [1, 7], [1, 8], [1, 9], [2, 3], [2, 4], [2, 8], [2, 9], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9], [4,...

>   

>   

>   

 6.- La clausura simétrica de la relación anterior es:

>   

>   

>   

>   

7.- Sea la matriz N definida más abajo,

>   

>    N:=Matrizdeunosyceros(M);

N := matrix([[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0], [1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 1, 1, ...

>    evalm(Matrizdeunosyceros(evalm(N^2))-N);

matrix([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1], [0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1], [0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1], [0, 1, 0, 0, 0, 1,...

>   

>   

Como la diagonal de N está formada por ceros, debemos convertirlos todos en unos, por lo que hay 11 entradas diferentes, la respuesta es la a).

>   

>   

9.- Determinar los valores de a y b en la matriz X definida más abajo para que la relación que da X sea transitiva.

>   

>    X:=matrix(4,4,[1,1,a,0,1,1,b,0,0,0,a,1,0,0,1,0]);

X := matrix([[1, 1, a, 0], [1, 1, b, 0], [0, 0, a, 1], [0, 0, 1, 0]])

>    evalm(X^2);

matrix([[2, 2, a+b+a^2, a], [2, 2, a+b+b*a, b], [0, 0, 1+a^2, a], [0, 0, a, 1]])

>   

>   

>    evalm(X-transpose(X));

matrix([[0, 0, a, 0], [0, 0, b, 0], [-a, -b, 0, 0], [0, 0, 0, 0]])

La respuesta correcta es la a).

>   

Test del curso 2001/2002

>    restart: with(linalg):

Warning, the protected names norm and trace have been redefined and unprotected

>    M:=matrix([[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1], [0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1], [0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1], [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0], [1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1], [1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0], [0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1], [0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1], [0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1], [0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], [1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1], [1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0], [1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0], [1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0], [0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0], [1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], [0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1], [0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1], [1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1], [0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0], [0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0], [1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0], [0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1], [1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1], [0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], [1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0], [1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1], [1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1], [0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1], [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1], [0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0]]):

1.-Sea un conjunto A y una relación R en A representada por la matriz M:

a) el conjunto A tiene 37 elementos

b) el conjunto A tiene 50 elementos

c) el conjunto A tiene 100 elementos

El cardinal de A es el número de filas (o de columnas) de M:

>    rowdim(M);

50

La respuesta correcta es la b).

2.- La relación R es:

a) simétrica y reflexiva

b) simétrica pero no reflexiva
c) ni simétrica ni reflexiva

Traemos los procedimientos que necesitamos.

 

>    Mref:=proc(M::matrix)
local j,S,r:
S:=0:
for j from 1 to coldim(M)
do S:=S+M[j,j]: od:
if S=coldim(M) then r:="reflexiva": else r:="no reflexiva":
fi:
r; end:

>    Msim:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M-transpose(M)):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 then S:=1: fi: od: od:
if S=1 then r:="no simetrica" else r:="simetrica" fi:
r; end:

>    Mref(M); Msim(M);

La respuesta correcta es la c).

3.-  La relación R es:

a) transitiva y antisimétrica

b) ni antisimétrica ni transitiva

c) antisimetrica y no transitiva

Traemos los procedimientos que necesitamos.

>    Mantisim:=proc(M::matrix)
local S,i,j,r:
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if M[i,j]=1 and M[j,i]=1 and i<>j then S:=1: fi: od: od:
if S=1 then r:="no antisimetrica" else r:="antisimetrica" fi:
r; end:

>    Mtrans:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M^2):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 and M[i,j]=0 then
S:=1: fi: od: od:
if S=1 then r:="no transitiva" else r:="transitiva":
fi:r; end:

>    Mantisim(M); Mtrans(M);

La respuesta correcta es la b)

4.- La matriz de la clausura reflexiva de R tiene

a) 20 entradas distintas a las de M

b) 30 entradas distintas a las de M

c) 50 entradas distintas a las de M

Contamos el número de entradas nulas en la diagonal

>    S:=0:
for z from 1 to 50 do
if M[z,z]=0 then S:=S+1: fi:
od: S;

50

La respuesta correcta es la c).

5.- La matriz de la clausura simétrica de la relación R tiene:

a) 2 entradas distintas a las de M

b) 3 entradas distintas a las de M

c) 5 entradas distintas a las de M

>    Matrizdeunosyceros:=proc(M::matrix)
  local i,j,Mat;
  Mat:=matrix(rowdim(M),coldim(M),0);
  for i from 1 to rowdim(M) do
   for j from 1 to coldim(M) do
    if(M[i,j]<>0) then Mat[i,j]:=1;
    fi;
   od;
  od;
RETURN(eval(Mat));
end:

>    N:=Matrizdeunosyceros(evalm(M+transpose(M))):

Vamos a construir un procedimiento para contar el número de entradas diferentes entre dos matrices:

>    Entradas:=proc(M::matrix, N::matrix)
local S,z,t:
S:=0:
for z from 1 to coldim(M) do
for t from 1 to coldim(M) do
if N[z,t]<>M[z,t] then S:=S+1: fi:
od: od: S; end:

>    Entradas(M,N);

2

La respuesta correcta es la a).

6.- Sea el conjunto B y la relación S definidas abajo. Sea Ct la clausura transitiva de S:

a) Ct tiene 28 elementos más que S

b) Ct tiene 32 elementos más que S

c) Ct tiene 64 elementos más que S

>    B:={1,2,3,4,5,6,7,8,9,0}; S:={[1,1],[1,2],[1,3],[2,2],[2,3],[2,5],[3,3],[3,5],[3,5],[3,6],[4,5],[4,6],[4,7],[5,5],[8,5],[8,6],[8,7],[8,8],[8,9],[9,5],[9,9],[9,6],[0,0],[0,1],[0,5],[8,0],[0,4],[4,0],[7,7],[7,8],[4,3],[4,4],[8,3],[0,1],[1,0]};

B := {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

S := {[1, 2], [1, 3], [2, 3], [2, 5], [3, 3], [3, 5], [3, 6], [4, 5], [4, 6], [4, 7], [5, 5], [8, 5], [8, 6], [8, 7], [8, 8], [8, 9], [9, 5], [9, 9], [9, 6], [0, 0], [0, 1], [0, 5], [8, 0], [0, 4], [4,...
S := {[1, 2], [1, 3], [2, 3], [2, 5], [3, 3], [3, 5], [3, 6], [4, 5], [4, 6], [4, 7], [5, 5], [8, 5], [8, 6], [8, 7], [8, 8], [8, 9], [9, 5], [9, 9], [9, 6], [0, 0], [0, 1], [0, 5], [8, 0], [0, 4], [4,...

Calculamos la matriz de la relación:

>    MatrizRelacion:=proc(D::list,R::set([anything,anything]))
 local i,j,L;
 L:=[];
 for i from 1 to nops(D) do
   for j from 1 to nops(D) do
     if member([[op(D)][i],[op(D)][j]],R) then
       L:=[op(L),1] else L:=[op(L),0];
     fi;
   od;
 od;
 evalm(matrix(nops(D),nops(D),L));
end:

>    A:=MatrizRelacion([1,2,3,4,5,6,7,8,9,0],S);

A := matrix([[1, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, ...

Se trata entonces de calcular la clausura transitiva y ver el número de entradas no nulas nuevas que tiene, lo hacemos mediante el algoritmo de Warshall:

>    Warshall:=proc(M::matrix)
  local i,j,k,W,n;
W:=matrix(rowdim(M),coldim(M),[seq(seq(M[i,j],j=1...coldim(M)),i=1..coldim(M))]):
  n:=coldim(M);
  for k from 1 to n do
   for i from 1 to n do
    for j from 1 to n do
     W[i,j]:=W[i,j]+(W[i,k]*W[k,j]);
    od;
   od;
  od;
 Matrizdeunosyceros(W);
end:

>    L:=Warshall(A);

L := matrix([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, ...

>    Entradas(A,L);

28

La respuesta correcta es la a).

Si lo hacemos mediante el otro algoritmo:

>    J:=Matrizdeunosyceros(evalm(add(A**i,i=1..10))):
Entradas(A,J);

28

7.- La relación S:

a) es antisimétrica y transitiva

b) es simétrica y reflexiva

c) no es reflexiva ni simétrica ni transitiva

>    Msim(A); Mref(A); Mantisim(A); Mtrans(A);

>   

La respuesta correcta es la c).

8. Determinar los valores de a y b para que la relación que representa la siguiente matriz P sea reflexiva:

>    P:=matrix(5,5,[1,1,1,1,a,1,1,1,b,1,a,1,1,1,1,0,0,0,0,0,a,a,a,b,1]);

P := matrix([[1, 1, 1, 1, a], [1, 1, 1, b, 1], [a, 1, 1, 1, 1], [0, 0, 0, 0, 0], [a, a, a, b, 1]])

a) No hay ningún valor de a y b que la haga reflexiva

b) cualquier valor de a y b la hacen reflexiva

c) a=1, b=1.

Como

>    P[4,4];

0

La respuesta correcta es la a).

9. Idem que 8 pero para la propiedad simétrica.

a) No hay ningún valor de a y b que la haga reflexiva

b) cualquier valor de a y b la hacen reflexiva

c) a=1, b=0.

Como

>    evalm(P-transpose(P));

matrix([[0, 0, 1-a, 1, 0], [0, 0, 0, b, 1-a], [a-1, 0, 0, 1, 1-a], [-1, -b, -1, 0, -b], [0, a-1, a-1, b, 0]])

tiene entradas no nulas la matriz nunca puede ser simétrica, la respuesta correcta es la a).

10. Idem que 8 pero para la propiedad transitiva.

a) No hay ningún valor de a y b que la haga reflexiva

b) cualquier valor de a y b la hacen reflexiva

c) a=1, b=1.

Como:

>    evalm(Matrizdeunosyceros(evalm(P^2))-P);

matrix([[0, 0, 0, 0, 1-a], [0, 0, 0, 1-b, 0], [1-a, 0, 0, 0, 0], [0, 0, 0, 0, 0], [1-a, 1-a, 1-a, 1-b, 0]])

>    Q:=matrix(5,5,[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1]);

Q := matrix([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [0, 0, 0, 0, 0], [1, 1, 1, 1, 1]])

>    evalm(Q^2);

matrix([[4, 4, 4, 4, 4], [4, 4, 4, 4, 4], [4, 4, 4, 4, 4], [0, 0, 0, 0, 0], [4, 4, 4, 4, 4]])

>   

La respuesta correcta es la c).

Test del curso 2002/2003

>    restart: with(linalg):

Warning, the protected names norm and trace have been redefined and unprotected

Sea M la matriz definida por

>    M:=matrix([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]):

>   

1.-Sea un conjunto A y una relación R en A representada por la matriz M:

a) el conjunto A tiene 84 elementos

b) el conjunto A tiene 50 elementos

c) el conjunto A tiene 45 elementos

El cardinal de A es el número de filas (o de columnas) de M:

>    rowdim(M);

45

La respuesta correcta es la c).

>   

2.- La relación R es:

a) simétrica y reflexiva

b) simétrica pero no reflexiva
c) ni simétrica ni reflexiva

Traemos los procedimientos que necesitamos.

 

>    Mref:=proc(M::matrix)
local j,S,r:
S:=0:
for j from 1 to coldim(M)
do S:=S+M[j,j]: od:
if S=coldim(M) then r:="reflexiva": else r:="no reflexiva":
fi:
r; end:

>    Msim:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M-transpose(M)):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 then S:=1: fi: od: od:
if S=1 then r:="no simetrica" else r:="simetrica" fi:
r; end:

>    Mref(M); Msim(M);

La respuesta correcta es la b).

>   

3.-  La relación R es:

a) transitiva y antisimétrica

b) ni antisimétrica, ni transitiva

c) antisimétrica y no transitiva

Traemos los procedimientos que necesitamos.

>    Mantisim:=proc(M::matrix)
local S,i,j,r:
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if M[i,j]=1 and M[j,i]=1 and i<>j then S:=1: fi: od: od:
if S=1 then r:="no antisimetrica" else r:="antisimetrica" fi:
r; end:

>    Mtrans:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M^2):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 and M[i,j]=0 then
S:=1: fi: od: od:
if S=1 then r:="no transitiva" else r:="transitiva":
fi:r; end:

>    Mantisim(M); Mtrans(M);

La respuesta correcta es la b).

>   

4.- La matriz de la clausura reflexiva de R tiene

a) 0 entradas distintas a las de M

b) 45 entradas distintas a las de M

c) 40 entradas distintas a las de M

Contamos el número de entradas nulas en la diagonal

>    S:=0:
for z from 1 to rowdim(M) do
if M[z,z]=0 then S:=S+1: fi:
od: S;

45

La respuesta correcta es la b).

>   

5.- La matriz de la clausura simétrica de la relación R tiene:

a) 0 entradas distintas a las de M

b) 10 entradas distintas a las de M

c) 4 entradas distintas a las de M

>   

>    Matrizdeunosyceros:=proc(M::matrix)
  local i,j,Mat;
  Mat:=matrix(rowdim(M),coldim(M),0);
  for i from 1 to rowdim(M) do
   for j from 1 to coldim(M) do
    if(M[i,j]<>0) then Mat[i,j]:=1;
    fi;
   od;
  od;
RETURN(eval(Mat));
end:

>    N:=Matrizdeunosyceros(evalm(M+transpose(M))):

>   

>    Entradas:=proc(M::matrix, N::matrix)
local S,z,t:
S:=0:
for z from 1 to rowdim(M) do
for t from 1 to coldim(M) do
if N[z,t]<>M[z,t] then S:=S+1: fi:
od: od: S; end:

>    Entradas(M,N);

0

También, se puede utilizar el comando de Maple iszero(B), que determina si una matriz B es la matriz cero:

>    iszero(evalm(M-N));

true

La respuesta correcta es la a).

>   

6.- Sea el conjunto B y la relación S definidas abajo.

>    B:={1,2,3,4,5,6,7,8,9,0}: S:={[1,1],[1,2],[1,3],[2,2],[2,3],[2,5],[3,3],[3,5],[3,5],[3,6],[4,5],[4,6],[4,7],[5,5],[8,5],[8,6],[8,7],[8,8],[8,9],[9,5],[9,9],[9,6],[0,0],[0,1],[0,5],[8,0],[0,4],[4,0],[7,7],[7,8],[4,3],[4,4],[8,3],[0,1],[1,0],[6,6]}:

Sea Ct la clausura transitiva de S. Se verifica que:

a) Ct no es reflexiva

b) Ct es una relación de orden total

c) Ct no es una relación de orden

>    B:={1,2,3,4,5,6,7,8,9,0}; S:={[1,1],[1,2],[1,3],[2,2],[2,3],[2,5],[3,3],[3,5],[3,5],[3,6],[4,5],[4,6],[4,7],[5,5],[8,5],[8,6],[8,7],[8,8],[8,9],[9,5],[9,9],[9,6],[0,0],[0,1],[0,5],[8,0],[0,4],[4,0],[7,7],[7,8],[4,3],[4,4],[8,3],[0,1],[1,0],[6,6]};

B := {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

S := {[2, 2], [1, 1], [1, 0], [1, 2], [1, 3], [2, 3], [2, 5], [3, 3], [3, 5], [3, 6], [4, 5], [4, 6], [4, 7], [5, 5], [8, 5], [8, 6], [8, 7], [8, 8], [8, 9], [9, 5], [9, 9], [9, 6], [0, 0], [0, 1], [0,...
S := {[2, 2], [1, 1], [1, 0], [1, 2], [1, 3], [2, 3], [2, 5], [3, 3], [3, 5], [3, 6], [4, 5], [4, 6], [4, 7], [5, 5], [8, 5], [8, 6], [8, 7], [8, 8], [8, 9], [9, 5], [9, 9], [9, 6], [0, 0], [0, 1], [0,...

>   

>    MatrizRelacion:=proc(D::list,R::set([anything,anything]))
 local i,j,L;
 L:=[];
 for i from 1 to nops(D) do
   for j from 1 to nops(D) do
     if member([[op(D)][i],[op(D)][j]],R) then
       L:=[op(L),1] else L:=[op(L),0];
     fi;
   od;
 od;
 evalm(matrix(nops(D),nops(D),L));
end:

>    A:=MatrizRelacion([1,2,3,4,5,6,7,8,9,0],S);

A := matrix([[1, 1, 1, 0, 0, 0, 0, 0, 0, 1], [0, 1, 1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 1, 1, 1, 0, 0, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, ...

Se trata entonces de calcular la clausura transitiva. Lo hacemos mediante el algoritmo de Warshall:

>    Warshall:=proc(M::matrix)
  local i,j,k,W,n;
W:=matrix(rowdim(M),coldim(M),[seq(seq(M[i,j],j=1...coldim(M)),i=1..coldim(M))]):
  n:=coldim(M);
  for k from 1 to n do
   for i from 1 to n do
    for j from 1 to n do
     W[i,j]:=W[i,j]+(W[i,k]*W[k,j]);
    od;
   od;
  od;
 Matrizdeunosyceros(W);
end:

>    L:=Warshall(A);

L := matrix([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 1, 1, 0, 1, 1, 0, 0, 0, 0], [0, 0, 1, 0, 1, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0, ...

>    Mref(L);

>    Mantisim(L);

La respuesta correcta es la c).

>   

7.- Determinar si existen valores de a y b para que la relación que representa la siguiente matriz P sea reflexiva:

>    P:=matrix(5,5,[[1,1,a*b,a*b,a],[1,1,1,1,a^3],[a,1,1,a*b,a],[a*b,1,a*b,a,b],[a^2,a*b,a*b,b,1]]):

a) no hay  valores de a y b que la hagan reflexiva

b) es reflexiva para cualquier valor de a y b

c) hay  valores de a y b que la hagan reflexiva

>    P:=matrix(5,5,[[1,1,a*b,a*b,a],[1,1,1,1,a^3],[a,1,1,a*b,a],[a*b,1,a*b,a,b],[a^2,a*b,a*b,b,1]]);

P := matrix([[1, 1, a*b, a*b, a], [1, 1, 1, 1, a^3], [a, 1, 1, a*b, a], [a*b, 1, a*b, a, b], [a^2, a*b, a*b, b, 1]])

La respuesta correcta es la c).

>   

8.- Idem que 7 pero para la propiedad simétrica:

a) no hay  valores de a y b que la hagan simétrica

b) es simétrica para cualquier valor de a y b

c) existen valores de a y b que la hagan simétrica

Como la matriz

>    evalm(P-transpose(P));

matrix([[0, 0, a*b-a, 0, a-a^2], [0, 0, 0, 0, a^3-a*b], [a-a*b, 0, 0, 0, a-a*b], [0, 0, 0, 0, 0], [a^2-a, a*b-a^3, a*b-a, 0, 0]])

tiene todas las entradas nulas si    a*b-a  = 0,   a-a^2 = 0 y a^3-a*b  = 0,  los posibles valores son

a  =0 y b  = 0 ó 1  y

a  =1 y b  =1.

La respuesta correcta es la c).

>   

9.- Determinar si existen valores de a y b para que la relación que representa la  matriz P de los problemas 7 y 8 sea de equivalencia:

a) no hay  valores de a y b que la hagan de equivalencia

b) es de equivalencia para a=1 y b=0

c) es de equivalencia para a=1 y b=1

Como toda relación de equivalencia tiene que ser reflexiva, necesariamente tiene que ser a  =1. Si   a  =1,  por el problema 8 anterior, la relación es también simétrica si b  =1. Tenemos que verificar que para estos valores de a   y b   la relación es transitiva:

>    a:=1;b:=1;P:=matrix(5,5,[[1,1,a*b,a*b,a],[1,1,1,1,a^3],[a,1,1,a*b,a],[a*b,1,a*b,a,b],[a^2,a*b,a*b,b,1]]); Mtrans(P);

a := 1

b := 1

P := matrix([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]])

También

>    Matrizdeunosyceros:=proc(M::matrix)
  local i,j,Mat;
  Mat:=matrix(rowdim(M),coldim(M),0);
  for i from 1 to rowdim(M) do
   for j from 1 to coldim(M) do
    if(M[i,j]<>0) then Mat[i,j]:=1;
    fi;
   od;
  od;
RETURN(eval(Mat));
end:

>    evalm(Matrizdeunosyceros(evalm(P^2))-P);

matrix([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]])

La respuesta correcta es la c).

>   

>   

>    B:=matrix([[1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1]]):

>   

>    B:=matrix([[1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1]]);

B := matrix([[1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [1, 0, 0, 0, 1, 0, 0, 0], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 1, 1, 1], [0, 1,...

>    Mref:=proc(M::matrix)
local j,S,r:
S:=0:
for j from 1 to coldim(M)
do S:=S+M[j,j]: od:
if S=coldim(M) then r:="reflexiva": else r:="no reflexiva":
fi:
r; end:

>    Mref(B);

>    Msim:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M-transpose(M)):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 then S:=1: fi: od: od:
if S=1 then r:="no simetrica" else r:="simetrica" fi:
r; end:

>    Msim(B);

>    Mtrans:=proc(M::matrix)
local N,S,i,j,r:
N:=evalm(M^2):
S:=0:
for i from 1 to rowdim(M) while S=0 do
for j from 1 to rowdim(M) do
if N[i,j]<>0 and M[i,j]=0 then
S:=1: fi: od: od:
if S=1 then r:="no transitiva" else r:="transitiva":
fi:r; end:

>    Mtrans(B);

>   

La respuesta correcta es la a).

>    #fin

>