La clase relacion

Para utilizar la clase, primero importamos el fichero que la contiene


In [1]:
from relaciones import *

Para definir una relación, podemos o bien dar un conjunto de parejas, o bien un conjunto de parejas y el universo donde están los elementos de los pares. En caso de no proporcionar el universo, se tomará como universo el conjunto de todos los valores que aparecen en las parejas.

Por ejemplo, definamos en el conjunto $\{0,1,\ldots,11\}$ la relación de ser congruentes módulo 5


In [2]:
u =set(range(12))
rl = set((a,b) for a in u for b in u if (a-b)%5 ==0)

In [3]:
r =relacion(rl,u)

Sabemos que esta relación es de equivalencia


In [4]:
r.es_equivalencia()


Out[4]:
True

Y podemos calcular sus clases de equivalencia (hemos congelado las clases para poder crear un conjunto de conjuntos)


In [5]:
r.clases_equivalencia()


Out[5]:
{frozenset({1, 6, 11}),
 frozenset({4, 9}),
 frozenset({3, 8}),
 frozenset({2, 7}),
 frozenset({0, 5, 10})}

El universo es un atributo de la clase, y se puede acceder a él de la siguiente forma


In [6]:
r.universo


Out[6]:
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

También podemos determinar si dos elementos están relacionados, bien usando el método rel o llamando a la relación con los dos elementos


In [7]:
r.rel(1,1)


Out[7]:
True

In [8]:
r(1,6)


Out[8]:
True

In [9]:
(1,1) in r.rels


Out[9]:
True

Si dibujamos las relaciones entre los elementos, aparecerán claramente las clases de equivalencia


In [10]:
r.pinta()


%3 0 0 0->0 5 5 0->5 10 10 0->10 1 1 1->1 6 6 1->6 11 11 1->11 2 2 2->2 7 7 2->7 3 3 3->3 8 8 3->8 4 4 4->4 9 9 4->9 5->0 5->5 5->10 6->1 6->6 6->11 7->2 7->7 8->3 8->8 9->4 9->9 10->0 10->5 10->10 11->1 11->6 11->11
Out[10]:
'Digraph.gv.svg'

Esta relación no es de orden


In [11]:
r.es_orden()


Out[11]:
False

Pues no es antisimétrica


In [12]:
r.es_antisimetrica()


Out[12]:
False

 Diagramas de Hasse

Veamos ahora como ejemplo el conjunto de los divisores de 12 con la relación de divisibilidad


In [13]:
d = set(a for a in range(1,13) if 12%a ==0)

In [14]:
rd =relacion(set((a,b) for a in d for b in d if b%a ==0))

Podemos dibujar el diagrama de Hasse como sigue


In [15]:
rd.hasse()


%3 1 1 2 2 2--1 3 3 3--1 4 4 4--2 6 6 6--2 6--3 12 12 12--4 12--6
Out[15]:
Relación binaria

O bien pintar todas las relaciones


In [16]:
rd.pinta()


%3 1 1 1->1 2 2 1->2 3 3 1->3 4 4 1->4 6 6 1->6 12 12 1->12 2->2 2->4 2->6 2->12 3->3 3->6 3->12 4->4 4->12 6->6 6->12 12->12
Out[16]:
'Digraph.gv.svg'

Claramente esta relación es de orden, y no es un orden total


In [17]:
rd.es_orden()


Out[17]:
True

In [18]:
rd.es_orden_total()


Out[18]:
False

Los elementos notables se calculan con los métodos que tienen nombres acordes a ellos


In [19]:
rd.maximales(set({2,3,6}))


Out[19]:
{6}

In [20]:
rd.maximales(set({2,3}))


Out[20]:
{2, 3}

O incluso podemos destacar esos elementos en el dibujo de relaciones


In [21]:
rd.pinta(rd.mayorantes(set({2,3})))


%3 12 12 12->12 6 6 6->12 6->6 1 1 1->12 1->6 1->1 2 2 1->2 3 3 1->3 4 4 1->4 2->12 2->6 2->2 2->4 3->12 3->6 3->3 4->12 4->4
Out[21]:
'Digraph.gv.svg'

In [22]:
rd.minimales(set({2,3}))


Out[22]:
{2, 3}

In [23]:
rd.minimo(set({2,4}))


Out[23]:
2

 Retículos

Continuamos con los divisores de 12


In [24]:
rd.es_reticulo_inferior()


Out[24]:
True

In [25]:
rd.es_reticulo_superior()


Out[25]:
True

In [26]:
rd.complemento(4)


Out[26]:
3

In [27]:
rd.cero


Out[27]:
1

In [28]:
rd.uno


