Seja K = (G, M, I) um contexto finito. O algoritmo Pr´oximos Vizinhos encontra o diagrama de B(K) pelo que chamaremos de n´ıveis. Definimos que o n´ıvel de um conceito (A, B) ´e o menor k tal que (A, B) = (A1, B1) ≺ (A2, B2) ≺ . . . ≺ (Ak, Bk) = (G, G′), para
conceitos (Ai, Bi) ∈ B(K), i = 1, 2, . . . , k. Isto ´e, o tamanho (em n´umero de v´ertices) do
menor caminho orientado de (A, B) a (G, G′) no diagrama de Hasse de B(K). Note que o
n´ıvel do conceito (G, G′), isto ´e, do elemento m´aximo de B(K), ´e um.
De importˆancia central para este algoritmo ´e a rotina que chamaremos de EncontraVi- zinhosDeBaixo. Esta rotina recebe um conceito (A, B) ∈ B(G, M, I) e encontra todos os conceitos que s˜ao cobertos por ele. A estrat´egia do algoritmo Pr´oximos Vizinhos ´e a seguinte:
1. O primeiro n´ıvel ´e trivialmente encontrado: {(G, G′)}.
2. Ap´os ser encontrado o i-´esimo n´ıvel,{(A1, B1), (A2, B2), . . . , (Ak, Bk)}, o n´ıvel de n´umero
i + 1 ´e encontrado ao aplicar-se a rotina EncontraVizinhosDeBaixo para cada elemento (Ai, Bi), com i = 1, . . . , k.
Vamos mostrar uma proposi¸c˜ao que descreve um conjunto de candidatos a cobrirem um conceito (A, B) ∈ B(G, M, I). Veremos que este conjunto de candidatos apresenta a boa propriedade de possuir O(|M|) elementos, e que este ser´a de grande utilidade para a rotina EncontraVizinhosDeBaixo, a ser descrita.
Proposi¸c˜ao 6.1. Sejam B(G, M, I) um reticulado de conceitos e (A, B) um de seus con- ceitos. Todos os conceitos cobertos por (A, B) possuem extens˜ao pertencente `a fam´ılia de subconjuntos
L = {(B ∪ {m})′ | m ∈ M \ B}.
Ademais, todo subconjunto em L ´e uma extens˜ao contida propriamente em A.
Prova. Seja (A, B) um conceito, e sejaL como no enunciado. Seja, ainda, (X, Y ) um conceito coberto por (A, B) e, portanto, Y ) B. Seja m ∈ Y \ B. Definimos W = B ∪ {m}. Note que B ( W ⊆ Y . Consideramos agora o par (W′, W′′). Pela Proposi¸c˜ao2.3, item iii’), temos que
(W′, W′′) ´e um conceito. Ademais, temos: W ) B ⇒ W′′ ⊇ B′′ = B e, como m ∈ W′′\ B,
temos, na realidade, a inclus˜ao estrita: W′′ ) B. Portanto, (W′, W′′) < (A, B). Por outro
lado, j´a que W ⊆ Y , tamb´em temos que W′′⊆ Y′′ = Y e, portanto (X, Y )≤ (W′, W′′). Em
suma, temos:
(X, Y )≤ (W′, W′′) < (A, B).
Como (X, Y ) ´e coberto por (A, B), a desigualdade (X, Y )≤ (W′, W′′) vale com igualdade e
portanto X = W′ = (B∪ {m})′ e, consequentemente, X pertence aL.
Para mostrarmos que todo subconjunto em L ´e uma extens˜ao contida propriamente em A, tomamos Z ∈ L, e portanto Z ´e da forma (B ∪ {m})′, para algum m ∈ M \ B. Pela
Proposi¸c˜ao2.3, item iii), e pela Proposi¸c˜ao2.2, item ii), segue que Z ´e uma extens˜ao. Usando o Lema 2.6, temos:
Z = (B∪ {m})′
= B′∩ {m}′ = A∩ {m}′.
Logo, Z ⊆ A. Como m /∈ B, segue que m /∈ A′, e portanto existe g ∈ A tal que g I m,
consequentemente {m}′ 6⊇ A e, assim, Z ( A.
A rec´ıproca da afirma¸c˜ao contida na Proposi¸c˜ao 6.1, no entanto, n˜ao vale: nem todo elemento da fam´ılia L presente no enunciado ´e uma extens˜ao cujo conceito associado ´e coberto por (A, B). Por exemplo, tomamos novamente o contexto dos vertebrados, e o conceito (A, B) = ({peixe papagaio, ´aguia, macaco, peixe lanterna}, {esqueleto}). Toma- mos tamb´em um elemento da fam´ılia L: X = (B ∪ {produz luz})′. A Figura 6.1(a) mostra
que (B∪{produz luz})′ ={peixe lanterna}, enquanto que a Figura6.1(b)mostra o conjunto
{peixe lanterna}′ = X′. No entanto, ´e mostrado na Figura 6.2 que o conceito (X, X′) n˜ao ´e
6.1. Algoritmo dos Pr´oximos Vizinhos 83 macaco possui mãos é vivíparo possui esqueleto respira na água vive na água possui bico voa peixe papagaio peixe lanterna
águia produz luz
(a) Deriva¸c˜ao de {possui esqueleto, pro- duz luz} macaco possui mãos é vivíparo possui esqueleto respira na água vive na água possui bico voa peixe papagaio peixe lanterna
águia produz luz
(b) Deriva¸c˜ao de{peixe lanterna}
Figura 6.1: Conceito do contra-exemplo para a rec´ıproca da Proposi¸c˜ao 6.1.
({peixe lanterna, peixe papagaio}, {esqueleto, r.n.a., v.n.a.})
(X,X') = ({peixe lanterna}, {esqueleto, r.n.a., v.n.a., produz luz})
(A,B) = ({peixe papagaio, águia, macaco, peixe lanterna}, {esqueleto})
Figura 6.2: Contra-exemplo para a rec´ıproca da Proposi¸c˜ao6.1.
A n˜ao validade da rec´ıproca significa que devemos submeterL a um processo que remova de L extens˜oes que n˜ao s˜ao de conceitos cobertos por (X, Y ). Na Proposi¸c˜ao 6.2, vamos mostrar que as extens˜oes pertencentes aL que devem ser removidas s˜ao exatamente as n˜ao maximais em L.
Proposi¸c˜ao 6.2. Sejam K = (G, M, I) um contexto e (A, B) ∈ B(G, M, I) um conceito qualquer. Seja L a fam´ılia de candidatos definida como na Proposi¸c˜ao 6.1. Seja (X, Y ) um conceito cuja extens˜ao pertence aL, isto ´e, X = (B ∪ {m})′, para algum m∈ M \ B. Ent˜ao,
o conceito (A, B) cobre (X, Y ) se e somente se X ´e maximal em L.
Prova. Vamos provar que, se X n˜ao ´e maximal em L, ent˜ao (A, B) n˜ao cobre (X, Y ). Su- ponha que X n˜ao seja maximal em L, e seja X1 ∈ L tal que X ( X1. Pela Proposi¸c˜ao 6.1,
temos que X1 ( A e que X1 ´e uma extens˜ao. Portanto, (X1, X1′) ´e um conceito. Al´em disso,
Para a rec´ıproca, vamos mostrar que se (A, B) n˜ao cobre (X, Y ), ent˜ao X n˜ao ´e maximal em L. Suponha, ent˜ao, que (A, B) n˜ao cobre (X, Y ), e tome (Z, W ) ∈ B(G, M, I) tal que (X, Y ) < (Z, W ) < (A, B). Como (Z, W ) < (A, B), segue imediatamente que W ) B. Logo, podemos tomar m ∈ W \ B. Definimos W1 = B∪ {m}. Note que W1′ ∈ L e que W1 ⊆ W .
Vale que:
W1 ⊆ W ⇒ W1′′⊆ W′′ = W ⇒ (Z, W ) ≤ (W1′, W1′′).
Como (X, Y ) < (Z, W ), temos, por transitividade, (X, Y ) < (W′
1, W1′′) ⇔ X ( W1′. Como
W′
1 ∈ L, temos que X n˜ao ´e maximal em L.
Seja (A, B) um conceito do qual desejamos listar todos os elementos que s˜ao cobertos por ele. As Proposi¸c˜oes 6.1 e 6.2 caracterizam as extens˜oes de conceitos cobertos por (A, B), e induzem um algoritmo simples para isto: basta construirmos a fam´ılia L, e depois descartar elementos n˜ao maximais para, finalmente, derivar cada um dos elementos restantes, obtendo o conjunto de conceitos cobertos por (A, B). No entanto, consideraremos um algoritmo ligeiramente diferente, e o chamaremos de EncontraVizinhosDeBaixo: construiremos um conjunto chamado candidatos que armazena todos os conceitos cujas extens˜oes pertencem a L, e depois da constru¸c˜ao deste conjunto, faremos o descarte de conceitos que possuem extens˜ao n˜ao maximal, dentre todas as extens˜oes de conceitos em candidatos. Tal processo est´a exposto no Algoritmo 4. A descri¸c˜ao da rotina ElementosMaximais, que realiza as remo¸c˜oes do conjunto candidatos, ´e trivial e n˜ao ser´a explicitada aqui.
EncontraVizinhosDeBaixo(A, B, G, M, I) 1 candidatos← ∅
2 para cada m∈ M \ B fa¸ca 3 A1 ← (B ∪ {m})′
4 B1 ← A′1
5 se (A1, B1) /∈ candidatos ent˜ao
6 candidatos← candidatos ∪ {(A1, B1)}
7 devolva ElementosM aximais(candidatos)
Algoritmo 4: Algoritmo EncontraVizinhosDeBaixo, para a determina¸c˜ao de conceitos cober- tos por um determinado conceito (A, B).
O algoritmo Pr´oximos Vizinhos, que se encontra descrito no Algoritmo 5, encontra o conjunto de conceitos B, bem como a lista de adjacˆencias de cada (A, B)∈ B. A estrat´egia do algoritmo ´e encontrar os conceitos por n´ıveis, do menor ao maior1. O n´ıvel mais alto
consiste em {(G, G′)}. A partir de um n´ıvel arbitr´ario, obtemos o pr´oximo n´ıvel aplicando
a fun¸c˜ao EncontraVizinhosDeBaixo para cada conceito do n´ıvel atual.
1
Expomos aqui o algoritmo conforme a apresenta¸c˜ao de Carpineto e Romano. A defini¸c˜ao deles de adjacˆencia no diagrama de Hasse ´e dual `a nossa: x ´e coberto por y se e s´o se existe arco (y, x). Esta estrat´egia de descoberta, “de cima para baixo”, resulta em adjacˆencias sim´etricas `as definidas por n´os na subse¸c˜ao2.5.1.
6.1. Algoritmo dos Pr´oximos Vizinhos 85 Pr´oximos Vizinhos(G, M, I)
1 B← {(G, G′)}
2 nivelAtual← {(G, G′)}
3 enquanto nivelAtual6= ∅ fa¸ca 4 proximoN ivel← ∅
5 para cada (A, B) ∈ nivelAtual fa¸ca
6 ⊲ Inicializa lista de adjacˆencias do conceito (A, B)
7 Adjacentes (A, B) ← ∅
8 vizinhosDeBaixo ← EncontraV izinhosDeBaixo(A, B, G, M, I) 9 para cada (A1, B1)∈ vizinhosDeBaixo fa¸ca
10 se (A1, B1) /∈ B ent˜ao ⊲ adiciona v´ertice a B
11 B← B ∪ {(A1, B1)}
12 proximoN ivel ← proximoNivel ∪ {(A1, B1)}
13 ⊲ adiciona arco de (A, B) para (A1, B1)
14 Adjacentes (A, B) ← Adjacentes (A, B) ∪ {(A1, B1)}
15 nivelAtual ← proximoNivel 16 devolva (B, Adjacentes)
Algoritmo 5: Pr´oximos Vizinhos
6.1.1
An´alise de complexidade
Analisaremos o tempo consumido pelo algoritmo Pr´oximos Vizinhos em duas etapas, analisando primeiramente a complexidade da subrotina EncontraVizinhosDeBaixo.
An´alise de EncontraVizinhosDeBaixo. Consideremos as linhas internas do la¸co, isto ´e, linhas de 3a 6. A linha 3pode ser executada em O(|G|), tirando proveito do fato de que Y′ = X ´e dado como entrada e (Y ∪{m})′ = Y′∩{m}′, pelo Lema2.6; ou seja, a linha3pode
ser implementada calculando a deriva¸c˜ao de um atributo e calculando a intersec¸c˜ao de dois subconjuntos de G (ambas opera¸c˜oes de complexidade O(|G|)). A linha 4 pode ser imple- mentada trivialmente com complexidade O(|G||M|). Se utilizarmos uma estrutura de lista para representar o conjunto candidatos, teremos tamanho m´aximo O(|M|) para tal lista. A linha5pode ser implementada comparando a extens˜ao X1 com a extens˜ao de cada elemento
da lista, (portanto O(|G|) por compara¸c˜ao), resultando numa complexidade de O(|G||M|) por vez que a linha 5 ´e executada. Utilizando uma lista para representar candidatos, cu- jos elementos s˜ao referˆencias para conceitos (A, B), podemos obter complexidade O(1) por execu¸c˜ao da linha 6. O la¸co de EncontraVizinhosDeBaixo itera O(|M|) vezes, resultando numa complexidade de O(|G||M|2) para a execu¸c˜ao completa do la¸co.
Resta-nos analisar a complexidade da fun¸c˜ao ElementosMaximais. Esta fun¸c˜ao realiza eventuais remo¸c˜oes na lista candidatos, o que motiva o uso de uma lista ligada, para obtermos complexidade de tempo O(1) por remo¸c˜ao de elemento. Ent˜ao a lista ligada candidatos ´e passada para a fun¸c˜ao ElementosMaximais e esta realiza um teste para cada par de elementos (Ai, Bi) e (Aj, Bj) tais que j > i, da seguinte maneira: se Ai ) Aj, ent˜ao (Aj, Bj) n˜ao ´e
coberto por (A, B) e, neste caso, (Aj, Bj) ´e removido da lista. Como este teste de compara¸c˜ao
Logo, a complexidade de tempo desta implementa¸c˜ao de ElementosM aximais ´e O(|G||M|2).
Conclu´ımos que a complexidade de tempo de EncontraVizinhosDeBaixo ´e O(|G||M|2).
An´alise de Pr´oximos Vizinhos. O la¸co da linha3itera exatamente o n´umero de n´ıveis do reticulado, enquanto o la¸co da linha 5 itera exatamente o n´umero de conceitos no n´ıvel atual. Ou seja, as linhas internas ao la¸co da linha5(isto ´e, linhas6a14) iteram exatamente uma vez por conceito do reticulado (|B| vezes).
Analisamos agora o consumo de tempo das linhas6a14. J´a vimos que a linha8consome tempo O(|G||M|2). As linhas internas ao la¸co da linha9, isto ´e, as linhas de10a14, executam
|vizinhosDeBaixo| = O(|M|) vezes. Se usarmos uma ´arvore de prefixos para representarmos as inten¸c˜oes de B e, em cada v´ertice da ´arvore de prefixos mantivermos uma referˆencia `a extens˜ao associada `aquela inten¸c˜ao, ent˜ao cada execu¸c˜ao da linha 10 consumir´a tempo O(|M|), conforme o Lema 5.3. Idem para a linha 11. Para a linha 12, proximoNivel pode ser implementado como uma lista ligada, o que significa complexidade O(1) por execu¸c˜ao. No momento da execu¸c˜ao da linha14, o conceito (A1, B1) certamente est´a em B e podemos
supor que temos o v´ertice da ´arvore de prefixos que representa B associado a (A1, B1)
(seja como subproduto da busca (linha 10), ou da adi¸c˜ao (linha 11)). Para adicionarmos o arco (A1, B1) → (A, B), simplesmente adicionamos uma referˆencia a (A1, B1) `a lista de
adjacˆencias Adjacentes((A,B)). Ent˜ao a linha 14consome O(1) unidades de tempo.
Em suma, a complexidade de tempo da linha8domina o tempo gasto pelas linhas6a14, que, durante todo o algoritmo, consomem tempo O(|B||M|2). O consumo total do algoritmo
Pr´oximos Vizinhos ´e portanto O(|B||G||M|2).