Algoritmos dos operadores StreamPref
Algoritmo 29 Ű InsertEndseq(L, s) Entrada: Lista L e sequência s
Atualização: Lista L
1: if s.inserted > 0 then //VeriĄca se s possui inserções 2: ns ← s[♣s♣ − s.inserted + 1, ♣s♣] //Obtém a sequência ns com as posições inseridas 3: forss ∈ L do //Para cada subsequência ss ∈ L 4: ss ← ss + ns //Concatena ss com ns 5: L ← L ∪ NewConseq(ns) //Adicionas as subsequências de ns em L
7.2.3 Análise de complexidade
A complexidade do algoritmo ingênuo NaiveSubseq é O(zn) para o operador
CONSEQ e O(zn2) para o operador ENDSEQ, onde z = ♣Z♣ é o número de sequências recebidas e n é o comprimento da maior sequência recebida. O custo do NaiveSubseq para o operador ENDSEQ é maior porque o algoritmo precisa processar uma sequência múltiplas vezes para obter todas as suas subsequências-up.
A complexidade do algoritmo IncConseq depende do custo das funções DeleteConseq, InsertConseq e NewConseq. As funções DeleteConseq e InsertConseq têm os custos O(d) e O(i), respectivamente, onde d é o maior número de remoções e i é o maior número de inserções. Já a função NewConseq tem o custo de O(i2). Desta maneira, a complexidade do algoritmo IncConseq é O(zd + zi + zi2). Como foi descrito no Capítulo 6, o operador
CONSEQ obtém subsequências a partir das sequências extraídas pelo operador SEQ.
Na prática, o número de inserções nunca é maior do que um porque a cada instante a operação de extração de sequências (operador SEQ) vai receber no máximo uma nova tupla. Isto faz com que a complexidade do algoritmo IncConseq seja reduzida para O(zd).
A complexidade do algoritmo IncEndseq está relacionada com o custo das funções DeleteEndseq, InsertEndseq e NewEndseq. Com a ordenação da lista L, o custo da função DeleteEndseq é O(d). A função InsertEndseq tem o custo de O(n − d) para atualizar as sequências existentes uma vez que o algoritmo DeleteConseq já removeu d das n subsequências existentes. Já a construção das novas subsequências pela função NewEndseq tem o custo de O(i2). Assim, o custo Ąnal da função InsertEndseq é de O(n − d + i2). Logo, a complexidade do algoritmo IncEndseq é O(z × (d + n − d + i2)) = O(zn + zi2). Considerando novamente que o número máximo de inserções é um, esta complexidade passa a ser O(zn).
7.3 Algoritmos dos operadores MINSEQ e MAXSEQ
O processamento dos operadores MINSEQ e MAXSEQ é feito conforme mostrado no algoritmo FilterByLength (Algoritmo 30). O algoritmo consiste em varrer todas as sequências recebidas e veriĄcar o comprimento das mesmas. As sequências que não possuem comprimento válido de acordo com os parâmetros α e β são descartadas. A implementação do algoritmo usa um atributo especial para armazenar o comprimento da sequência, evitando assim a varredura de todas as posições da sequência para obter seu comprimento. Portanto, a complexidade do algoritmo FilterByLength é O(z), onde z = ♣Z♣ é o número de sequências recebidas.Algoritmo 30 Ű F ilterByLength(Z)
1: Z′← ¶♢ //Cria o conjunto Z′ para armazenar as sequências a serem retornadas
2: for all s ∈ Z do //Para cada sequência s ∈ Z
3: if ♣s♣ é válido then //VeriĄca se s possui um comprimento válido 4: Z′ ← Z′∪ ¶s♢ //Adiciona s em Z′
5: return Z′ //Retorna as sequências com tamanho válido
7.4 Algoritmos
dos
operadores
BESTSEQ
e
TOPKSEQ
No processamento dos operadores de preferência BESTSEQ e TOPKSEQ, assim como no processamento dos operadores de subsequência, foram consideradas duas aborda- gens: ingênua e incremental. A Seção 7.4.1 descreve a algoritmo ingênuo. Em seguida, o algoritmo incremental é explicado na Seção 7.4.2. Depois, a Seção 7.4.3 apresenta a análise de complexidade dos algoritmos.
7.4.1 Algoritmo ingênuo
O processamento ingênuo do operador BESTSEQ é feita por meio do algoritmo GetBestSeq (Algoritmo 31). Primeiro, o algoritmo copia as sequências recebidas para o conjunto Z′. Em seguida, para cada par de sequências s e s′ de Z′, o algoritmo testa se
s ≻Φ s′ ou s′ ≻Φ s usando a função Dominates (Algoritmo 32). Ao Ąnal, as sequências dominadas são descartadas e somente aquelas que são dominantes permanecem em Z′. O Apêndice B apresenta um exemplo de execução completo do algoritmo GetBestSeq.
A função Dominates realiza o teste de dominância entre duas sequências s e s′ de acordo com uma teoria-pct Φ. Primeiro, o menor tamanho entre as duas sequências recebidas é calculado e armazenado em j. Em seguida, a função varre as posições de 1 a j das sequências em busca da primeira posição não correspondente. Quando a posição
7.4. Algoritmos dos operadores BESTSEQ e TOPKSEQ 139
Algoritmo 31 Ű GetBestSeq(Φ, Z)
Entrada: Conjunto de sequências Z e teoria-pct Φ Saída: Sequências dominantes de Z
1: Z′← Z //Copia as sequências recebidas para Z′
2: for all s, s′ ∈ Z′ do //Para cada par de sequências s, s′ em Z′
3: if Dominates(Φ, s, s′) then //Testa se s ≻Φs′
4: Z′← Z′− ¶s′♢ //Remove a sequência dominada s′ de Z′
5: else if Dominates(Φ, s′, s) then //Testa se s′≻
Φs
6: Z′← Z′− ¶s♢ //Remove a sequência dominada s de Z′
7: return Z′ //Retorna somente as sequências dominantes
não corresponde i é encontrada, todas as regras-pct de Φ válidas em s[i] e s′[i] são usadas para criar a teoria-pc Γ.
A obtenção de uma regra-pc a partir de uma regra-pct φ consiste em remover os componentes temporais de φ conforme explicado no Capítulo 5. A teoria-pc Γ construída é usada então para comparar as tuplas s[i] e s′[i] usando o algoritmo SearchDom (Algoritmo 1). O algoritmo SearchDom, apresentado no Capítulo 3, usa a técnica de busca em profundidade para comparar duas tuplas de acordo com uma teoria-pc. Desta maneira, o resultado da comparação das sequências s e s′ é o resultado da comparação das tuplas
s[i] e s′[i]. O algoritmo Dominates retorna false, quando a posição de comparação não é encontrada.
Algoritmo 32 Ű Dominates(Φ, s, s′)
Entrada: Teoria-pct Φ e duas sequências s e s′ Saída: true, se s domina s′. Caso contrário, false
1: j ← min¶♣s♣, ♣s′♣♢ //Obtém o tamanho j da menor sequência 2: for all i ∈ ¶1, ..., j♢ do //Percorre as posições de 1 a j das sequências 3: if s[i] ̸= s′[i] then //Testa se posição atual é diferente nas sequências 4: Γ ← ¶♢ //Cria uma teoria-pc Γ vazia
5: for all φ ∈ Φ do //Para cada regra-pct φ de Φ
6: if ((s, i) ♣= Cφ) and ((s′, i) ♣= Cφ) then //Testa se a posição i de s e s′ satisfaz Cϕ
7: Γ ← Γ ∪ ¶φ•♢ //Adiciona a regra-pc φ•em Γ
8: return SearchDom(Γ, s[i], s′[i]) //Testa se s[i] ≻
Γ s′[i]
9: return false
O algoritmo GetTopkSeq (Algoritmo 33) realiza a processamento ingênua do ope- rador TOPKSEQ. Inicialmente, todas as sequências são movidas para o conjunto Z+. A cada iteração do laço de repetição, as sequências são separadas em dominantes (Z+) e dominadas (Z−) por meio da função SeparateSequences (Algoritmo 34). As sequências dominantes são inseridas no Ąnal da lista L e as sequências dominadas são movidas para Z+ para que possam ser separadas novamente na próxima iteração.
A lista L armazena as sequências ordenadas de forma crescente pelo nível de preferência. Na primeira iteração, as sequências com nível zero são acrescentadas a lista, na segunda iteração, são acrescentadas as sequências com nível um e assim por diante.
Algoritmo 33 Ű GetTopkSeq(Φ, Z, k)
Entrada: Conjunto de sequências Z, teoria-pct Φ e inteiro k Saída: Top-k sequências de Z
1: Z+← Z //Copia as sequências recebidas para Z+
2: Z−← ¶♢ //Conjunto para armazenar as sequências dominadas
3: L ← NewList() //Lista para guardar as sequências ordenadas pelo nível 4: while (♣L♣ < k) and (♣Z+♣ > 0) do //Enquanto ♣L♣ < k e ♣Z+♣ > 0
5: Z+, Z−← SeparateSequences(Z+, Φ) //Separa Z+ em dominantes e dominadas
6: L.append(Z+) //Acrescenta as sequências dominantes à lista L
7: Z+← Z− //Move as sequências dominadas de Z− para Z+
8: return L.getFirst(k) //Retorna as primeiras k sequências de L
As iterações do laço terminam quando L possui, no mínimo, k sequências ou todas as sequências recebidas já se encontram em L. No Ąnal, o algoritmo retorna as primeiras k sequências de L.
A função SeparateSequences recebe os mesmos parâmetros e trabalha de forma semelhante ao algoritmo GetBestSeq. A diferença é que a função SeparateSequences retorna dois conjuntos disjuntos, um contendo as sequências dominantes e outro contendo as sequências dominadas.
Algoritmo 34 Ű SeparateSequences(Φ, Z) Entrada: Conjunto de sequências Z e teoria-pct Φ Saída: Sequências dominantes e dominadas de Z
1: Z+← Z //Copia as sequências recebidas para Z+
2: Z−← ¶♢ //Conjunto para armazenar as sequências dominadas
3: for all s, s′ ∈ Z+ do //Para cada par de sequências s, s′ em Z+
4: if Dominates(Φ, s, s′) then //Testa se s ≻
Φs′
5: Z+← Z+− ¶s′♢ //Remove a sequência dominada s′ de Z+
6: Z−← Z−∪ ¶s′♢ //Adiciona sequência dominada s′ em Z−
7: else if Dominates(Φ, s′, s) then //Testa se s′≻
Φs
8: Z+← Z+− ¶s♢ //Remove a sequência dominada s de Z+
9: Z−← Z−∪ ¶s♢ //Adiciona sequência dominada s′ em Z−
10: return Z+, Z− //Retorna sequências dominantes e dominadas
7.4.2 Algoritmo incremental
O processamento ingênuo dos operadores de preferência não usa qualquer informação do instante anterior. Isto pode causar a repetição desnecessária de testes de dominância. Por exemplo, em um instante, existem duas sequências s e s′ tais que s ≻
Φ s′. Se, no instante seguinte, estas sequências não sofrerem qualquer alteração, a comparação já realizada prevalece a mesma. Os algoritmos incrementais foram criados para reduzir este tipo de problema.
O processamento incremental dos operadores de preferência utiliza uma estrutura de índice baseada em árvore chamada de árvore de sequências. Esta estrutura permite saber
7.4. Algoritmos dos operadores BESTSEQ e TOPKSEQ 141 onde duas sequências devem ser comparadas e também mantém hierarquias de preferências para as tuplas das sequências nas posições onde devem acontecer as comparações. A árvore de sequências possui uma raiz na profundidade zero. Começando na profundidade um, os nós da árvore passam a ser associados às tuplas das sequências. Seja s = ⟨t1, ..., tz⟩. Cada tupla ti de s é representada por um nó. A primeira tupla (t1) se torna um nó Ąlho da raiz. A partir de então, todo nó ti é pai do nó ti+1. A sequência s Ąca armazenada no último nó tn. O Exemplo 27 mostra como armazenar sequências em uma árvore de sequências.