Out[28]:
12

In [29]:
rd.es_complementado()


Out[29]:
False

Veamos qué elementos no tienen complemento


In [30]:
[a for a in rd.universo if rd.complemento(a)==None]


Out[30]:
[2, 6]

Ahora damos un ejemplo que sí es complementado, de hecho un álgebra de Boole


In [31]:
u = set(a for a in range(1,31) if 30%a==0)

In [32]:
u


Out[32]:
{1, 2, 3, 5, 6, 10, 15, 30}

In [33]:
p = set((a,b) for a in u for b in u if b%a ==0)

In [34]:
r = relacion(p)

In [35]:
r.es_distributivo()


Out[35]:
True

In [36]:
r.atomos()


Out[36]:
{2, 3, 5}

In [37]:
r.es_algebra_Boole()


Out[37]:
True

In [38]:
r.pinta(r.atomos())


%3 2 2 2->2 10 10 2->10 30 30 2->30 6 6 2->6 3 3 3->3 3->30 3->6 15 15 3->15 5 5 5->5 5->10 5->30 5->15 1 1 1->2 1->3 1->5 1->1 1->10 1->30 1->6 1->15 10->10 10->30 30->30 6->30 6->6 15->30 15->15
Out[38]:
'Digraph.gv.svg'

Retículos de divisores

Podemos definir retículos con los divisores de un entero o bien dar un conjunto ordenado por la relación de divisibilidad. Para ellos utilizaremos divisores


In [39]:
r = divisores(24)

In [40]:
r.hasse()


%3 1 1 2 2 2--1 3 3 3--1 4 4 4--2 6 6 6--2 6--3 8 8 8--4 12 12 12--4 12--6 24 24 24--8 24--12
Out[40]:
Relación binaria

In [41]:
_.rels


Out[41]:
{(1, 2),
 (1, 3),
 (2, 4),
 (2, 6),
 (3, 6),
 (4, 8),
 (4, 12),
 (6, 12),
 (8, 24),
 (12, 24)}

El diamante


In [42]:
r = divisores({0,1,2,3,5})

In [43]:
r.pinta()


%3 0 0 0->0 1 1 1->0 1->1 2 2 1->2 3 3 1->3 5 5 1->5 2->0 2->2 3->0 3->3 5->0 5->5
Out[43]:
'Digraph.gv.svg'

In [44]:
r.hasse()


%3 0 0 2 2 0--2 3 3 0--3 5 5 0--5 1 1 2--1 3--1 5--1
Out[44]:
Relación binaria

In [45]:
r.es_orden()


Out[45]:
True

In [46]:
r.es_orden_total()


Out[46]:
False

In [47]:
r.es_reticulo()


Out[47]:
True

In [48]:
r.es_subreticulo({0,1,2,3})


Out[48]:
True

In [49]:
r.es_distributivo()


Out[49]:
False

In [50]:
r.es_complementado()


Out[50]:
True

 El pentágono


In [51]:
r = divisores({1,0,2,4,3})

In [52]:
r.hasse()


%3 0 0 3 3 0--3 4 4 0--4 1 1 2 2 2--1 3--1 4--2
Out[52]:
Relación binaria

In [53]:
r.es_distributivo()


Out[53]:
False

In [54]:
r.es_complementado()


Out[54]:
True

Otros ejemplos

Retículo que no es distributivo ni complementado


In [55]:
r=divisores({1,0,2,18,9,3})

In [56]:
r.hasse()


%3 0 0 18 18 0--18 1 1 2 2 2--1 18--2 9 9 18--9 3 3 3--1 9--3
Out[56]:
Relación binaria

In [57]:
r.es_complementado()


Out[57]:
False

In [58]:
r.es_distributivo()


Out[58]:
False

In [59]:
[s for s in r.universo if r.complemento(s)==None]


Out[59]:
[2, 18, 3, 9]

In [60]:
r.es_reticulo()


Out[60]:
True

Retículo distributivo, no complementado


In [61]:
r = divisores({1,2,4})

In [62]:
r.hasse()


%3 1 1 2 2 2--1 4 4 4--2
Out[62]:
Relación binaria

In [63]:
r.es_distributivo()


Out[63]:
True

In [64]:
r.es_complementado()


Out[64]:
False

In [65]:
r=divisores({0,1,2,3,4,6})

In [66]:
r.hasse()


%3 0 0 4 4 0--4 6 6 0--6 1 1 2 2 2--1 3 3 3--1 4--2 6--2 6--3
Out[66]:
Relación binaria

In [67]:
r.es_distributivo()


Out[67]:
True

In [68]:
r.es_complementado()


Out[68]:
False