emprego de gramáticas livres de contexto para a construção de um ...

121
EMPREGO DE GRAM ´ ATICAS LIVRES DE CONTEXTO PARA A CONSTRUC ¸ ˜ AO DE UM ALGORITMO CRIPTOGR ´ AFICO Jo˜ao Felipe Pontes Faria Projeto de Gradua¸c˜ao apresentado ao Curso de Engenharia Eletrˆonica e de Computa¸c˜ ao da Escola Polit´ ecnica, Universidade Federal do Rio de Janeiro, como parte dos requisitos necess´arios`aobten¸c˜aodot´ ıtulo de Enge- nheiro. Orientador: Fl´avio Luis de Mello Rio de Janeiro Abril de 2016

Transcript of emprego de gramáticas livres de contexto para a construção de um ...

Page 1: emprego de gramáticas livres de contexto para a construção de um ...

EMPREGO DE GRAMATICAS LIVRES DE CONTEXTO PARA

A CONSTRUCAO DE UM ALGORITMO CRIPTOGRAFICO

Joao Felipe Pontes Faria

Projeto de Graduacao apresentado ao Curso

de Engenharia Eletronica e de Computacao

da Escola Politecnica, Universidade Federal

do Rio de Janeiro, como parte dos requisitos

necessarios a obtencao do tıtulo de Enge-

nheiro.

Orientador: Flavio Luis de Mello

Rio de Janeiro

Abril de 2016

Page 2: emprego de gramáticas livres de contexto para a construção de um ...
Page 3: emprego de gramáticas livres de contexto para a construção de um ...

UNIVERSIDADE FEDERAL DO RIO DE JANEIRO

Escola Politecnica - Departamento de Eletronica e de Computacao

Centro de Tecnologia, bloco H, sala H-217, Cidade Universitaria

Rio de Janeiro - RJ CEP 21949-900

Este exemplar e de propriedade da Universidade Federal do Rio de Janeiro, que

podera incluı-lo em base de dados, armazenar em computador, microfilmar ou adotar

qualquer forma de arquivamento.

E permitida a mencao, reproducao parcial ou integral e a transmissao entre bibli-

otecas deste trabalho, sem modificacao de seu texto, em qualquer meio que esteja

ou venha a ser fixado, para pesquisa academica, comentarios e citacoes, desde que

sem finalidade comercial e que seja feita a referencia bibliografica completa.

Os conceitos expressos neste trabalho sao de responsabilidade do(s) autor(es).

iii

Page 4: emprego de gramáticas livres de contexto para a construção de um ...

DEDICATORIA

A todos os gigantes, celebres ou anonimos, que humildemente oferecem seus om-

bros aos aprendizes.

iv

Page 5: emprego de gramáticas livres de contexto para a construção de um ...

AGRADECIMENTO

Agradeco primeiramente ao povo brasileiro que contribuiu de forma significativa

a minha formacao e estada nesta Universidade. Este projeto e uma pequena forma

de retribuir o investimento e confianca em mim depositados.

Gostaria tambem de agradecer a Daniela, minha amada e minha musa, que me

apoiou e motivou na realizacao deste trabalho e na conclusao desta etapa academica;

meus pais Nelson e Andrea que tambem sempre estiveram ao meu lado e me apoiando

em minhas escolhas e conquistas; meus avos Rita e Ismael que sempre me incenti-

varam em todos os meus desafios; minha avo Nathalia que sempre me apoiou; meus

irmaos, todos os meus tios, primos e agregados, que sempre me proporcionaram

um ambiente familiar acolhedor, estimulante e incentivador, especialmente a Titita,

entre outros tantos que nao haveria espaco para citar um a um.

Meu muito obrigado ao professor Flavio Mello, que me apresentou este assunto

interessantıssimo e aceitou me orientar neste projeto, apesar do pouco tempo de que

eu dispunha para me dedicar a ele, e sempre me tratou com total atencao e respeito;

a todos os demais professores e orientadores (Case, Seixas, Mauros, Augusto, Jomar,

Henrik, Jose, Robert e muitos mais!), assim como os meus colegas, funcionarios e

amigos da UFRJ e da KTH, com quem estudei e trabalhei dentro ou fora de sala

de aula e que trouxeram, cada um, informacoes e experiencias fundamentais para a

minha formacao.

Sou grato tambem aos meus amigos, colegas e professores, do CAp-UFRJ que me

proporcionaram uma preparacao para os desafios academicos e de vida, especial-

mente ao Beto, cujos ensinamentos vao muito alem da Fısica.

v

Page 6: emprego de gramáticas livres de contexto para a construção de um ...

RESUMO

Um algoritmo criptografico e construıdo empregando gramaticas livres de contexto

tal que a representacao criptografica dos dados seja uma gramatica que os representa.

Para dificultar o acesso indevido aos dados, trechos da gramatica codificada contendo

sımbolos terminais sao substituıdos por sımbolos fictıcios que nao fazem parte da

gramatica, e estes trechos substituıdos formam a chave criptografica do algoritmo.

Para descriptografar os dados, a chave e utilizada para reconstruir a gramatica que,

em seguida, e utilizada para gerar os dados originais.

Alem de criptografar os dados, o algoritmo proposto alcanca simultaneamente a

sua compressao, pois a abordagem utilizada em sua construcao e baseada no fato

de que gramaticas podem ser vistas como representacoes compactas dos dados que

elas geram, caracterıstica esta explorada por algoritmos de compressao de dados

tomados como ponto de partida neste estudo.

Uma avaliacao empırica mostra que, em media, a saıda do algoritmo criptografico

proposto e aprovada em 95 dentre 162 testes aplicados na bateria de testes es-

tatısticos para aplicacoes criptograficas do NIST.

Palavras-Chave: gramaticas livres de contexto, criptografia, teoria da informacao.

vi

Page 7: emprego de gramáticas livres de contexto para a construção de um ...

ABSTRACT

A cryptographic algorithm is built employing context-free grammars such that

the cryptographic representation of the data is a grammar that represents it. To

make it hard to access the data without proper authorisation, segments of the coded

grammar containing terminal symbols are substituted by dummy symbols that are

not part of the grammar, and these substituted segments are used as the crypto-

graphic key of the algorithm. To decrypt the data, the key is used to reconstruct

the grammar so that it can be used to generate the original data.

Beyond encrypting the data, the proposed algorithm achieves simultaneously its

compression, as the approach used in its construction is based on the fact that gram-

mars can be seen as compact representations of the data it generates, a characteristic

exploited by compression algorithms used as a starting point for this study.

An empirical evaluation shows that, on average, the output of the proposed cryp-

tographic algorithm passes 95 out of 162 tests from NIST’s statistical test suite for

cryptography applications.

Key-words: context-free grammars, cryptography, information theory.

vii

Page 8: emprego de gramáticas livres de contexto para a construção de um ...

SIGLAS

DAG - Direct acyclic graph

DSA - Digital Signature Algorithm

E/S - Entrada/saıda

FPGA - Field-programmable gate array

HEVC - High-Efficiency Video Coding

IED - Interactive Encoding and Decoding

LCA - Lowest common ancestor

LZ - Lempel-Ziv

LZMA - Lempel-Ziv-Markov chain algorithm

LZW - Lempel-Ziv-Welch

NIST - National Institute of Standards and Technology

NP - Non-deterministic polynomial

PPM - Prediction by partial matching

RGB - Red, green, and blue

RSA - Rivest-Shamir-Adleman

SLT - Static lookup table

STS - Statistical Test Suite

viii

Page 9: emprego de gramáticas livres de contexto para a construção de um ...

XML - Extensible Markup Language

ix

Page 10: emprego de gramáticas livres de contexto para a construção de um ...

Sumario

1 Introducao 1

1.1 Tema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Delimitacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3 Justificativa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.4 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.5 Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.6 Descricao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Gramaticas e Criptografia 6

2.1 Esteganografia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.2 Autenticacao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3 Gramaticas e Compressao 11

3.1 Gramaticas admissıveis . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.2 Transformadas de gramatica . . . . . . . . . . . . . . . . . . . . . . . 16

3.2.1 Transformada gulosa . . . . . . . . . . . . . . . . . . . . . . . 23

3.2.2 Transformada condicional de casamento de padroes multinıvel 26

3.3 Trabalhos posteriores . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3.3.1 Indiretamente ligados aos codigos baseados em gramaticas . . 30

3.3.2 Codigos baseados em gramaticas e suas aplicacoes diretas . . . 33

4 Um novo algoritmo criptografico 50

4.1 Sımbolo de partida . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

4.2 Regras de Producao . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

4.3 Sımbolos terminais . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

4.4 Avaliacao empırica do algoritmo proposto . . . . . . . . . . . . . . . 55

x

Page 11: emprego de gramáticas livres de contexto para a construção de um ...

5 Conclusoes 62

5.1 Consideracoes finais . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

5.2 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

Bibliografia 65

A Implementacao do algoritmo Crypto LCA 71

A.1 bits.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

A.2 bits.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

A.3 cfg2enc.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

A.4 cfg2enc.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

A.5 cfg2txt.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

A.6 enc2txt.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

A.7 enc2txt.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

A.8 lcacommon.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

A.9 lcacomp.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

A.10 lcacrypt.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

A.11 txt2cfg online.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

A.12 txt2cfg online.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

xi

Page 12: emprego de gramáticas livres de contexto para a construção de um ...

Lista de Figuras

4.1 Exemplo de arvore parcial de derivacao de uma gramatica . . . . . . 53

xii

Page 13: emprego de gramáticas livres de contexto para a construção de um ...

Lista de Tabelas

4.1 Testes estatısticos nos arquivos originais do corpus Pizza&Chili . . . 59

4.2 Testes estatısticos nos arquivos comprimidos pelo Online LCA . . . . 60

4.3 Testes estatısticos nos arquivos criptografados pelo Crypto LCA . . . 60

4.4 Testes estatısticos nas chaves criptograficas geradas pelo Crypto LCA 61

xiii

Page 14: emprego de gramáticas livres de contexto para a construção de um ...

Capıtulo 1

Introducao

1.1 Tema

A teoria da informacao e um campo do conhecimento interdisciplinar e de interesse

no ambito da engenharia eletronica, ciencia da computacao, telecomunicacoes, ma-

tematica aplicada, entre outros. Desde o inıcio da formalizacao das ideias centrais

deste campo de estudo com o trabalho seminal de Claude Shannon[1], os concei-

tos de quantidade de informacao, entropia e redundancia se mostraram poderosas

ferramentas no projeto e analise de todo tipo de sistema que tenha em seu cerne

a producao, transmissao ou consumo de dados (informacao), mesmo tomados em

sentido amplo.

Se pensarmos na modelagem de Shannon para os sistemas de comunicacao vere-

mos que partes fundamentais sao o transmissor e o receptor que, respectivamente,

codificam e decodificam a informacao em sinais transmitidos. A codificacao pode ser

projetada com (e analisada em relacao a) diversos objetivos e, enquanto Shannon

se debrucava sobre a transmissao eficiente da informacao por meio de sinais em um

canal, uma outra aplicacao da codificacao se encontra na area da criptografia. Nesta

ultima o foco nao e a eficiencia da transmissao mas sim a sua seguranca – busca-se

sinais que transmitam a informacao sem que terceiros possam compreende-la e nem

comprometer a sua integridade.

E interessante tambem notar que Shannon, no mesmo artigo, ao definir fontes de

informacao toma como exemplo a lıngua inglesa e mostra uma serie de aproximacoes

1

Page 15: emprego de gramáticas livres de contexto para a construção de um ...

que a modelam[1, Parte 1, Secao 3], e pode-se fazer aqui a ponte a uma subarea da

teoria da informacao e da matematica –e tambem da linguıstica– que nos interessa:

o estudo das gramaticas livres de contexto. Gramaticas gerativas, entre as quais

as chamadas livres de contexto, passam a ser o foco de profundo estudo e amplas

aplicacoes a partir de outro trabalho seminal, este do linguista Noam Chomsky, que

busca modelar a estrutura da producao de sentencas na gramatica da lıngua inglesa

para gerar frases validas e ganhar um melhor entendimento sobre as gramaticas que

regem os idiomas[2].

Busca-se no presente trabalho investigar e experimentar o uso de gramaticas livres

de contexto na codificacao para criptografia.

1.2 Delimitacao

Na atualidade, comunicacoes e arquivos eletronicos sao extensivamente utilizados

em diversas aplicacoes que requerem seguranca e privacidade de dados, tais como

mensagens, aplicacoes bancarias e governamentais, entre outras, muitas das quais

implementadas em dispositivos moveis, sistemas embarcados e distribuıdos que tem

recursos restritos, e tambem em servidores de aplicacao centralizados que, apesar

de disporem de mais recursos, precisam responder a um alto numero de requisicoes

simultaneas.

Tais situacoes tornam imperativo o uso de algoritmos criptograficos simples e que

demandem poucos recursos computacionais e de memoria, e neste contexto se insere

a investigacao de algoritmos criptograficos obtidos a partir de codigos baseados em

gramaticas, originalmente desenvolvidos para compressao de dados e frequentemente

de implementados de maneira simples e com uso eficiente de recursos.

Adicionalmente, deseja-se que a saıda do algoritmo criptografico construıdo com

esta abordagem passe nos testes estatısticos para aplicacoes em criptografia do NIST

(National Institute of Standards and Technology).

2

Page 16: emprego de gramáticas livres de contexto para a construção de um ...

1.3 Justificativa

A despeito da formalizacao do estudo das gramaticas livres de contexto no ambito

da teoria da informacao ter se iniciado nem uma decada apos a formalizacao desta

teoria, a area de codigos baseados em gramaticas e relativamente recente e foi for-

malizada do ponto de vista da compressao de dados por Yang e Kieffer praticamente

meio seculo depois[3].

As intencoes da compressao e da criptografia podem ser vistas, de certo modo,

como relacionadas. Algoritmos de compressao sem perdas buscam eliminar re-

dundancias e aproximar a taxa de bits da sequencia de saıda a taxa de entropia

da sequencia de entrada, ou seja, busca-se uma sequencia de saıda que se aproxime

de uma sequencia aleatoria do ponto de vista da teoria da informacao que conte-

nha toda a informacao da sequencia de entrada porem que seja mais curta que a

mesma –e este ponto fica absolutamente claro quando se observa que uma sequencia

aleatoria e incompressıvel por um algoritmo sem perdas. Algoritmos de criptogra-

fia, por sua vez, tambem buscam gerar uma sequencia de saıda que se aproxime de

uma sequencia aleatoria. O objetivo na criptografia nao e, contudo, representar a

informacao da sequencia de entrada com uma outra sequencia mais curta, mas sim

mascarar as correlacoes de modo a ocultar a informacao tal que somente da posse

de uma chave ou segredo alguem seja capaz de reconstruir a sequencia de entrada a

partir da sequencia de saıda.

Como se ve, uma das principais caracterısticas desejadas nas sequencias de saıda

tanto de algoritmos de compressao quanto de criptografia e a mesma, e daı pode-se

intuir que tecnicas de compressao podem ser adaptadas para o uso criptografico

e vice-versa. A ideia de se utilizar gramaticas livres de contexto no ambito da

criptografia ja foi levantada em aplicacoes de esteganografia[4, 5] e de producao de

tokens para autenticacao (numeros de cartao de credito descartaveis)[6].

As aplicacoes em esteganografia sao mais simples e diretas, e consistem na geracao

de textos gramaticais em que bits ou sequencias sao associados a cada uma das pos-

sibilidades distintas de escolha de palavras ou sintagmas terminais na geracao do

texto de modo que um subconjunto da linguagem gerada pela gramatica codifica

3

Page 17: emprego de gramáticas livres de contexto para a construção de um ...

inequivocamente a sequencia de entrada em um texto gramaticalmente correto que

nao levante suspeitas. Ja na producao de numeros de cartao de credito descartaveis

(isto e, tokens de autenticacao para transacoes on-line) baseada em gramaticas li-

vres de contexto as regras das gramaticas sao parte do segredo compartilhado pelo

emissor e pelo titular do cartao, enquanto os tokens trocados sao derivados das lin-

guagens da gramatica. Essa abordagem se apoia na dificuldade de se reconstruir

uma gramatica a partir de exemplos de sequencias da linguagem gerada por ela.

Nas duas abordagens exemplificadas as gramaticas sao mantidas secretas e o que

se envia sao partes das linguagens geradas, em contraste com a abordagem da com-

pressao sem perdas baseada em gramaticas em que se constroi uma gramatica cuja

linguagem unitaria e a sequencia de entrada e cuja taxa de bits se aproxima da taxa

de entropia da sequencia de entrada, se aproximando tambem de uma sequencia

aleatoria. Nao ha, tanto quanto e do nosso conhecimento, aplicacoes de criptografia

utilizando gramaticas livres de contexto com uma abordagem similar a adotada nos

codigos de compressao sem perdas baseados em gramaticas e, dadas as ja aponta-

das similaridades entre os objetivos da criptografia e da compressao, ha razoes para

crer que a investigacao do uso de tal abordagem em criptografia pode resultar em

tecnicas simples, inovadoras e seguras.

1.4 Objetivos

Os principais objetivos perseguidos no desenvolvimento deste trabalho sao (i)

identificar de um algoritmo de compressao implementando um codigo baseado em

gramaticas que seja um bom candidato a ser utilizado como base para a obtencao de

um algoritmo criptografico simples e eficiente; (ii) propor e desenvolver um algoritmo

criptografico baseado em gramaticas a partir de modificacoes no algoritmo de com-

pressao candidato; (iii) avaliar o algoritmo proposto tanto do ponto de vista pratico

quanto teorico; e (iv) identificar direcoes promissoras para investigacoes futuras.

4

Page 18: emprego de gramáticas livres de contexto para a construção de um ...

1.5 Metodologia

A presente investigacao se fundamenta em uma revisao bibliografica do uso de

gramaticas livres de contexto em criptografia, uma revisao bibliografica da producao

cientıfica sobre o uso de gramaticas livres de contexto na compressao de dados,

sistematica, partindo do trabalho seminal de Yang e Kieffer que formaliza o campo

de estudo dos codigos de compressao sem perdas baseados em gramaticas livres

de contexto[3], para a partir daı cumprir os objetivos elencados acima por meio

da formulacao de um algoritmo criptografico baseado em um codigo baseado em

gramaticas que represente o estado da arte e atenda aos requisitos de simplicidade

e uso eficiente de recursos, sua avaliacao teorica basica, implementacao e avaliacao

experimental de sua performance.

1.6 Descricao

No capıtulo 2 sera apresentada uma breve revisao bibliografica das abordagens

existentes com o emprego de gramaticas livres de contexto em criptografia e areas

correlatas.

O capıtulo 3 apresenta a classe dos codigos de compressao baseados em gramaticas

livres de contexto e uma revisao detalhada da bibliografia sobre o assunto a partir

dos artigos de Yang e Kieffer.

A construcao de um novo algoritmo criptografico baseado em gramaticas e apre-

sentada no capıtulo 4. Nele serao mostradas diferentes possibilidades avaliadas para

esta construcao e suas respectivas vantagens e desvantagens, assim como a aborda-

gem final adotada, suas caracterısticas basicas, sua implementacao e uma avaliacao

empırica apoiada em testes estatısticos.

As conclusoes e sugestoes para trabalhos futuros se encontram no capıtulo 5.

5

Page 19: emprego de gramáticas livres de contexto para a construção de um ...

Capıtulo 2

Gramaticas e Criptografia

Para contextualizar a investigacao ora conduzida, apresentamos aqui um resumo

sobre as aplicacoes ja existentes de gramaticas livres de contexto na criptografia. A

bibliografia cientıfica sobre o assunto e limitada, indicando que este nao e um campo

que tem recebido muita atencao da comunidade de pesquisadores, mas ha literatura

com aplicacoes em autenticacao, esteganografia e em criptografia.

Todas as abordagens encontradas sao baseadas no fato de que e facil verificar se

um texto e gerado por uma gramatica quando da posse da ambos, mas difıcil obter

a gramatica da posse somente do texto[4, 6, 7, 8]; a consequencia disto e que a

chave do codigo e a propria gramatica, que deve ser conhecida por todas as partes

(mas nao por terceiros) e cuja linguagem forma o sinal transmitido, enquanto a

abordagem investigada neste trabalho e oposta e busca utilizar partes da propria

gramatica como sinal.

2.1 Esteganografia

A esteganografia e um campo correlato a criptografia mas com objetivos ligei-

ramente distintos; a ideia nao e somente evitar que terceiros possam compreender

a informacao enviada caso a mensagem seja interceptada mas buscam disfarcar a

mensagem, isto e, esconder o proprio fato de que alguma informacao sigilosa esteja

sendo enviada.

6

Page 20: emprego de gramáticas livres de contexto para a construção de um ...

Ha muitas mencoes de usos bastante similares de gramaticas em esteganografia,

simples e diretas, e uma descricao bastante completa de tecnicas de esteganografia

pode ser encontrada no livro de Peter Wayner, “Disappearing Cryptography”[4],

que inclui um capıtulo dedicado a esteganografia com gramaticas livres de contexto.

A ideia basica consiste na formulacao de gramaticas livres de contexto nao de-

terminısticas com regras de producao cuidadosamente montadas de forma a possi-

bilitar a geracao de textos estruturados que codificam uma mensagem na selecao

das regras de producao aplicadas aos sımbolos nao-terminais. Assim, diferentes re-

gras de producao para um mesmo nao-terminal sao associadas a diferentes valores

(numeros, sequencias binarias, letras, palavras, etc) e o decodificador, conhecendo

a gramatica e os valores associados a cada regra de producao, pode analisar o texto

recebido e identificar as regras utilizadas e, por conseguinte, os valores codificados

que formam a mensagem oculta. Nao ha, contudo, um corpo significativo de resul-

tados teoricos em relacao a como de fato projetar codigos esteganograficos fortes

utilizando gramaticas livres de contexto[4].

Para exemplificar estas operacoes, considere a gramatica livre de contexto (porem

nao-determinıstica) abaixo, em que cada regra de producao e associada a uma

sequencia binaria, mostrada entre parenteses ao lado da respectiva regra:

S → αβγ

α → o flamengo (00)

α → o fluminense (01)

α → o botafogo (10)

α → o vasco (11)

β → ganhou (0)

β → perdeu (1)

γ → aquele jogo (0)

γ → aquela partida (1)

Esta gramatica pode ser utilizada para transmitir de maneira oculta a sequencia

0011 em uma mensagem aparentemente inocua: ”o flamengo perdeu aquela partida”.

7

Page 21: emprego de gramáticas livres de contexto para a construção de um ...

Em abordagens hıbridas, a mensagem ocultada pode ser ja criptografada ou,

ainda, o texto pode codificar nao a mensagem diretamente, mas uma chave para

a obtencao da mensagem oculta por outra tecnica esteganografica, por exemplo en-

derecando uma sequencia de pixels de uma imagem em cujos bits menos significativos

se esconde a verdadeira mensagem[5].

A mesma gramatica do exemplo anterior poderia ser utilizada para exemplificar

(muito simplificadamente) como uma abordagem hıbrida poderia ser utilizada. Su-

ponha que quatro pixels de uma imagem RGB de quatro por quatro, com um byte

codificando cada componente de cor de cada pixel, sejam escolhidos para esconder

a sequencia 100111110100 no bit menos significativo de cada um dos componentes

dos pixels isto e, suponha que o primeiro pixel escolhido seja denotado pela tripla

RGB(0xFF, 0x45, 0x45), para esconder os tres primeiros bits da sequencia secreta

(100) podemos modificar a cor do pixel para RGB(0xFF, 0x44, 0x44). Como a

sequencia estara escondida em quatro pixels arbitrarios, podemos especificar quais os

pixels codificando de alguma maneira a sequencia em frases geradas pela gramatica.

Como neste exemplo usaremos a mesma gramatica do exemplo acima, podemos

simplesmente utilizar a sequencia binaria de uma frase, que tem quatro bits, para

especificar enumerativamente qual o pixel da imagem a ser utilizado, lendo os pixels

de cima para baixo e da esquerda para a direita. A sequencia de pixels indicada na

matriz abaixo poderia ser especificada, entao, pela sequencia de frases a sua direita:

3

1

4 2

o fluminense ganhou aquela partida (= 0b0101 = 5)

o vasco ganhou aquele jogo (= 0b1100 = 12)

o flamengo perdeu aquele jogo (= 0b0010 = 2)

o botafogo perdeu aquela partida (= 0b1011 = 11)

Wayner[4] observa ainda que do mesmo modo que os textos podem ser construıdos

como imitacoes de linguagens naturais, a mesma abordagem pode ser utilizada para

gerar sequencias binarias arbitrarias tendo como resultado entao um codigo crip-

tografico e nao mais esteganografia.

Um codigo deste tipo poderia ser construıdo, por exemplo, com uma gramatica

que tenha 256 regras de producao distintas para cada nao-terminal (sendo utilizado o

8

Page 22: emprego de gramáticas livres de contexto para a construção de um ...

valor do proximo byte lido da entrada para decidir qual regra aplicar) cujos membros

direitos contenham cada um apenas um dos 256 terminais da gramatica (todos os

bytes possıveis) seguidos por zero ou mais nao-terminais, em combinacoes diferentes

para cada regra. A producao de frases se daria enquanto houvesse bytes a serem

codificados, e a producao da ultima frase pode ser interrompida quando atingido o

final da entrada. A decodificacao se daria pela identificacao, a cada byte lido dos

dados criptografados, de qual regra de producao foi utilizada e, por conseguinte, qual

o byte correspondente dos dados originais. Por exemplo, uma sequencia codificada

0x00FF... pode ser decodificada com o auxılio da gramatica abaixo para obter a

sequencia original 0x3037....

S → 0x00βγθ (0x30) β → 0x00θωγ (0xFE)

S → 0x01αω (0x4D) β → 0x01 (0x12)

... ... ...

S → 0xFF (0x02) β → 0xFFωαθγφ (0x37)

2.2 Autenticacao

Singh e dos Santos[6] desenvolveram um sistema de autenticacao para a auto-

rizacao de transacoes de cartao de credito atraves do uso de numeros de cartao de

credito descartaveis, isto e, tokens ou codigos de autenticacao de uso unico.

No esquema proposto, o titular do cartao de credito e a instituicao financeira

emissora do cartao compartilham um conjunto de gramaticas que o titular utiliza

para gerar novos numeros a cada transacao e o emissor utiliza para validar tais

numeros na autorizacao de transacoes. Um protocolo e seguido para definir qual a

ordem de utilizacao das gramaticas de modo que gramaticas distintas sejam utiliza-

das em sucessivas transacoes, o comprimento dos codigos e o historico dos codigos

ja autenticados para que um numero nao possa ser reutilizado para autenticar uma

segunda transacao fraudulenta[6].

A tecnica apresentada e de implementacao relativamente simples e nao requer

muitos recursos computacionais, e ao mesmo tempo que e segura, e e uma aborda-

gem similar a frequentemente utilizada em autenticacao de dois fatores com tokens

9

Page 23: emprego de gramáticas livres de contexto para a construção de um ...

mas com a ideia original de aplicar gramaticas livres de contexto na producao dos

tokens. A principal motivacao apresentada por Singh e dos Santos[6] para a esco-

lha do uso de gramaticas livres de contexto ao inves de algoritmos criptograficos

usuais tais como RSA ou DSA e o fato de que a seguranca destes algoritmos de-

pende da dificuldade de fatoracao de grandes numeros, porem o avanco do poder

computacional significa que chaves de comprimentos considerados seguros tornam-se

em poucas decadas totalmente vulneraveis, e ha entao a necessidade de se atuali-

zar os algoritmos para que utilizem chaves cada vez maiores ao longo do tempo;

computar uma gramatica a partir de exemplos de sua linguagem, por sua vez, e

um problema computacionalmente intratavel e, portanto, a seguranca de algoritmos

baseados nesta caracterıstica estariam imunes aos avancos do poder computacional

ao longo do tempo.

Esquemas alternativos sao avaliados por Singh e dos Santos[6], porem eles apon-

tam que estes esquemas introduzem complexidade na operacao, requerendo por

exemplo autenticacao em tempo real diretamente entre o emissor e o titular e o

envio do codigo de uso unico do primeiro para o segundo, ou somente diminuem

as chances o o potencial de dano do roubo de numero de cartao de credito, mas

nao os eliminando, ao gerar numeros temporarios com limites de valor de transacao,

numero de usos ou tempo de validade mais curto que o usual.

Outros autores apontaram, entretanto, a falta de resultados teoricos que garantam

a seguranca deste esquema, dado que computar uma gramatica a partir de exemplos

de sua linguagem e um problema intratavel no pior caso mas nao se sabe a dificul-

dade de computacao no caso medio[9, 10] (e nem o esquema indica como construir

as gramaticas com a dificuldade desejavel[9, 11]) e que tambem nao se sabe o quao

difıcil e gerar novas frases validas a partir de exemplos da linguagem[9, 11, 12].

Estas questoes estao em linha com as colocadas por Wayner[4] acerca do uso de

gramaticas em esteganografia, ja comentados na secao anterior.

Trabalhos posteriores de Singh e dos Santos[12] trataram de uma destas crıticas

apresentando um algoritmo para a obtencao de gramaticas difıceis de se computar

a partir de exemplos, porem a avaliacao apresentada foi empırica.

10

Page 24: emprego de gramáticas livres de contexto para a construção de um ...

Capıtulo 3

Gramaticas e Compressao

John C. Kieffer e En-hui Yang investigaram em uma serie de papers a classe de

codigos de compressao sem perdas batizada codigos baseados em gramaticas (no

original, grammar-based codes) e que “em resposta a qualquer sequencia x de dados

de entrada sobre um alfabeto, seleciona uma gramatica livre de contexto Gx que

represente x no sentido de que x e a unica sequencia que pertence a linguagem

gerada por Gx”[3]1.

O objetivo dos autores e desenvolver novos algoritmos de compressao de dados sem

perdas baseados em gramaticas que sejam eficientes, praticos e universais. Algorit-

mos de compressao existentes e largamente utilizados sao baseados ou em codificacao

aritmetica (tambem conhecidos como metodos estatısticos ou de aproximacao de en-

tropia) ou no algoritmo Lempel-Ziv (metodos baseados em dicionarios ou de reducao

de redundancia). A codificacao aritmetica utiliza modelos estatısticos para codifi-

car cada sımbolo com uma probabilidade condicional, enquanto no Lempel-Ziv a

sequencia de entrada e analisada e dividida em subsequencias utilizando casamento

de padroes, e as sequencias sao codificadas com suas posicoes em um dicionario[13].

Ate entao, algoritmos que nao se baseiam em nenhuma das duas tecnicas obtinham

taxas de compressao inferiores, nao tinham implementacao pratica, ou ambos[13],

mas os autores argumentam que a representacao de uma sequencia de dados por

1Traducao livre do original “in response to any input data x over a fixed alphabet, selects a

context-free grammar Gx representing x in the sense that x is the unique string belonging to the

language generated by Gx”

11

Page 25: emprego de gramáticas livres de contexto para a construção de um ...

uma gramatica que a gera pode ser eficientemente utilizada para a compressao de

dados pois as regras de producao de tal gramatica podem ser vistas como uma

representacao compacta da sequencia que, em seguida, pode ser indiretamente com-

primida ao se aplicar tecnicas reconhecidas de codificacao aritmetica para comprimir

as regras de producao da gramatica[3]. Indo alem, construir uma gramatica a par-

tir de uma sequencia pode ser visto como um modo de analisar os dados e obter

subsequencias, tal qual o objetivo dos algoritmos Lempel-Ziv, e isto sugere que

codigos baseados em gramaticas podem ser uma combinacao elegante e eficiente de

casamento de padroes e codificacao aritmetica[13].

A principal proposicao do artigo seminal de Kieffer e Yang sobre o assunto de

codigos baseados em gramaticas[3] e que tais codigos (sujeitos a pequenas restricoes)

sao compressores sem perdas e universais que obtem boas taxas de compressao, al-

cancando resultados melhores que o algoritmo Lempel-Ziv para algumas sequencias

de dados se os codigos forem bem projetados. A estrutura geral de um codigo

baseado em gramatica consiste de duas partes, uma transformada de gramatica e

um codificador de gramatica. A transformada de gramatica recebe como entrada a

sequencia de dados x que se deseja comprimir e constroi uma gramatica livre de

contexto Gx que represente x (no sentido explicitado na citacao acima). O codifica-

dor de gramatica entao comprime as regras de producao de Gx em uma sequencia

binaria B(Gx). Para obter x, e necessario primeiro utilizar um decodificador que

reconstrua Gx a partir de B(Gx) para entao seguir aplicando as regras de producao

de Gx para, ao final, obter x.

Nas secoes que seguem serao apresentadas e discutidas as principais definicoes

e teoremas introduzidos por Kieffer, Yang e co-autores em tres de seus principais

artigos sobre os codigos baseados em gramaticas[3, 13, 14] em relacao a gramaticas

admissıveis, propriedades desejaveis de transformadas de gramaticas, analise de en-

tropia e metodos para a codificacao binaria nos codificadores de gramatica, assim

como algoritmos praticos para a implementacao dos codigos.

Serao tambem apresentados e discutidos, em seguida, alguns artigos e trabalhos

de diversos autores em uma revisao bibliografica sobre o desenvolvimento recente e

12

Page 26: emprego de gramáticas livres de contexto para a construção de um ...

relevante dos codigos baseados em gramatica apos a sua definicao por Yang e Kief-

fer. Os trabalhos foram selecionados para a revisao seguindo os seguintes criterios:

trabalhos contendo citacoes a todos os tres artigos de Yang e Kieffer mencionados;

ou contendo citacoes a ao menos um dos artigos e tendo sido publicado nos ultimos

cinco anos (isto e, de 2011 a 2015 inclusive).

3.1 Gramaticas admissıveis

Gramaticas admissıveis sao a subclasse das gramaticas livres de contexto para as

quais se pode garantir que L(G) = x para alguma sequencia x, e a apresentacao

das mesmas neste trabalho segue a feita por Yang e Kieffer[3], que introduziram

notacoes uteis e definicoes e teoremas importantes que mostram que as propriedades

das gramaticas admissıveis sao consistentes e que nos dao ferramentas matematicas

para a utilizacao das gramaticas nos codigos de compressao.

Uma gramatica livre de contexto pode ser colocada na forma de uma quadrupla

G = (N, T,R, S) onde N e o conjunto de sımbolos nao-terminais ou variaveis da

gramatica, T e o conjunto de sımbolos terminais (disjunto de N), R e o conjunto de

regras de producao (como definidas acima) cujos membros esquerdos sao elementos

em N e cujos membros direitos sao elementos em (N ∪ T )∗, e cada variavel aparece

ao menos uma vez entre os membros esquerdos das regras em R e, finalmente, S

e uma variavel especial denominada sımbolo de partida. As regras de producao de

uma gramatica podem ser expressas na forma A → α, onde A ∈ Σ e α ∈ Σ∗ para

algum conjunto finito Σ.

Para definir a linguagem L(G) gerada por G, a seguinte notacao e utilizada:

αG→ β significando que uma regra de producao pode ser utilizada para substituir

uma variavel na sequencia α para obter a sequencia β, e de modo similar αG⇒ β

se uma sequencia de substituicoes utilizando regras de producao pode ser aplicada

para obter β a partir de α. Pode-se definir entao L(G) = u ∈ T ∗ : SG⇒ u.

Uma gramatica admissıvel pode ser, entao, definida como uma gramatica livre de

contexto G possui mais algumas propriedades:

13

Page 27: emprego de gramáticas livres de contexto para a construção de um ...

1. G e determinıstica, isto e. para cada variavel ha exatamente uma regra de

producao em que ela e o membro esquerdo;

2. Nenhuma regra de producao tem o membro direito vazio;

3. L(G) nao e vazia; e

4. G nao contem sımbolos inuteis.

Nota-se que se uma gramatica e determinıstica entao sua linguagem e vazia ou

contem uma unica sequencia, portanto e claro que as propriedades 1 e 3 acima sao

suficientes para garantir que para cada gramatica admissıvel ha uma unica sequencia

x tal que L(G) = x, como desejado, e pode-se dizer que essa sequencia e represen-

tada por G. Adicionalmente, por conta destas propriedades exigidas das gramaticas

admissıveis, ve-se que somente a lista de regras de producao e suficiente para espe-

cificar completa e univocamente uma gramatica admissıvel G, pois N(G), T (G) e S

podem ser facilmente inferidas pela simples observacao de R(G).

Apresentamos ainda duas ultimas definicoes antes dos primeiros teoremas. Uma

e a de um endomorfismo fG sobre (N(G)∪T (G))∗, onde G e uma gramatica livre de

contexto determinıstica que nao contem nenhuma regra de producao com o membro

direito vazio (o que, como veremos, significa que ela e admissıvel), tal que fG(a) =

a, a ∈ T (G) e se A → α ∈ R(G) entao fG(A) = α. Essa definicao e, basicamente,

uma ferramenta pratica para denotar a aplicacao das regras de producao de uma

gramatica admissıvel e trabalhar matematicamente as suas propriedades. A outra

definicao e um mapeamento f∞G de (N(G)∪T (G))∗ em si mesmo, mapeando qualquer

sequencia u no domınio ao ponto fixo do L-sistema (ou sistema de Lindenmayer)

(N(G) ∪ T (G), fG, u).

Agora, apresentamos os teoremas como introduzidos em [3]:

Teorema 1. [3, Teo. 1] Seja G uma gramatica admissıvel. Entao a sequencia de

dados x representada por G pode ser caracterizada como o ponto fixo do L-systema

(N(G) ∪ T (G), fG, S).

14

Page 28: emprego de gramáticas livres de contexto para a construção de um ...

Teorema 2. [3, Teo. 2] Seja G livre de contexto determinıstica tal que a sequencia

vazia nao seja o membro direito de nenhuma regra de producao de G. Entao as tres

afirmacoes a seguir sao equivalentes:

1. G e admissıvel;

2. O grafo de derivacao de G e acıclico e tem sua raiz no vertice S;

3. f|V (G)|G (S) ∈ T (G)+ e cada sımbolo em N(G) ∪ T (G) e uma entrada de ao

menos uma das sequencias f iG(S), i = 0, 1, . . . , |N(G)|.

Teorema 3. [3, Teo. 3] Seja G uma gramatica admissıvel. Entao a sequencia de

dados x representada por G e computada pelo calculo x = f|N(G)|G (S).

Teorema 4. [3, Teo. 4] Seja G uma gramatica admissıvel livre de contexto. Seja u

qualquer sequencia em (N(G) ∪ T (G))+. Entao o L-systema (N(G) ∪ T (G), fG, u)

tem um ponto fixo u∗, e u∗ ∈ T (G)+. O ponto fixo u∗ e computavel pela formula

u∗ = f|N(G)|G (u).

Teorema 5. [3, Teo. 5] Seja G uma gramatica admissıvel. Entao

1. f∞G e um endomorfismo em (N(G) ∪ T (G))∗;

2. f∞G (u) ∈ T (G)+ para cada u ∈ (N(G) ∪ T (G))+;

3. Para cada u ∈ (N(G) ∪ T (G))+, f∞G (u) = f

|N(G)|G (u);

4. Se A → α e uma regra de producao de G, entao f∞G (A) = f∞

G (α).

Estes teoremas garantem que qualquer gramatica livre de contexto determinıstica

tal que a sequencia vazia nao seja o membro direito de nenhuma de suas regras

de producao tera todas as propriedades das gramaticas admissıveis e provem um

arcabouco matematico para a analise da aplicacao das regras de producao atraves

do endomorfismo definido acima, que e uma representacao de operacoes de subs-

tituicao paralelas e que alcanca uma sequencia terminal em no maximo |N(G)|

iteracoes. Pode-se notar, por exemplo, que a terceira afirmacao do Teorema 2 equi-

vale a propriedade das gramaticas admissıveis de nao terem sımbolos inuteis; o

Teorema 3 segue diretamente do Teorema 2 e prove um algoritmo direto para com-

putar a sequencia de dados atraves de substituicoes paralelas, assim como um limite

15

Page 29: emprego de gramáticas livres de contexto para a construção de um ...

superior para o numero de iteracoes necessarias para obter a sequencia representada

por uma gramatica admissıvel; Os teoremas 1, 4 e 3 tambem sao estreitamente re-

lacionados; e, finalmente, o Teorema 5 segue dos anteriores e introduz uma notacao

util.

O limite superior para o numero de iteracoes de substituicoes de sequencias ne-

cessarias para obter a sequencia representada a partir do sımbolo de partida (e simi-

larmente para o ponto fixo u∗ do sistema (N(G)∪ T (G), fG, u)) pode ser facilmente

deduzido se considerarmos que gramaticas admissıveis nao tem sımbolos inuteis e

que representam uma e somente uma sequencia composta somente por sımbolos

terminais. Qualquer sımbolo que nao o sımbolo de partida claramente deve estar

em um caminho que se inicia no sımbolo de partida, pois nao pode ser inutil, e

portanto o grafo tem sua raiz no sımbolo de partida. Como a sequencia produzida

contem apenas sımbolos terminais, ela e obrigatoriamente a sequencia representada

pela gramatica e mais nenhuma substituicao e possıvel e nao podem haver, entao,

ciclos no grafo de derivacao, caso contrario variaveis do ciclo iriam aparecer infi-

nitas vezes na sequencia produzida e haveriam infinitas iteracoes de substituicoes.

Sendo o grafo acıclico e com a raiz no sımbolo de partida, qualquer caminho entre o

sımbolo de partida e um sımbolo terminal pode passar por cada variavel no maximo

uma unica vez, e consequentemente o numero maximo de iteracoes necessarias para

produzir a sequencia terminal e o numero de variaveis da gramatica.

3.2 Transformadas de gramatica

Yang e Kieffer definem transformadas de gramatica mapeamentos um a um de

sequencias de dados a gramaticas (que representam as respectivas sequencias) e

focam em duas classes de transformadas, as assintoticamente compactas e as irre-

dutıveis. O conjunto G (Σ) e definido como o conjunto de todas as gramaticas G em

que i. G e admissıvel; ii. T (G) ⊂ Σ; iii. A0 e o sımbolo de partida de G; iv. N(G) =

A0, A1, A2, . . . , A|N(G)−1|; e v. a ordem da primeira aparicao (da esquerda para

a direita) das variaveis na sequencia f 0G(A0)f

1G(A0)f

2G(A0) . . . f

|N(G)|−1G (A0) segue a

ordem dos subscritos. Utilizando esta definicao, uma transformada de gramatica

pode ser representada como um mapeamento de Σ+ em G(Σ) tal que para x ∈ Σ+

16

Page 30: emprego de gramáticas livres de contexto para a construção de um ...

e Gx ∈ G(Σ), a transformada de gramatica que assinala a gramatica Gx a sequencia

x que ela representa e denotada por x → Gx.[3]

Uma transformada de gramatica e dita assintoticamente compacta se para cada

sequencia x do alfabeto Σ a gramatica correspondenteGx ∈ G*(Σ) e, adicionalmente,

limn→∞maxx∈Σn|Gx||x| = 0, onde G*(Σ) e o subconjunto de gramaticas G ∈ G(Σ)

para as quais f∞G (A) 6= f∞

G (B) para todo A,B ∈ N(G) | A 6= B; e |G| e definido

como o comprimento total de todos os membros direitos das regras de producao de

G[3]. E evidente o porque de tal propriedade ser desejada em codigos baseados em

gramaticas para compressao de dados.

Por outro lado, uma transformada de gramatica e definida irredutıvel se cada

gramatica Gx produzida por si e irredutıvel, isto e, e uma gramatica admissıvel

em que f∞G (v1) 6= f∞

G (v2)∀v1, v2 ∈ N(G) | v1 6= v2, todas as variaveis (exceto o

sımbolo de partida) aparecem ao menos duas vezes entre os membros direitos das

regras de producao e nao ha subsequencias (nao-sobrepostas) repetidas de compri-

mento 2 ou mais nos membros direitos das regras de producao[3]. E novamente

evidente o porque destas propriedades serem desejadas, pois qualquer gramatica

que nao e irredutıvel pode ser manipulada e modificada por simples substituicoes de

subsequencias, variaveis e regras de producao para obter uma nova gramatica repre-

sentando a mesma sequencia de dados mas com um comprimento total menor dos

membros direitos das regras de producao e portanto obtendo melhor compressao.

Alias, Yang e Kieffer apontam em [3] que qualquer transformada de gramatica pode

ser tornada irredutıvel por meio da aplicacao sistematica de um numero finito de pas-

sos de reducao (basicamente casamento e substituicao de subsequencias) apos uma

gramatica representando a sequencia de dados ter sido obtida; os referidos autores

ainda definem um numero de regras de reducao e uma abordagem sistematica para

a sua aplicacao na forma de algoritmos para transformadas de gramatica que usam

as regras de reducao para alcancar a irredutibilidade, assim como teoremas relacio-

nados as propriedades de codificacao das gramaticas e transformadas de gramatica,

que sao os principais resultados do artigo.

17

Page 31: emprego de gramáticas livres de contexto para a construção de um ...

Cinco regras de reducao sao apresentadas em Yang e Kieffer[3], todas bastante

simples e descritas a seguir:

1. Se A e uma variavel que aparece uma unica vez entre os membros direitos das

regras de producao de G, remova a regra de producao cujo membro esquerdo

e A e substitua por seu membro direito a variavel A no unico lugar em que ela

ocorre nos membros direitos do restante das regras de producao;

Exemplo 1. Suponha que S → aabaAbaaaba e A → bb sao as regras de

producao de uma gramatica. A regra de reducao 1 pode ser utilizada para

obter uma gramatica com o conjunto reduzido de regras de producao S →

aababbbaaaba.

2. Se β e uma sequencia de comprimento ao menos 2 que aparece duas vezes

no membro direito de uma regra de producao (em posicoes nao sobrepostas),

adicione um novo sımbolo de variavel a N(G), substitua β pela nova variavel

na regra de producao, e adicione uma nova regra de producao com o membro

direito sendo β e o membro esquerdo a nova variavel;

Exemplo 2. Suponha que S → aababbbaaaba e a unica regra de producao

de uma gramatica. A regra de reducao 2 pode ser aplicada para obter uma

gramatica com as regras de producao S → AbbbaA e A → aaba.

3. A Regra de Reducao 3 e similar a Regra de Reducao 2, mas neste caso a

sequencia β nao aparece duas vezes na mesma regra de producao, mas aparece

nos membros direitos de duas regras de producao distintas e e substituıda por

uma nova variavel nos dois lugares, ao passo que uma nova regra de producao

e adicionada;

Exemplo 3. Suponha que S → AbbbaA e A → aaba sao as regras de producao

de uma gramatica. Aplique a regra de reducao 3 para obter uma nova gramatica

com as regras de producao S → AbbBA, A → aaB e B → ba.

4. Se β e o membro direito de uma regra de producao mas tambem aparece como

uma subsequencia no membro direito de outra regra de producao, substitua β

no membro direito da segunda regra pelo membro esquerdo da primeira;

18

Page 32: emprego de gramáticas livres de contexto para a construção de um ...

Exemplo 4. Suponha que S → AbbBA, A → aaba e B → ba sao as regras

de producao de uma gramatica. Aplicando a regra de reducao 4 as regras de

producao se tornam S → AbbBA, A → aaB e B → ba.

5. Se ∃A,B ∈ V (G) | A 6= B ∧ f∞G (A) = f∞

G (B), substitua B por A em todos

os membros direitos das regras de producao e remova as regras de producao

cujos membros esquerdos se tornem sımbolos inuteis.

Exemplo 5. Suponha que S → AbbBC, A → aaB, B → ba, e C → aaba

sao as regras de producao de uma gramatica. Utilizando a regra de reducao

5 obtem-se uma gramatica reduzida com as regras de producao S → AbbBA,

A → aaB e B → ba.

Pode-se ver facilmente que as regras de reducao 2, 3 e 4 sao as que trazem o po-

der de compressao do casamento de sequencias as transformadas de gramatica irre-

dutıveis, mas estas regras nao definem, por si, transformadas de gramatica, nem nos

instruem explicitamente no melhor caminho para projeta-las[13]. Yang e Kieffer[3]

discutem dois algoritmos iterativos que se utilizam destas regras na implementacao

de transformadas de gramatica, que resumimos a seguir:

• Algoritmo do Casamento Mais Longo de Subsequencia: Dada uma sequencia

de dados, se inicia com a gramatica trivial que possui uma unica regra de

producao com o sımbolo de partida como seu membro esquerdo e a sequencia

de dados completa como seu membro direito. O restante do procedimento

se resume a buscar iterativamente o casamento mais longo de subsequencias

nos membros direitos das regras de producao da gramatica, isto e, a mais

longa subsequencia que aparece duas vezes (em posicoes nao-sobrepostas, se

na mesma regra de producao), e, dependendo de onde a subsequencia e en-

contrada, aplicar a regra de reducao 2, 3 ou 4. Quando nao puderem mais

ser encontrados casamentos de subsequencias de comprimento 2 ou mais, a

gramatica obtida representa a sequencia de dados de entrada e irredutıvel.

• Algoritmo Sequitur Modificado: O procedimento comeca com uma gramatica

mınima cuja unica regra de producao possui o sımbolo de partida como seu

membro esquerdo e o primeiro sımbolo (da esquerda para a direita) da sequencia

19

Page 33: emprego de gramáticas livres de contexto para a construção de um ...

de dados de entrada como seu membro direito. A cada iteracao, o proximo

sımbolo (lendo da esquerda para a direita) da sequencia de dados e adicionado

ao final da regra de producao atual para o sımbolo de partida e as regras de

reducao sao aplicadas de modo que ao fim de cada passo a gramatica obtida

seja sempre irredutıvel. Quando o ultimo sımbolo da sequencia de entrada e

adicionado e o ultimo passo de aplicacao das regras de reducao e executado, a

gramatica resultante representa a sequencia de dados de entrada e e irredutıvel.

O segundo algoritmo e denominado Sequitur Modificado pois ele e bastante pa-

recido com o algoritmo Sequitur proposto por Nevill-Manning e Witten, que e um

algoritmo em tempo linear para gerar recursivamente uma gramatica que represente

uma dada sequencia adicionando um sımbolo por vez e aplicando duas restricoes

a cada passo: todo digrama (par de sımbolos) deve ser unico e todas as regras de

producao devem ser utilizadas ao menos duas vezes[15].

Em [3] ha tambem varias definicoes, demonstracoes e teoremas sobre os codigos

baseados em gramaticas vistos pelo prisma da teoria da informacao, tais como resul-

tados referentes a entropia, metodos de codificacao em sequencias de codigo binario

com os limites para tais sequencias (Teorema 6), e resultados acerca do decaimento

assintotico de sua maxima redundancia pontual (Teoremas 7 e 8 – os principais

resultados de [3]). O conceito de maxima redundancia pontual exprime um limite

superior para a redundancia ponto a ponto, um conceito mais forte que o de um

limite para o valor esperado da redundancia, que e a diferenca entre o comprimento

da descricao de um codigo e o numero otimo teorico de bits de informacao[16].

Teorema 6. [3, Teo. 6] Ha um mapeamento um a um B : G(Σ) → 0, 1+ tal que:

1. Se G1 e G2 sao gramaticas distintas em G(Σ), entao o codigo binario B(G1)

nao e um prefixo do codigo binario B(G2); e

2. Para cada G ∈ G(Σ), o comprimento do codigo B(G) satisfaz |B(G)| ≤ |Σ|+

4 |G|+ dH(G)e.

A quantidade H(G) referida no Teorema 6 e a entropia da gramatica G, definida

em [3] como a entropia nao normalizada da sequencia ωG, que por sua vez e a

20

Page 34: emprego de gramáticas livres de contexto para a construção de um ...

concatenacao dos membros direitos das regras de producao de G ρG com a primeira

ocorrencia (da esquerda para a direita) de cada variavel de G removida. A entropia

nao normalizada de uma sequencia e definida por H∗(u) ,∑n

i=1 log(

nm(ui|u)

), onde

m(s | u) = |1 ≤ i ≤ n : ui = s| e n = |u|; a entropia da gramatia e entao H(G) ,

H∗(ωG).

Teorema 7. [3, Teo. 7] Seja φ um codigo baseado em gramaticas da classe Cac(Σ)

[todos os codigos baseados em gramaticas com alfabeto Σ e utilizando uma trans-

formada de gramatica assintoticamente compacta], e seja x → Gx a transformada

de gramatica utilizada por φ. Seja νn uma sequencia de numeros positivos con-

vergindo a zero tal que maxx∈ΣnGx

x= O(νn). Entao, para cada inteiro positivo k,

Redn(φ,Λkfs(Σ)) = O(γ(νn)), onde γ , x log( 1

x), x > 0.

Teorema 8. [3, Teo. 8] A classe de codigos Cirr(Σ) [todos os codigos baseados em

gramaticas com alfabeto Σ e utilizando uma transformada de gramatica irredutıvel]

e um subconjunto da classe Cac(Σ). Adicionalmente, para cada inteiro positivo k,

maxφ∈Cirr(A)Redn(φ,Λkfs(Σ)) = O( log log n

log n).

Note que o Teorema 8 garante que todas as transformadas de gramatica irre-

dutıveis sao tambem assintoticamente compactas, o que e um resultado muito in-

teressante uma vez que as regras de reducao que podem ser utilizadas para obter

gramaticas irredutıveis sao relativamente simples de serem implementadas em al-

goritmos (como visto, porr exemplo, nos algoritmos de Casamento Mais Longo de

Subsequencia e Sequitur Modificado). Uma prova oferecida para o Teorema 6 e

um exemplo de algoritmo para o codificador de gramatica que satisfaz as condicoes

do teorema. Entretanto, uma observacao e feita em relacao a este algoritmo para

codificacao (e os Teoremas 7 e 8 que dependem dele) restringe os codigos baseados

em gramaticas a processamento em batelada somente, pois as gramaticas precisam

estar completas (e portanto a sequencia de dados de entrada deve ter sido comple-

tamente analisada) para ser codificada, o que impede a adocao de abordagens de

codificacao sequencial contınua. Esta questao e resolvida num outro artigo de Yang

e Kieffer[13]. O esquema do codificador de gramatica para uma gramatica G ∈ G(Σ)

introduzida na prova do Teorema 6 consiste em montar uma sequencia binaria B(G)

concatenando seis partes B1 a B6, cada uma computada como descrito a seguir[3]:

21

Page 35: emprego de gramáticas livres de contexto para a construção de um ...

1. B1 tem comprimento |N(G)| e consiste de |N(G)| − 1 zeros seguidos por um

1. Isto indica o numero de variaveis da gramatica;

2. B2 tem comprimento |Σ| e consiste em uma sequencia de bits indicando quais

sımbolos do alfabeto sao incluıdos entre os sımbolos terminais da gramatica;

3. B3 tem comprimento |G| e consiste da representacao unaria (como em B1)

da frequencia absoluta de cada sımbolo da gramatica (variaveis e sımbolos

terminais) exceto o sımbolo de partida nos membros direitos das regras de

producao;

4. B4 tem comprimento |G| e consiste nos comprimentos dos membros direitos

das regras de producao (tambem em representacao unaria);

5. B5 tem comprimento |G| e consiste em uma sequencia de bits indicando em que

posicoes de ρG (a concatenacao dos membros direitos das regras de producao

de G) esta a primeira (da esquerda para a direita) ocorreencia de cada variavel

de G; e

6. B6 tem comprimento maximo de dH(G)e e consiste de ωG codificado utilizando

codificacao enumerativa (que faz uso das frequencias em B3).

A tecnica de codificacao enumerativa consiste na producao de um dicionario

ordenado (em ordem lexicografica) das sequencias com as mesmas frequencias de

sımbolos da sequencia a ser codificada e a transmissao do ındice desta naquele di-

cionario, assim como os proprios sımbolos e suas frequencias se estas informacoes ja

nao forem do conhecimento do decodificador[17].

As transformadas de gramatica e os algoritmos introduzidos em [3] se utilizam

tanto do casamento de padroes e codificacao aritmetica, porem nao e feita uma

tentativa explıcita de otimizar esta combinacao. Isto e feito em [13] com a introducao

de uma transformada de gramatica gulosa sequencial e tres algoritmos de compressao

baseados nela.

22

Page 36: emprego de gramáticas livres de contexto para a construção de um ...

3.2.1 Transformada gulosa

A transformada de gramatica gulosa descrita em [13] e bastante similar ao algo-

ritmo Sequitur Modificado de [3], mas ao inves de simplesmente adicionar o proximo

sımbolo a cada passo, o algoritmo guloso adiciona a variavel da gramatica (exceto o

sımbolo de partida) que representa o prefixo mais longo do restante da sequencia de

dados, se houver tal variavel ou, se nao, adiciona o proximo sımbolo. Uma variante

ligeiramente mais gulosa e de implementacao mais complicada, permitindo o uso

do sımbolo de partida (e o redefinindo, se utilizado), tambem foi apresentada por

Kieffer e Yang [18], porem e pouco provavel que toda a sequencia ja processada se

repita inteiramente como prefixo da sequencia restante a nao ser bem no inıcio do

processo, e as propriedades da transformada sao identicas a da versao mais simples

[13].

Tres algoritmos de compressao desenvolvidos utilizando esta transformada gulosa

e apresentados em [13] se encontram resumidos a seguir. Em [13] Kieffer e Yang

tambem apresentam resultados de simulacoes mostrando que a performance de com-

pressao utilizando estes algoritmos foi ate 26% melhor em comparacao com o Unix

Compress (LZ78) e 37% em comparacao com o Gzip (LZ77). Mais resultados de

simulacoes e detalhes de implementacao seriam apresentados em [19] porem apesar

dos nossos melhores esforcos nao foi possıvel localizar uma versao publicada deste

artigo.

3.2.1.1 Algoritmo Hierarquico

Uma gramatica e obtida a partir da sequencia de dados de entrada com a aplicacao

da transformada gulosa, e em seguida a gramatica final obtida e codificada com um

codigo aritmetico de ordem zero e alfabeto dinamico.

Para codificar a gramatica, primeiro faz-se uma conversao para a sua forma

canonica (simplesmente renomear as variaveis para si, i = 0, 1, 2, . . ., onde s0 e o

sımbolo de partida e tal que se as regras de producao forem lidas da esquerda para

a direita e de cima para baixo, as variaveis aparecam em ordem, isto e, si aparece

antes de si+1 para todo i–para simplificar a notacao utilizamos S ao inves de N(G)

23

Page 37: emprego de gramáticas livres de contexto para a construção de um ...

para denotar este novo conjunto de variaveis renomeadas) e se concatenam os mem-

bros direitos das regras de producao em uma sequencia, inserindo o sımbolo e apos

o membro direito da regra do sımbolo de partida, e apos inserindo b e e respectiva-

mente antes e depois de qualquer regra de producao cujo comprimento seja maior

que 2.

A partir desta sequencia, a primeira ocorrencia da esquerda para a direita de

cada variavel e substituıda por s, tirando vantagem do fato que a gramatica foi

reescrita em sua forma canonica, e finalmente e aplicado um codigo aritmetico de

ordem zero para codificar esta sequencia, utilizando um contador c(β), β ∈ S ∪Σ ∪

b, e, s, iniciando com c(β) = 1 para cada β ∈ Σ ∪ b, e, s e c(β) = 0 para os

outros. Cada sımbolo da sequencia, lido da esquerda para a direita, e codificado

pela probabilidade c(β)/∑

α∈S(i)∪Σ∪b,e,sc(α), onde S(i) = s1, s2, ..., si e o subconjunto

de S contendo somente as variaveis introduzidas ate aquele ponto na codificacao da

sequencia (exceto o sımbolo de partida s0); e conforme cada sımbolo e codificado, seu

contador e incrementado e, se o sımbolo for s, a proxima variavel si+1 e adicionada

ao alfabeto do codigo aritmetico e o contador c(si+1) tambem e incrementado.

3.2.1.2 Algoritmo Sequencial

Enquanto a transformada de gramatica gulosa analisa a sequencia de dados, a

sequencia de subsequencias analisadas e codificada utilizando um codigo aritmetico

de ordem zero.

Note que cada subsequencia analisada na entrada ou e um unico sımbolo do alfa-

beto ou e representada por uma unica variavel e, pela natureza sequencial do algo-

ritmo guloso, o decodificador pode decodificar cada subsequencia sequencialmente,

conforme bits suficientes sao recebidos, e utilizar as mesmas regras da transformada

gulosa para obter tanto a gramatica quanto a propria sequencia de dados original

tambem de modo sequencial. Cada sımbolo da sequencia de subsequencias analisa-

das pode ser codificada de modo similar ao visto acima no algoritmo hierarquico,

mas com o alfabeto do codigo aritmetico iniciando somente com Σ, e as variaveis

sao adicionadas ao passo em que sao adicionadas a propria gramatica.

24

Page 38: emprego de gramáticas livres de contexto para a construção de um ...

Os contadores sao iniciados com c(β) = 1 para β ∈ Σ, e cada sımbolo lido e

codificado usando a probabilidade c(β)/ ∑α∈S(i)∪Σ

c(α) e tem seu contador incrementado.

Se uma variavel e introduzida a gramatica, um contador e criado com o valor c(si) =

1.

3.2.1.3 Algoritmo Sequencial Aprimorado

Enquanto a transformada de gramatica gulosa analisa a sequencia de dados, ao

inves de simplesmente codificar a sequencia de subsequencias, o algoritmo procura

operar na sequencia de particoes induzida pela gramatica, que e uma sequencia mais

curta.

A sequencia de particoes induzida pela gramatica e obtida substituindo a primeira

ocorrencia da esquerda para a direita de cada variavel regra de producao do sımbolo

de partida pelo membro direito da sua regra de producao correspondente, e uma

analise da sequencia de dados pode ser obtida substituindo cada variavel pela sub-

sequencia que ela representa. Como foi descrito, so se poderia obter a sequencia de

particoes induzida pela gramatica apos esta ter sido completamente formada, mas

pode-se tentar utilizar esta ideia se, no momento da codificacao de um sımbolo ana-

lisado pela transformada gulosa, se uma regra de reducao sera aplicada ou nao apos

a sua adicao, e se tambem se tem acesso ao estado atual da gramatica antes de ser

atualizada; o decodificador tem, na realidade, acesso ao estado atual da gramatica

pois ele a constrois sequencialmente durante a decodificacao, como visto no algo-

ritmo sequencial original acima, e e assim que o algoritmo sequencial aprimorado

busca operar na sequencia de particoes induzida.

Uma sequencia auxiliar I e produzida com um bit para cada sımbolo analisado da

sequencia de dados. Quando o i-esimo sımbolo e analisado, I(i) = 1 se ocorre uma

reducao apos sua adicao a gramatica e caso contrario I(i) = 0. Esta sequencia e

codificada com um codigo aritmetico de primeira ordem utilizando quatro contadores

c(0, 0), c(0, 1), c(1, 0) e c(1, 1), inicialmente com o valor 1. Se i sımbolos ja foram

analisados, o valor de I(i+1) e definido quando o (i+1)-esimo sımbolo β e analisado

e adicionado a gramatica. I(i+ 1) e entao codificado coma probabilidade dada por

c(I(i),I(i+1))/(c(I(i),0)+c(I(i),1)) e β e codificado com um codigo aritmetico de ordem zero

25

Page 39: emprego de gramáticas livres de contexto para a construção de um ...

com dois contadores separados c(β) e c(β), usando a probabilidade c(β)/∑

c(γ)γ∈S(ji)∪Σ−L2(α)

se I(i+1) = 0, a probabilidade c(β)/∑c(γ)

γ∈L1(α)

se I(i) = 0 e I(i+1) = 1, e nao codificando

β se I(i) = 1 e I(i+1) = 1. L1(α) e L2(α) sao listas mantidas de todos os sımbolos

η ∈ S ∪ Σ tal que αη e um padrao que aparece no estado atual da gramatica

mas nao e os dois ultimos sımbolos da regra de producao do sımbolo de partida, e

L1(α) tem a restricao adicional que αη nao esteja no membro direito de nenhuma

regra de producao. Estas listas sao atualizadas tanto pelo codificador quanto pelo

decodificador e mantem informacoes sobre a estrutura da gramatica atual, que e

utilizada como contexto na codificacao dos sımbolos analisados, em conjunto com

I(i + 1) que e enviado ao decodificador como informacao lateral. A ideia e que se

o decodificador sabe que uma reducao acontecera, ao menos parte da informacao

contida no proximo sımbolo ja esta prasente na gramatica atual.

3.2.2 Transformada condicional de casamento de padroes

multinıvel

Uma transformada de gramatica condicional de casamento de padroes multinıvel

(conditional multilevel pattern matching grammar transform ou conditional MPM

(CMPM) grammar transform) e descrita em [14] e e baseada na transformada MPM

incondicional introduzida num artigo anterior dos mesmos autores[20]. A ideia

basica da transformada MPM e particionar a sequencia de dados em blocos e entao

em sub-blocos, de modo que repeticoes de subsequencias sao capturadas em varios

nıveis, e a versao condicional aumenta a capacidade de compressao se utilizando de

correlacoes entre a sequencia de dados e a informacao lateral.

3.2.2.1 A transformada incondicional

Uma transformada MPM tem dois parametros, I e r, e pode ser representada

por MPM(r, I), onde I define o numero de nıveis e r o tamanho dos blocos e sub-

blocos. Cada nıvel e uma particao diferente da sequencia de dados usando tamanhos

de blocos diferentes, o nıvel mais baixo e o nıvel 0 e contem os menores blocos,

compostos por um sımbolo cada; nos nıveis i = 1, . . . , I a sequencia e particionada

em blocos de ri sımbolos e se o comprimento da sequencia nao e um multiplo de ri,

o restante so ira ser processado a partir do (i− 1)-esimo nıvel, e assim por diante.

26

Page 40: emprego de gramáticas livres de contexto para a construção de um ...

Em cada nıvel os blocos distintos sao etiquetados com numeros naturais denomi-

nados tokens, tal que blocos contendo a mesma subsequencia sao representados pelo

mesmo token, os numeros representam a ordem em que eles aparecem conforme a

sequencia de dados de entrada e lida da esquerda para a direita, e cada nıvel pode ser

descrito por sua sequencia de tokens, exceto o nıvel mais baixo, cujos tokens podem

ser os proprios sımbolos do alfabeto. Como para cada bloco representado por um

mesmo token em um nıvel i correspondem r sub-blocos iguais no nıvel i−1, somente

o primeiro conjunto de r sub-blocos (correspondendo a primeira ocorrencia do token)

precisa ser mantida e representada por tokens, enquanto as proximas ocorrencias dos

mesmos blocos no nıvel i − 1 sao redundantes sao descartadas. Adicionalmente, a

primeira ocorrencia da esquerda para a direita de cada token em cada sequencia de

tokens e substituıda por s, exceto no nıvel mais baixo.

O conjunto de sequencias de tokens e entao a representacao multinıvel da sequencia

de dados original e pode ser vista como um conjunto de regras de producao de uma

gramatica, de modo similar ao ja visto nas outras transformadas acima, e e uma

representacao compacta da sequencia de dados de entrada, formada explorando os

casamentos de padroes. Assim como com as regras de producao, as sequencias

de tokens podem ser comprimidas com codificacao aritmetica. Cada sequencia

e codificada de maneira independente e, exceto pela do nıvel mais baixo, todas

comecam com o sımbolo s, entao ele nao precisa ser codificado. Utiliza-se um con-

tador c(β), β ∈ s∪1, 2, 3, . . . , f si , iniciando com c(β) = 1 para cada β ∈ s, 1 e

c(β) = 0 caso contrario, e onde f si representa o numero de vezes que o sımbolo s apa-

rece na sequencia de tokens, isto e, o numero de blocos distintos naquele nıvel. Cada

sımbolo β e entao codificado com a probabilidade c(β)/∑

α∈s,1∪2,3,...,j+1c(α), onde j e o

numero de vezes que o codificador processou o sımbolo s ate entao, e, conforme cada

sımbolo e processado, seu contador e incrementado e, se o sımbolo for s, o proximo

token na ordem natural e adicionado ao alfabeto do codigo aritmetico e o contador

c(j + 2) tambem e incrementado. No nıvel mais baixo nao e preciso levar em conta

o sımbolo s e os sımbolos podem ser codificados diretamente utilizando-se contado-

res c(β), β ∈ Σ, todos iniciando em 1, e cada sımbolo β codificado utilizando-se a

probabilidade c(β)/∑

α∈Σc(α), e incrementando seu contador.

27

Page 41: emprego de gramáticas livres de contexto para a construção de um ...

A sequencia binaria codificada pode ser construıda concatenando as sequencias de

tokens codificadas comecando (da esquerda para a direita) com a do nıvel mais alto,

seguida pelo nıvel imediatamente abaixo e assim sucessivamente ate o nıvel 0. Se o

comprimento total da sequencia de dados original e conhecido pelo decodificador, o

comprimento da sequencia de tokens do nıvel mais alto pode ser diretamente calcu-

lado e, uma vez que esta sequencia seja decodificada, pode-se calcular o comprimento

da sequencia seguinte e assim por diante. Entretanto, note que este codificador de

gramatica implica codificacao em batelada; um algoritmo de codificacao sequencial

para a transformada MPM e apresentada no artigo [21].

3.2.2.2 A transformada condicional

A versao condicional da transformada MPM (transformada CMPM) descrita em

[14] e uma adaptacao direta do esquema mostrado acima, em que, ao inves de a unica

entrada ser a sequencia de dados x, a transformada tambem recebe uma sequencia

y do mesmo comprimento de x como informacao lateral, e a entrada e tratada como

uma sequencia de pares (xi, yi) ao inves de uma sequencia simples de sımbolos. O

particionamento da entrada em blocos e sub-blocos e o mesmo, mas duas sequencias

de tokens sao geradas a cada nıvel, uma em relacao aos dados de y em que cada

bloco de y e etiquetado sequencialmente com um numero natural como token (1, 2,

3, ...) e blocos iguais recebem o mesmo token, enquanto a sequencia de tokens com

relacao a x e construıda condicionalmente a y: os blocos de x que correspondem

a blocos de y iguais sao etiquetados como uma subsequencia independente condi-

cional, tal que os numeros utilizados como tokens representam o numero de blocos

diferentes encontrados em cada subsequencia e nao na sequencia x completa como

no caso incondicional. Alem disso, a primeira vez que cada token aparece em cada

subsequencia de x e substituıda por s. Note que agora, como a etiquetagem dos blo-

cos de x e condicional a etiquetagem dos blocos de y e possıvel que blocos diferentes

de x sejam representados pelo mesmo token e tambem que s represente o mesmo

bloco de x mais de uma vez, diferentemente do caso incondicional. Note tambem

que nenhum dos tokens de y e s.

28

Page 42: emprego de gramáticas livres de contexto para a construção de um ...

Presuma que x e ytenham sido apropriadamente etiquetados no nıvel i com o

metodo descrito acima, de modo similar ao caso incondicional, no nıvel i−1th nao e

necessario manter e etiquetar os sub-blocos correspondendo a combinacoes repetidas

de blocos de x e de y, de maneira que no nıvel i − 1 so e necessario processar sub-

blocos de blocos de x no nıvel i que sejam etiquetados com o token s e os blocos de

y correspondentes.

As sequencias de tokens a cada nıvel vem, como vimos, como um par de sequencias

ou, alternativamente, podem ser interpretadas como sequencias de pares de tokens.

Como no caso incondicional, estas sao comprimidas utilizando um codigo aritmetico,

e para cada primeira ocorrencia de um token de y, o token de x correspondente

sempre sera um s e portanto este par nao precisa ser codificado. Adicionalmente,

se nos lembrarmos que a sequencia y e informacao lateral disponıvel tanto para o

codificador quanto para o decodificador, nao e necessario codificar os tokens de y

mas somente os tokens de x. Para tirar proveito da informacao lateral no codificador

de gramatica, ela tambem e utilizada para codificar condicionalmente os tokens de x

associando-se diferentes contadores cγ(β) para cada par de sımbolos (β, γ), onde β e

um token de x e γ ´r um token de y, os contadores iniciando em 1 se β ∈ s, 1 e 0

caso contrario, e entao codificando cada sımbolo β de cada par lido da sequencia de

tokens com a probabilidade cγ(β)/∑

α∈s,1∪2,3,...,j+1cγ(α), onde j e onumero de vezes que

o codificador processou o par (β, γ) ate entao, e, conforme cada par e processado,

seu contador e incrementado e, se o sımbolo codificado for s, o proximo token na

ordem natural e adicionado ao alfabeto do codigo aritmetico e o contador cγ(j + 2)

tambem e incrementado. Para o nıvel mais baixo nao e necessario levar em conta

o sımbolo s e os sımbolos podem ser condicionalmente codificados utilizando-se os

contadores cγ(β), β ∈ Σ, todos iniciando em 1, e cada sımbolo β e codificado com a

probabilidade cγ(β)/∑α∈Σ

cγ(α) e tem seu contador incrementado.

Novamente, a sequencia do codigo binario pode ser construıda concatenando-se

as sequencias de tokens de x codificadas, comecando pela do nıvel mais alto seguida

pelo nıvel imediatamente abaixo e assim por diante ate o nıvel mais baixo. O

comprimento total da sequencia de dados original x e conhecida pelo decodificador

pois e o mesmo comprimento da sequencia de informacao lateral y, entao o com

29

Page 43: emprego de gramáticas livres de contexto para a construção de um ...

primento da sequencia de tokens do nıvel mais alto pode ser facilmente calculada e,

uma vez que ela seja decodificada, o comprimento da sequencia seguinte pode ser

calculado e assim por diante.

3.3 Trabalhos posteriores

Agora partimos para uma revisao bibliografica sistematica de artigos de varios

autores que citam os artigos seminais de Yang e Kieffer ([3, 13, 14]) que foram

revisados acima. Artigos que citam todos os tres principais artigos de Yang e Kief-

fer sobre codigos baseados em gramaticas ([22, 23, 24, 25, 26]) e artigos que citam

ao menos um deles e foram publicados nos ultimos cinco anos, isto e, entre 2011

e 2015 ([27, 28, 29, 30, 31, 32, 33, 24, 25, 34, 35, 36, 37, 38, 39, 40]) foram se-

lecionados para esta revisao. Um artigo publicado em 2005 foi identificado como

uma referencia importante para varios dos artigos selecionados e traz resultados

interessantes em relacao a dificuldade de aproximar a solucao otima para o pro-

blema da menor gramatica[41] entao tambem foi incluıdo na revisao, assim como

tambem incluımos um artigo interessante reportando uma comparacao de perfor-

mance de compressao em ferramentas de compressao de documentos XML[42] que

compara abordagens baseadas em gramaticas especializadas em documentos XML

a outras ferramentas especializadas e compressores de uso geral, que aponta para a

falta de implementacoes solidas publicamente disponıveis para codigos baseados em

gramaticas.

3.3.1 Indiretamente ligados aos codigos baseados em gramaticas

Alguns dos trabalhos que citam os artigos de Yang e Kieffer nao tratam direta-

mente de codigos baseados em gramaticas ou suas aplicacoes, mas investigam areas

relacionadas, complementares, ou de algum modo similares. Fazemos uma breve re-

visao destes abaixo, antes de partir para uma revisao mais detalhada da bibliografia

que trata diretamente dos codigos baseados em gramaticas.

30

Page 44: emprego de gramáticas livres de contexto para a construção de um ...

3.3.1.1 Codificacao e Decodificacao Interativa

A maioria dos artigos que citam todos os tres artigos de Yang e Kieffer sao tra-

balhos de Yang e co-autores apresentando o arcabouco teorico da Codificacao e

Decodificacao Interativa (Interactive Encoding and Decoding – IED) [22, 23, 24, 25].

A IED e uma proposta de um esquema para codigos de compressao quase sem

perdas com informacao lateral somente para o decodificador, que e conceitualmente

similar a codificacao Slepian-Wolf, exceto pelo fato de que a IED utiliza de um canal

de retorno entre o codificador e o decodificador e a codificacao e decodificacao da

sequencia de dados e feita diversas vezes, em iteracoes, em que o encoder utiliza

uma fluxo de bits realimentado do decodificador a partir do resultado da iteracao

anterior para produzir uma codificacao melhor na iteracao atual, e o decodificador

utiliza a informacao lateral para decodificar a sequencia codificada e produzir a

realimentacao para a proxima iteracao de tal modo que sucessivas estimativas ou

aproximacoes da sequencia de dados original sao obtidas pelo decodificador ate que

uma seja tida como suficientemente correta[23].

Os autores tambem demonstraram que qualquer codigo de compressao sem perdas

classico com informacao lateral disponıvel tanto para o codificador quanto para o

decodificador pode ser adaptado ao esquema IED[25], e as citacoes aos artigos de

Yang e Kieffer sao feitas muito rapidamente em relacao a certas propriedades que

estao neles demonstradas para codigos baseados em gramaticas e cuja existencia e

necessaria para analise teorica feita da IED.

3.3.1.2 Tecnicas de compressao relacionadas mas nao baseadas em gramaticas

Alguns artigos investigam outras tecnicas de compressao que sao de algum modo

relacionadas aos codigos baseados em gramaticas ou que usam esquemas similares

ou analogos em alguns pontos aos algoritmos propostos para codigos baseados em

gramaticas e citam os artigos de Yang e Kieffer neste contexto.

Doshi e Gandhi[30] demonstram uma combinacao de duas tecnicas (processamento

de multiplos bits simultaneos no ciclo de renormalizacao e escalamento da frequencia

31

Page 45: emprego de gramáticas livres de contexto para a construção de um ...

total para uma potencia de 2) para reduzir bastante o tempo de execucao de im-

plementacoes de codigos aritmeticos tanto na codificacao quanto na decodificacao,

e notam que codigos baseados em gramaticas podem ter a execucao do codificador

de gramatica otimizada.

Zhang, Yang e Kieffer[33] codificam arvores binarias utilizando suas representacoes

por grafos acıclicos diretos (direct acyclic graph – DAG) mınimos. Os autores notam

que ha algoritmos em tempo linear para a obtencao do DAG mınimo de uma arvore

binaria, que pode ser codificado em uma sequencia binaria utilizando um esquema

similar ao utilizado para codificar as gramaticas com codificacao enumerativa como

mostrado na prova do Teorema 6.

Hu e Yang[37] desenvolvem um algoritmo para reduzir o tempo de codificacao

do HEVC (High Efficiency Video Coding/H.265) utilizando deteccao de amostras

atıpicas para acelerar a selecao do modo intra e um aprimoramento da codificacao

aritmetica que usa indicadores de amostras atıpicas numa imagem binıvel pois ela

e altamente relacionada as decisoes de divisao da unidade de codificacao e escolha

do modo intra que precisam ser codificadas juntamente com os dados da imagem

de vıdeo, e usam um esquema de arvore que se parece com um algoritmo MPM

bidimensional para codificar a imagem binıvel de amostras atıpicas.

3.3.1.3 Tecnicas de compressao nao relacionadas

Ha tambem artigos que nao se relacionam diretamente com codigos baseados em

gramaticas mas os citam como exemplos de esquemas de codificacao e compressao

existentes.

Debowski[28] conduz uma investigacao empırica sobra a conjectura de Hilberg so-

bre a linguagem natural, que afirma que a informacao mutua de dois blocos longos

adjacentes de texto natural cresce como uma potencia do comprimento do bloco.

Ele argumenta que utilizando um codigo de compressao universal pode-se obter

um limite superior para o expoente em nβ onde n e o comprimento do bloco e a in-

formacao mutua e conjecturada proporcional a nβ. Codigos baseados em gramaticas

sao citados como exemplos de codigos universais, entre outros, e o autor escolhe

32

Page 46: emprego de gramáticas livres de contexto para a construção de um ...

introduzir um novo codigo de compressao baseado numa mistura de cadeias de Mar-

kov adaptativas, que ele compara empiricamente ao LZ77 e obtem melhores taxas

de compressao e portanto um limite mais justo para o valor de β.

Jain e Bansal[31] investigam certos cenarios para codigos LZ de janela deslizante

e incluem um dos artigos de Yang e Kieffer[3] na bibliografia, mas ele nao e citado

no texto do artigo.

Kuzuoka e Watanabe[34] estudam a codificacao de comprimento variavel na co-

dificacao Slepian-Wolf e citam brevemente o artigo de Yang e Kieffer que inclui

informacao lateral[14] para fazer a distincao de que a investigacao naquele artigo

e em outros se refere a codificacao sem perdas como codificacao de erro zero, en-

quanto neste artigo os codigos tratados sao fracamente sem perdas, isto e, que tem

a probabilidade de erro diferente de zero mas assintoticamente indo a zero.

O artigo de Zheng e Yang sobre codificacao causal de vıdeo[35] descreve um al-

goritmo para codificar quadros de vıdeo modelando cada quadro como uma fonte

de informacao estacionaria, utilizando todos os quadros anteriores na codificacao do

quadro atual (isto e, considerando multiplas fontes) e minimizando a distorcao total

para todas as fontes. O algoritmo gera para cada quadro codificado uma sequencia

de ındices utilizando todas as fontes de informacao disponıveis, e entao codifica essa

sequencia utilizando um codigo de comprimento fixo para a transmissao, mas menci-

ona que esquemas de codigos de comprimento variavel poderiam ser utilizados como

alternativas, e cita codigos baseados em gramaticas como um exemplo.

3.3.2 Codigos baseados em gramaticas e suas aplicacoes di-

retas

3.3.2.1 Avaliando aplicacoes diretas de compressao baseada em gramaticas

Revisamos um par de artigos que avaliam aplicacoes diretas de codigos de com-

pressao baseados em gramaticas e comparam a sua performance as de outras ferra-

mentas disponıveis.

33

Page 47: emprego de gramáticas livres de contexto para a construção de um ...

Wang et al [38] descrevem em seu artigo uma aplicacao bastante direta de codigos

baseados em gramaticas em sistemas de detecao de intrusao. Eles empregam com-

pressao sem perdas para medir a quantidade de informacao (no mesmo espırito do

uso que Debowski faz da compressao sem perdas[28]) tal que se uma amostra adi-

cionada a um corpo de referencia representativo afeta significativamente o tamanho

total dos dados comprimidos (em relacao ao tamanho dos dados de referencia com-

primidos por si so), a amostra pode ser considerada anomala.

E requerido que o codigo de compressao nao utlize janelas deslizantes para que os

dados de todo o corpo de referencia seja de fato utilizado na compressao da amostra

adicionada, e tambem que nao possua alfabeto fixo de modo que o codigo se adapte

melhor a diferentes tipos de fontes de dados tais como registros de sistema e de

aplicacoes ou tracos de execucao, e nao deve haver nenhuma restricao quanto aos

dados. Codigos baseados em gramaticas sao considerados a escolha mais adequada,

dadas estas condicoes, para o codigo de compressao utilizado, e os autores adotam

a transformada gulosa de Yang e Kieffer[13] mas nao o codificam a gramatica, pois

a taxa de compressao nao e um objetivo direto nesta aplicacao e os autores desejam

que seja preservada a relacao entre a estrutura dos dados e a hierarquia, alem de

facilitar a analise manual de anomalias por ventura detectadas.

Os resultados alcancados com o uso do codigo baseado em gramaticas sao posi-

tivos e favoraveis na comparacao com metodos estatısticos tradicionais ou baseados

em cadeias de Markov; quatro diferentes cenarios foram testados (analise de tex-

tos, detecao de acesso por terceiros a linha de comando de um usuario, detecao de

intrusao utilizando sequencias de chamadas de sistema e detecao de erros usando

registros de depuracao de alta granularidade da execucao de saltos num programa)

e o algoritmo baseado em gramaticas obteve boa performance em todos os casos,

enquanto todos os metodos concorrentes falharam em ao menos alguns. Os au-

tores apontam como sugestoes para investigacao futura algumas modificacoes no

algoritmo que permitiriam nao so a detecao de anomalias como tambem a sua clas-

sificacao.

34

Page 48: emprego de gramáticas livres de contexto para a construção de um ...

Sakr[42] fez um levantamento e testes comparativos das ferramentas disponıveis

para compressao sem perdas de documentos XML. Os testes incluıram tanto com-

pressores sem perdas de uso geral (gzip, bzip2 e PPM) quando ferramentas especi-

alizadas em compressao de XML que sejam livremente disponıveis e independentes

de esquema. No total foram comparados nove compressores, dos quais seis espe-

cializados em compressao de documentos XML –entre os quais dois sao codigos

baseados em gramaticas (Exalt e AXECHOP). Os testes avaliaram a estabilidade,

taxa de compressao e tempo de compressao e descompressao para um corpo grande

e diversificado de documentos XML.

O autor observou que ambos os compressores baseados em gramaticas tiveram

muito baixa estabilidade, e frequentemente falhavam para descomprimir correta-

mente os documentos, tanto que em muitos dos resultados compilados os dados

referentes a estes compressores tiveram de ser excluıdos por nao haver representa-

tividade para comparacao com as outras opcoes. Nos comentarios finais do artigo,

o autor nota que tanto quanto se foi possıvel saber nao ha implementacoes solidas

e confiaveis de compressores de documentos XML baseados em gramaticas, e esta

continua sendo uma area de pesquisa aberta.

3.3.2.2 Novos codigos baseados em gramaticas e extensoes para fins es-

pecıficos

A seguir discutimos artigos que descrevem novos codigos baseados em gramaticas

e extensoes de algoritmos anteriores para adaptacao de codigos a casos especıficos.

Kieffer e Yang[26] introduzem um codigo de compressao de refinamento sem per-

das baseado em gramaticas. Codigos de refinamento podem ser vistos como um

caso especial de codigos com informacao lateral em que a informacao lateral y e

uma aproximacao grosseira da sequencia de dados original x (isto e, uma versao em

baixa resolucao) que o decodificador utiliza em conjunto com o codigo binario rece-

bido para reconstruir a sequencia original; tambem podem ser vistos como codigos

de camadas diferenciais. De modo mais geral, varios passos de refinamento podem

ser empregados em uma codificacao progressiva sem perdas que produz no deco-

dificador uma sequencia de aproximacoes progressivas em que a cada passo uma

35

Page 49: emprego de gramáticas livres de contexto para a construção de um ...

representacao cada vez mais proxima dos dados originais e obtida, ate que seja ob-

tida uma copia fiel. A abordagem baseada em gramaticas apresentada pelos autores

constroi uma sequencia binaria B(x|y) em duas partes, primeiro codificando uma

maneira de construir a gramatica Gy (que representa y) dado y em B(Gy|y) e entao

codifica uma sequencia B(Gx|Gy) instruindo como obter a gramatica Gx que re-

presenta x a partir de Gy, e Gx pode ser chamado um refinamento de Gy (ou, ao

contrario, Gy um engrossamento de Gx). A sequencia de dados original x pode entao

ser obtida realizando-se as substituicoes paralelas usando as regras de producao de

Gx.

Para tornar a operacao de refinamento de Gy para Gx algo direto, os autores

restringem a estrutura das gramaticas utilizadas criando conjuntos parametrizados

de gramaticas que impoe certas estruturas as arvores de derivacao das gramaticas de

modo que tanto Gy quanto Gx compartilham da mesma estrutura em suas arvores

de derivacao. Esta abordagem e emprestada dos codigos estruturados baseados em

gramaticas tambem introduzidos por Yang e Kieffer que codificam separadamente a

estrutura e os dados das gramaticas no que eles chamam de gramatica estrutural e

gramatica representativa, respectivamente[43]. Um conjunto de gramaticas Gn pode

ser composto fixando um parametro β ≥ 3 e incluindo todas as gramaticas livres

de contexto G tal que N(G) ⊂ 2, 3, . . . , n, n e o sımbolo de partida (a raiz da

arvore de derivacao), T (G) = 1 e para cada nao-terminal i ha uma unica regra

de producao i → (i1, i2, . . . , ik) tal que k ≥ 2, each ij > 1 e um nao-terminal de G,∑kj=1 ij = i e i/ij ≤ β, j = 1, 2, . . . , k.

Os conjuntos definidos acima podem ser vistos como conjuntos de gramaticas

G que servem como modelos que podem ser utilizados para construir gramaticas

Gu ou (G)u representando qualquer sequencia u de comprimento n. Em seguida,

os autores mostram passos para construir estas gramaticas; cada sımbolo de u e

utilizado para etiquetar as n folhas da arvore de derivacao de G, e seus vertices

internos sao etiquetados com subsequencias de u formadas pela concatenacao das

etiquetas de seus filhos. Pode-se entao tomar os sımbolos nas etiquetas das folhas

como terminais de Gu, e nao -terminais sao distribuıdos aos vertices internos tal que

aqueles etiquetados com a mesma subsequencia de u recebem o mesmo nao-terminal,

36

Page 50: emprego de gramáticas livres de contexto para a construção de um ...

de modo que o numero de nao-terminais e o numero de diferentes subsequencias de

u nas etiquetas. Claramente a etiqueta da raiz da arvore de derivacao sera a propria

sequencia u, que e substituıda pelo sımbolo de partida. A ideia defendida pelos

autores e que pode-se codificar uma gramatica estrutural G∗ adequada que pode ser

transformada tanto na gramatica representativa Gy quanto na Gx; de modo que a

gramatica estrutural pode ser codificada e, com a versao em baixa resolucao (ou

informacao lateral) y, ela especifica univocamente Gy (B(Gy|y)) e, por sua vez, so

se necessita codificar um mapeamento dos nao-terminais de Gy aos de Gx –o que

sempre sera possıvel pois ambos compartilham o mesmo comprimento n e sempre

sera unico pois elas compartilham a mesma estrutura G∗– tal que utilizando Gx o

decodificador pode obter o refinamento, ou seja, a sequencia original x.

E demonstrado que num conjunto Gn(A) de gramaticas representando sequencias

do conjunto An (isto e, sequEncias de comprimento n cujas entradas vem do alfabeto

A) ha no maximo C√n log2 n gramaticas distintas representando cada sequencia, onde

C e uma constante. Isto segue do Lema 1, cuja prova se encontra em[43] e nao

estao incluıdos em [26] passos para codificar em uma sequencia binaria Bn(G) uma

gramatica estrutural G. Entretanto, podemos ligar a segunda assercao do Lema

1 ao [43, Th. 1], mas a primeira assercao nao se encontra naquele artigo. Na

realidade, este outro artigo[43] trata de um problema ligeiramente diferente pois nele

se pretende codificar uma gramatica representativa dada uma gramatica estrutural

como informacao lateral, enquanto na primeira parte da sequencia codificada binaria

em [26] o objetivo e codificar a gramatica estrutural dada uma sequencia como

informacao lateral, isto e, B(Gy|y). Pode ser que um caso seja facilmente convertido

para uso no outro, mas esta nao e uma analise que tentamos fazer neste momento.

Lema 1. [26, Lem. 1] Seja n qualquer inteiro ≥ 2. Entao

• para cada G ∈ Gn, ha uma sequencia binaria Bn(G) de comprimento |Bn(G)| =

4⌊β3/2

√n⌋(1 + dlog2 ne) tal que Bn(G1) 6= Bn(G2) sempre que G1, G2 sao

gramaticas distintas em Gn;

• para cada conjunto finito nao-vazio A e cada gramatica G ∈ Gn(A), |G| ≤

72β2(|A|+ 2)2 log2(|A|+ 2)(n/log2 n).

37

Page 51: emprego de gramáticas livres de contexto para a construção de um ...

Um metodo para obter a sequencia binaria B(Gx|Gy) e entao mostrado pela

prova do Teorema 9, que e reproduzido a seguir:

Teorema 9. [26, Teo. 2] Seja n qualquer inteiro ≥ 2. Ha um mapeamento

(G1, G2) → B(G1|G2) de R(Gn(A1),Gn(A2)) ao conjunto de sequencias binarias

nao-vazias como segue: i) para cada (G1, G2) ∈ R(Gn(A1),Gn(A2)), B(G1|G2) ≤

H(G1|G2) + Jn; e ii) sempre que (G1, G2) e (G′1, G

′2) em R(Gn(A1),Gn(A2)) satis-

fazem G2 = G′2 e G1 6= G′

1, a sequencia B(G1|G2) nao e um prefixo da sequencia

B(G′1|G′

2), onde R(Gn(A1),Gn(A2)) e o conjunto de todos os pares (G1, G2) em que

G2 e um engrossamento de G1 e G1 ∈ Gn(A1), G2 ∈ Gn(A2), e Jn e definido como

Jn , 72β2(3 + dlog2 |A1|e)(|A1|+ 2)2 log2(|A1|+ 2)(n/log2 n).

Omitimos aqui a prova (que pode ser consultada em [26], assim como a derivacao

da entropia condicional H(G1|G2)) e descrevemos brevemente como e formada a

sequencia B(Gx|Gy) propsota pelos autores. Note que se presume que os alfabetos

das gramaticas Gy e Gx ou sao iguais ou que o de Gy e menor que o de Gx, o que

faz sentido se vemos y como uma versao em baixa resolucao de x. B(Gx|Gy) e uma

concateacao B1B2B3B(s(U1))B(s(U2)) . . . B(s(Uj)):

1. B1 de comprimento |Gx| instrui como construir, usando Gy, a estrutura da

sub-arvore T ∗ da arvore de derivacao T de Gx (T∗ e obtida percorrendo a

arvore de derivacao em largura e podando os vertices filhos e as folhas sempre

que um nao-terminal repetido e encontrado);

2. B2 de comprimento K dlog2 |Ax|e, K sendo o numero de folhas de T ∗ que

tambem sao folhas de T , especifica quais sımbolos terminais de Gx serao assi-

nalados a cada uma das K folhas;

3. B3 de comprimento |Gx| −K com as frequencias dos nao-terminais nos mem-

bros direitos das regras de producao de Gx;

4. cada B(s(U)) e uma codificacao enumerativa de s(U), onde cada s(U) e uma

sequencia de sımbolos de Gx obtida percorrendo as folhas de T ∗ em profun-

didade para a qual o nao-terminal U e assinalado no vertice correspondente

da arvore de derivacao de Gy. Note que todas as permutacoes de cada s(U)

podem ser computadas utilizando Gy, B1, B2 e B3.

38

Page 52: emprego de gramáticas livres de contexto para a construção de um ...

Yang e Kieffer[26] nao especificam exatamente como podem ser codificados os

componentes B1, B2, . . . mas codificacoes apropriadas podem ser facilmente deduzi-

das, B1, por examplo pode ser codificado percorrendo em largura a sub-arvore T ∗,

ignorando a raiz, e codificando um bit 1 se o vertice atual e interno ou um bit 0

caso contrario. A sequencia binaria codificada completa transmitida para o refina-

mento e entao a concatenacao B(Gy|y)B(Gx|Gy), e os autores mostram que o limite

para a redundancia maxima para tal codigo de refinamento baseado em gramaticas

e O( 1log2 n

).

Debowski[27] escreve sobre uma explicacao para a distribuicao das palavras em

linguagens naturais, que e be descrita pela lei de Zipf-Mandelbrot (a frequencia das

palavras e uma lei de inverso de potencia do posto das palavras) e uma versao desta

lei chamada lei de Herdan, que afirma que o numero de palavras distintas e uma lei

de potencia do comprimento do texto. E esta segunda versao que Debowski busca

explicar, e para isso ele busca provar outra proposicao, que afirma que um texto

de comprimento n descrevendo nβ fatos independentes em uma maneira repetitiva

deve conter ao menos nβ/log n, presumindo β ∈ (0, 1).

Para atingir seu objetivo, Debowski escolhe utilizar um codigo baseado em gramaticas

pois sao eficientes na detecao de limites de palavras (tomando palavras nao em sen-

tido estrito, contando expressoes como palavras, como por exemplo New York) e o

numero de nao-terminais numa gramatica mınima pode ser tomado como um indi-

cador para o numero de palavras distintas no texto que ela representa. Ele define

uma classe de transformadas de gramatica codigos baseados em gramaticas que ele

chama admissivelmente mınimos. Transformadas de gramatica codigos baseados

em gramatica admissivelmente mınimos sao aqueles para os quais |B(Γ(W ))| ≤

|B(G)| para todas as gramaticas G que representam w, onde Γ e a transformada de

gramatica e B e o codificador de gramatica; alem disso, a estrutura do codificador

de gramatica e definida em uma forma especıfica. Classes de processos estocasticos

tambem sao definidos para modelar a producao de fatos e textos, e tres teoremas

sao provados utilizando as classes definidas para mostrar uma motivacao para a

conjectura de Hilberg (veja [28]), como esta conjectura implica a lei de Herdan e

explicacoes para essas leis a partir da proposicao introduzida por Debowski.

39

Page 53: emprego de gramáticas livres de contexto para a construção de um ...

Analises interessantes de codigos baseados em gramaticas sao feitas no artigo,

entretanto, apesar de serem utilizadas propriedades de gramaticas mınimas, ele nao

introduz resultados que possam ser utilizados para o aprimoramento de algoritmos

praticos para a obtencao de transformadas de gramatica mınimas.

Dorier et al [29] introduzem uma abordagem duplamente original: uma nova mo-

delagem de comportamento de entrada/saıda baseado em gramaticas formais e uma

extensao inovadora de codigos baseados em gramaticas para uso como preditores. Os

autores buscam solucionar o problema de que em aplicacoes de computacao de alta

performance E/S e um gargalo, e propoe modelar tanto o acesso temporal quanto

espacial de E/S com uma abordagem contınua, rapidamente convergente, adapta-

tiva, de baixo nıvel (que nao requeira modificacoes no codigo de aplicacoes ou de

bibliotecas de alto nıvel) e agnostica em relacao a aplicacao. Outras tecnicas pre-

viamente empregadas consistem principalmente em metodos estatısticos tais como

modelos ocultos de Markov ou modelos auto-regressivos integrados de media movel

e, de acordo com os autores, abordagens baseadas nestes metodos nao foram, ate

o momento, capazes de preencher todos os requisitos dispostos acima. Os autores

tambem notam que metodos estatısticos sao mais adequados para modelar processos

estocasticos em que ha aleatoriedade, enquanto aplicacoes de computacao de alto

desempenho sao, por sua natureza, altamente determinısticas. Isto torna uma abor-

dagem baseada em gramaticas muito interessante, pois gramaticas podem capturar

a natureza determinıstica e hierarquica da execucao de programas e operacoes de

E/S.

Chamadas de funcoes de E/S de baixo nıvel sao empacotadas e instrumentadas

para registrar o traco das pilhas das chamadas, das quais e mantido um dicionario

em que diferentes pilhas sao assinaladas a sımbolos de contexto distintos, que podem

ser relacionados a tamanhos de acessos e cujas transicoes podem ser relacionadas

a evolucao da posicao de leitura ou escrita e o tempo entre chamadas de E/S. O

algoritmo proposto pelos autores utiliza uma abordagem escalonada em que uma

gramatica principal modela a sequencia de sımbolos de contexto e gramaticas locais

modelam sequencias de tamanhos e saltos nas posicoes de acessos. O tempo entre

acessos nao e modelado por uma gramatica, mas por algumas estatısticas basicas

40

Page 54: emprego de gramáticas livres de contexto para a construção de um ...

que permitem um agendamento eficiente (tempos mınimo, maximo e medio entre

acessos); a mesma abordagem estatıstica e utilizada se o comprimento da gramatica

local se torna maior que 24 sımbolos. As aplicacoes consideradas nos testes nao

acessam mais de um arquivo simultaneamente, entao este caso nao foi modelado no

algoritmo.

A transformada de gramatica introduzida pelos autores para gerar as gramaticas

locais e a principal e uma extensao do algoritmo Sequitur (que e bastante simi-

lar ao Sequitur Modificado de Yang e Kieffer[3] e foi brevemente descrito na Secao

3.2) em que certos sımbolos terminais sao marcados como preditores de acordo com

operacoes de atualizacao e descoberta e duas novas restricoes relativas a marcacao

de preditores: nao-terminais so podem ser marcados como preditores se o membro

direito de sua regra de producao contem ao menos um preditor, e um sımbolo no

membro direito de uma regra de producao (exceto a do sımbolo de partida) so pode

ser um preditor se o seu membro esquerdo e um preditor no membro direito de

outra regra de producao. A operacao de atualizacao de preditores e feita sempre

que um novo sımbolo e lido da entrada; todos os sımbolos terminais marcados como

preditores sao desmarcados se nao coincidem com o novo sımbolo, as restricoes aos

preditores sao aplicadas, e entao os preditores que coincidem com o sımbolo lido sao

tambem desmarcados e sao agora marcados como preditores os sımbolos seguintes

na sequencia nos membros direitos, a nao ser que o preditor seja o ultimo sımbolo

de uma regra de producao, caso em que os sımbolos seguintes ao nao-terminal cor-

respondente em outras regras de producao serao marcados. Se nenhum sımbolo e

preditor (isto e, nenhum preditor coincidiu com o sımbolo lido e todos foram des-

marcados), e feita a operacao de descoberta em que todos os sımbolos iguais ao

lido sao marcados como preditores, e caso o sımbolo apensado tenha formado um

digrama que seja substituıdo por um nao-terminal na aplicacao das restricoes do

Sequitur, somente sımbolos na regra de producao correspondente serao marcados

como preditores.

Os resultados reportados no artigo sao muito bons, com acertos de predicoes

entre 79.5% e 100% nos cenarios de teste, e isto demonstra que gramaticas podem

codificar eficientemente padroes de sequencias, rapidamente convergindo o modelo

41

Page 55: emprego de gramáticas livres de contexto para a construção de um ...

a um regime estacionario sem nenhum conhecimento previo da estrutura ou da

estatıstica dos dados, o que e por si so uma confirmacao empırica das qualidades

defendidas por Yang e Kieffer para codigos de compressao baseados em gramaticas.

Se tanto a extensao do Sequitur apresentada quanto a abordagem escalonada sao

bastante especıficas para esta aplicacao, nao deixam de ser excelentes exemplos de

usos possıveis para transformadas de gramatica.

Zhang, Yang e Kieffer[32] estudam o problema da compressao sem perdas de

arvores binarias utilizando codigos baseados em gramativas. A abordagem geral

adotada e muito similar ao caso generico: uma transformada de gramatica e aplicada

para obter uma representacao compacta da arvore binaria original, que em seguida

e comprimida e codificada numa sequencia binaria. A originalidade da abordagem

esta no fato de que o codigo baseado em gramaticas apresentado pretende comprimir

a informacao de uma estrutura e nao de um conteudo, propriamente. Isto e feito

construindo uma gramatica tal que sua arvore de derivacao, retiradas as etiquetas

dos nos, seja igual a arvore que se deseja comprimir. Esta ideia e de certo modo

relacionaa aos codigos estruturados baseados em gramaticas e abordagens similares

investigados Por Yang e Kieffer[43, 26], mas nestes o objetivo nao e comprimir uma

estrutura, as estruturas sao utilizadas como auxiliares na compressao dos dados.

Um algoritmo que codifica univocamente os isomorfismos de uma arvore binaria

nao-trivial e descrito pelos autores. Ele se inicia por uma etiquetagem dos vertices

da arvore t talque a raiz e etiquetada 0 e todas as folhas sao etiquetadas T , e entao

a arvore e percorrida em largura e os vertices restantes sao etiquetados de modo

que, se a sub-arvore com raiz no vertice atual e igual a sub-arvore com raiz em um

vertice que ja foi etiquetado, a mesma etiqueta e aplicada, caso contrario o proximo

numero natural nao utilizado e aplicado como a etiqueta. Os inteiros utilizados como

etiquetas podem ser vistos como o conjunto de nao-terminais de uma gramatica Gt,

e T como o conjunto de terminais. Se N e a cardinalidade do conjunto de todas as

sub-arvores distintas de t, havera N−1 sımbolos nao-terminais na gramatica e o seu

conjunto sera 0, 1, . . . , N − 2. Adicionalmente, a arvore etiquetada sera a arvore

de derivacao de Gt. O proximo passo e codificar Gt em uma sequencia binaria, e

aqui os autores se inspiram em abordagens anteriores e utilizam um procedimento

42

Page 56: emprego de gramáticas livres de contexto para a construção de um ...

similar ao utilizado para codificar a gramatica no algoritmo hierarquico de Yang

e Kieffer[13], descrito na Secao 3.2.1, e ao utilizado em seu artigo seminal[3]. Os

membros direitos das regras de producao –todos com comprimento 2– sao listados

em uma sequencia S(t); as primeiras ocorrencias da esquerda para a direita dos

sımbolos nao-terminais sao removidas para obter uma nova lista S1(t); o numero de

nao-terminais e codificado em B1 na forma de N − 2 zeros seguidos de um bit 1,

B2 tem comprimento 2N − 2 (isto e, o comprimento de S(t)) e codifica as posicoes

da primeira ocorrencia de cada nao-terminal em S(t), B3 codifica as frequencias

dos nao terminais em N − 1 sequencias alternadas de zeros e uns, a ultima tendo

comprimento 1 (a frequencia de T pode ser computada usando a informacao de B1)

e B4 representa S1(t) utilizando uma codificacao enumerativa.

Uma extensa prova de que tal codigo e universal e otimo para certas classes de

arvores binarias e incluıda no artigo, mas a omitimos aqui nesta revisao

Maruyama et al [36] desenvolvem uma versao contınua de um algoritmo para um

codigo baseado em gramaticas e seu artigo e uma continuacao de trabalhos anteriores

do mesmo grupo. Sakamoto[44] introduziu o algoritmo Levelwise-RePair inspirado

no Re-Pair de Larsson and Moffat[45] (que e muito simples mas de difıcil analise[46])

com a intencao de igualar o melhor resultado conhecido para a taxa de aproximacao

as gramaticas mınimas –O(log2(n/g∗)), onde n e o comprimento da entrada e g∗

e o menor tamanho possıvel para uma gramatica que o representa– usando um

algoritmo simples que nao demande a construcao de arvores de sufixos (que nao

sao eficientes em uso de memoria) e com a mesma complexidade de espaco do Re-

Pair, que como outros algoritmos depende linearmente do comprimento da entrada.

Sakamoto et al [47] entao buscam desenvolver um algoritmo com execucao em tempo

linear e espaco sublinear baseado no menor ancestral comum em arvores binarias

balanceadas; este algoritmo foi posteriormente denominado LCA (de lowest common

ancestor) e e o algoritmo adaptado para o caso contınuo por Maruyama et al no

que foi batizado de algoritmo Online LCA no artigo que ora revisamos.

Os autores primeiro simplificam o algoritmo LCA e entao fazem a extensao para

o caso contınuo. Seu objetivo e minimizar o numero de nao -terminais na gramatica

43

Page 57: emprego de gramáticas livres de contexto para a construção de um ...

final gerada pela substituicao de pares por nao-terminais. Nota-se tambem que os

autores restringem as gramaticas de modo que suas regras de producao sempre tem

comprimento 2. Sao introduzidas tres regras de decisao para a substituicao de pares:

1. Regra do par repetitivo: Se uma sequencia x contem uma subsequencia de

repeticao maxima x [i, j] = ak, isto e, uma subsequEncia de comprimento

k = j−i+1 emque o sımbolo a e repetido k vezes tal que x [i− 1] , x [j + 1] 6= a,

uma regra de producao A → aa e gerada e x [i, j] e substituıda por outra

repeticao Ak/2 para k par ou x [i, j − 1] e substituıda por A(k−1)/2 para k

ımpar.

2. Regra do par mınimo: Presuma que todos os sımbolos sao representados por

inteiros, se uma subsequencia aiajak e tal que j < i, k entao aj e chamado

mınimo e o par ajak e substituıdo por um nao-terminal.

3. Regra do par maximo: Novamente presuma que todos os sımbolos sao repre-

sentados por inteiros e, alem, que sao folhas ordenadas em uma arvore binaria

T ordenada, completa e com raiz, se uma subsequencia aiajakal e tal que

i < j < k < l or i > j > k > l, se a altura do menor ancestral comum do

par formado por aj e ak e maior que a altura do menor ancestral comum dos

outros pares possıveis, isto e, lca(j, k) > lca(i, j), lca(k, l), entao o par do meio

ajak e um maximo e substituiıdo por um nao-terminal.

Conforme os dados sao lidos para a compressao, o algoritmo sempre avalia as

regras para decidir se o par x[i, i + 1] ou o par x[i + 1, i + 2] sera substituıdo.

A prioridade das regras e a mesma da ordem que elas foram listadas, para evitar

ambiguidade na decisao; primeiro o algoritmo verifica se x[i, i+1] ou x[i+2, i+3] sao

pares repetitivos e, se algum deles for, o par x[i, i+ 1] e substituıdo; caso contrario

se x[i+1, i+2] for repetitivo ele e substituıdo. Se nenhum e repetitivo, verifica-se se

x[i, i+1] e um par mınimo ou maximo, e caso positivo ele e substituıdo, caso contrario

verifica-se o mesmo em relacao ao par x[i+1, i+2] que, caso positivo, e substituıdo.

Se nenhuma das regras e verificada positivamente, x[i, i + 1] e substituıdo. Sempre

que e feita uma substituicao uma nova regra de producao e adicionada a gramatica,

se necessario. Quando o final da sequencia de entrada e alcancado, o algoritmo

44

Page 58: emprego de gramáticas livres de contexto para a construção de um ...

passa a ler a sequencia modificada pelas substituicoes novamente desde o inıcio e

continua avaliando os pares conforme as regras e fazendo novas substituicoes, ate

que o processo se completa quando a sequencia original se reduz a um unico sımbolo,

que e tomado como o sımbolo de partida da gramatica.

A versao contınua e entao apresentada pelos autores, introduzindo o uso de no

maximo h filas q1, q2, . . . , qh que contem segmentos da sequencia que corresponde a

cada uma das iteracoes do laco externo do algoritmo em batelada descrito acima. O

numero maximo de filas h e portanto limitado a O(log2 n), assim como o numero de

iteracoes do laco. No algoritmo contınuo, todas as filas quando sao criadas ja contem

um sımbolo fictıcio que nao faz parte do alfabeto e nem e admissıvel como sımbolo

nao-terminal; os sımbolos da sequencia a ser comprimida sao entao lidos sequenci-

almente e enfileirados em q1. Se, apos o enfileiramento de um sımbolo, len(q1) ≥ 5,

entao o mesmo procedimento do algoritmo em batelada e utilizado para decidir se

q1[1, 2] ou q1[2, 3] sera susbstituıdo por um nao-terminal. Com a decisao tomada,

q1[0] (isto e, o primeiro sımbolo de q1) e desenfileirado e descartado (na primeira vez

sera o sımbolo artificial, depois sera um sımbolo ja substituıdo) e entao, se q1[1, 2]

sera substituıdo, q1[1] e desenfileirado e um nao-terminal apropriado e enfileirado

em q2, enquanto se q1[2, 3] for substituıdo, q1[1] e q1[2] sao desenfileirados, e q1[1] e

enfileirado em q2 seguido por um nao-terminal apropriado. Note que no final desta

operacao ou o conteudo inicial de q1[2] ou de q1[3] estarao na frente da fila, em q1[0],

e podem ser utilizados na avaliacao das regras mas serao descartados pois ja sao re-

presentados por um nao-terminal em q2. Essas operacoes sao feitas recursivamente

de modo que quando len(q2) ≥ 5 um para sera substituıdo e um nao-terminal enfi-

leirado em q3, e assim por diante ate que todos os sımbolos da sequencia de dados

de entrada tenham sidos processados e todos os sımbolos restantes em filas sao pa-

reados e substituıdos por nao-terminais apropriados ate que um unico nao-terminal

ira resultar da ultima fila utilizada (que sera, no maximo, a fila qh).

Os autores entao propoe um esquema simples para codificar a gramatica obtida,

utilizando a ideia da arvore parcial de derivacao (utilizada por Rytter[48] e tambem

por Yang e Kieffer[26]r). Uma arvore parcial de derivacao e construıda de modo

similar a arvore completa de derivacao, com a diferenca que os nos representando

45

Page 59: emprego de gramáticas livres de contexto para a construção de um ...

nao-terminais repetidos sao podados e deixados como folhas; deste modo, o numero

de nos internos e o numero de nao-terminais na gramatica e, como neste caso a arvore

e binaria, o numero de folhas e numero de nao-terminais mais um. Os autores propoe

entao codificar esta arvore parcial a percorrendo em pos-ordem e indicando com um

bit para cada no se ele e um no interno ou uma folha, e construindo uma sequencia

das etiquetas das folhas que pode ser codificada em (|N(G)|+1) dlog2(|N(G)|+ |Σ|)e

bits.

Os resultados de testes apresentados pelos autores mostram que para conjuntos

de dados repetitivos o Online LCA obtem melhor taxa de compressao e e uso de

memoria do que o LZW, gzip e bzip, enquanto tanto o Re-Pair e o LZMA obtem

melhores taxas de compressao mas com uso de memoria muito maior do que o do

Online LCA.

Yamagiwa e Sakamoto[39] fazem ainda uma extensao do algoritmo Online LCA

para uma implementacao em FPGA com regras de producao estaticas. Dados de

treino comprimidos pelo Online LCA geram uma gramatica cujas regras de producao

podem ser total ou parcialmente distribuıdas como tabelas estaticas utilizadas por

compressores e decompressores simples que nao atualizam as regras de producao e

nem as transmite. As tabelas podem ser atualizadas de tempos em tempos utli-

zando novos conjuntos de treino, representativos dos dados transmitidos em um

dado perıodo, de modo que as regras guardadas nas tabelas estaticas continuem

sendo capazes de prover uma boa taxa de compressao conforme os padroes dos da-

dos transmitidos mudam ao longo do tempo. O novo algoritmo e nomeado LCA-SLT

(onde SLT e acronimo para Static Lookup Table), e a implementacao em FPGA e

mostrada, mas omitimos aqui os seus detalhes.

3.3.2.3 Aspectos praticos e teoricos da busca por uma gramatica mınima

Revisamos tambem aqui um artigo importante acerca do desafio de se obter a

menor gramatica possıvel que represente uma dada sequencia de dados.

Charikar et al [41] apresentam em seu artigo uma revisao profunda e uma inves-

tigacao teorica dos limites das transformadas de gramatica e dos algoritmos exis-

46

Page 60: emprego de gramáticas livres de contexto para a construção de um ...

tentes, assim como mostram algoritmos proprios para aproximar a menor gramatica

possıvel, obtendo, na epoca, a melhor taxa de aproximacao teorica conhecida de

O(log2(n/g∗)). Contudo, os autores nao abordam o problema da construcao pratica

de um codigo baseado em gramaticas para compressao de dados e nao se preocupam

com aspectos praticos dos algoritmos tais como compelxidade de tempo e espaco,

taxa de compressao final apos a codificacao da gramatica em uma sequencia binaria,

etc.

Inicialmente, e mostrado que a menor gramatica representando uma dada sequencia

de comprimento n tem tamanho Ω(log2 n) e tambem que sequencias altamente es-

truturadas,que contem muitas repeticoes, sao codificadas por gramaticas menores

que as nao estruturadas, pois se Gα gera α e Gβ gera β, ha uma gramatica de tama-

nho |Gα|+ |Gβ|+ 2 que gera αβ mas que uma de tamanho apenas |Gα|+O(log2 k)

gera αk. Entao os autores mostram de duas maneiras diferentes que a aproximacao

da menor gramatica por uma constante pequena e NP-difıcil, uma presumindo que

as entradas nao sao adequadas para a geracao de gramaticas pequenas e uma presu-

mindo entradas altamente estruturadas e adequadas para a obtencao de gramaticas

pequenas.

O artigo segue entao com a analise das taxas de aproximacao (a gramatica mınima)

de varios dos algoritmos existentes: LZ78 e LZW (O((n/ log2 n)2/3)); a transformada

de bisseccao de Yang e Kieffer[3] (O(√n/ log2 n)), as transformadas MPM de Yang

e Kieffer[20, 14] (O(√

n/ log2 n)), assim como a sua transformada gulosa[13] –que

os autores denominam Sequencial– (Ω(n1/3) e O((n/ log2 n)2/3)) e o algoritmo do

casamento mais longo[3] (Ω(log2 log2 n) e O((n/ log2 n)2/3g∗)); o algoritmo guloso de

Apostolico e Leonardi[49] que traz uma ideia similar a do Casamento mais Longo

mas escolhe subsequencias repetidas que tragam a maior reducao no tamanho da

gramatica ao inves de simplesmente a mais longa (ao menos (5 log 3)/(3 log 5) e

O((n/ log2 n)2/3g∗)); e finalmente o Re-Pair[45], para os quais foram encontrados li-

mites muito largos pois e um algoritmo de difıcil analise (Ω(√log2 n) eO((n/ log2 n)

2/3g∗)).

Os novos algoritmos introduzidos pelos autores tem taxa de aproximacaoO(log32 n)

e O(log2(n/g∗)). O primeiro e um algoritmo recursivo que comeca com a sequencia

47

Page 61: emprego de gramáticas livres de contexto para a construção de um ...

de entrada completa de comprimento n e a corta ao meio, em duas partes; as partes

sao sobrepostas de modo a formar uma sequencia mais curta, que por sua vez e

cortada nos limites esquerdos de cada uma das partes originais que a constituem,

de modo a formar novas partes, e qualquer parte mais longa que n/2 e dividida pela

metade. Na proxima iteracao, estas partes sao sobrepostas de maneira gulosa para

formar uma nova sequencia ainda mais curta, que tambem sera cortada nos limites

esquerdos das partes que a constituem e cujos pedacos mais longos que n/4 serao

divididos ao meio, e assim por diante ate que na ultima iteracao as pecas sao de

comprimento 2 ou menos; assinalando nao-terminais para as partes em cada iteracao,

cada parte pode ser especificada por pares de terminais (as partes da ultima iteracao)

ou por nao-terminais correspondentes as partes das iteracoes seguintes. O segundo

algoritmo e baseado no LZ77; primeiramente e feita uma passada da esquerda para

a direita na sequencia de dados de entrada para gerar a menor sequencia LZ77, e

entao esta sequencia e analisada e transformada em uma gramatica pela introducao

de nao-terminais para os pares do LZ77.

Os autores reconhecem que os algoritmos apresentados tem como objetivo uma

melhor compreensao analıtica do problema de aproximacao da gramatica mınima

e podem nao ser adequados para a implementacao pratica e usos reais, pois varios

outros fatores estao envolvidos em compressores praticos e eles nao sao abordados

no artigo. Contudo, o artigo traz uma contribuicao muito interessante na forma da

analise dos principais algoritmos disponıveis a epoca, fazendo a primeira abordagem

analıtica do ponto de vista da aproximacao da gramatica mınima e mostrando um

examplo estabelecendo um novo valor para a melhor taxa de aproximacao conhecida.

Li e Chen[40] propoe uma abordagem nao-determinıstica para a construcao de

gramaticas a partir de sequencias com o uso de algoritmos geneticos. Eles buscam

obter gramaticas menores que as obtidas por algoritmos determinısticos baseados

em heurısticas gulosas conhecidos ate o momento e, alem disso, obter diferentes

gramaticas para uma mesma sequencia. O algoritmo genetico proposto pelos au-

tores toma o Sequitur como ponto de partida e referencia; a ideia de digramas

e extendida para trigramas que podem ser classificados em quatro tipos distintos

dependendo se os digramas esquerdo e direito que constituem o trigrama estao pre-

48

Page 62: emprego de gramáticas livres de contexto para a construção de um ...

sentes ou nao na sequencia parcial ja lida da entrada, e o Sequitur pode ser visto

como um algoritmo de decisao determinıstico que sempre substitui o digrama es-

querdo por um nao-terminal caso ele seja repetido, mas nunca o direito. Contudo

os autores notam que pode ser benefico pular o primeiro sımbolo e substituir o di-

grama direito, e extendem aqui uma proposta anterior de um dos autores de decidir

aleatoriamente entre a substituicao do digrama esquerdo ou direito quando ambas

sao possıveis[50] e desenvolvem um algoritmo genetico em que os cromossomos sao

sequencias binarias do mesmo comprimento da entrada codificando uma sequencia

de decisoes de substituicao do digrama esquerdo ou direito.

Os resultados obtidos mostram que foi possıvel obter gramaticas mais curtas que

as obtidas com o Sequitur e a convergencia rapida do algoritmo. Nao ha, contudo,

comparacoes com outras transformadas de gramatica mais recentes que o Sequitur

e nao analisam a performance do algoritmo para entradas muito grandes.

49

Page 63: emprego de gramáticas livres de contexto para a construção de um ...

Capıtulo 4

Um novo algoritmo criptografico

Feita uma revisao dos fundamentos teoricos dos codigos baseados em gramaticas

para compressao de dados e um levantamento dos mais recentes desenvolvimentos em

algoritmos para a area, nesta secao segue-se para o objetivo final deste trabalho, que

visa obter novos algoritmos criptografico a partir de codigos baseados em gramaticas

para compressao de dados.

Como ponto de partida para a formulacao de algoritmos criptograficos, foi es-

colhido o algoritmo Online LCA de Maruyama et al [36]. Ve-se como vantagens

do Online LCA a sua simplicidade, bom equilıbrio entre complexidade de tempo

e espaco do algoritmo, assim como seu desempenho de aproximacao da gramatica

mınima.

4.1 Sımbolo de partida

A ideia basica aplicada aqui e que, assim como no caso da compressao, pode-se

produzir uma gramatica a partir da sequencia de dados de entrada. Escondendo

alguma parte desta gramatica busca-se impedir a obtencao da sequencia de dados

original e ate mesmo de subsequencias dela a partir da parte restante que e gravada

ou transmitida.

Uma opcao obvia seria esconder a regra de producao do sımbolo de partida e

toma-la como chave; ela e parte necessaria para a obtencao da sequencia original

pois e justamente a peca utilizada para se dar o inıcio do processo de substituicoes

50

Page 64: emprego de gramáticas livres de contexto para a construção de um ...

paralelas que produz a sequencia original e decodifica a gramatica. Entretanto,

no Online LCA todas as gramaticas produzidas tem regras de producao com ape-

nas dois sımbolos em seus membros direitos (de maneira similar a forma normal

de Chomsky), o que tornaria muito curta a chave e consequentemente facil a de-

criptacao por forca bruta. Mesmo que se aplicassem substituicoes, como por exemplo

aplicacoes seguidas das regras de reducao de Yang e Kieffer, poder-se-ia obter uma

chave mais longa, mas seria ainda possıvel somente com o restante da gramatica

obter trechos de texto pleno que comprometam a seguranca e a privacidade dos da-

dos, possibilitando ate, dependendo do contexto e do conhecimento de quem tenta

o ataque, a obtencao do entendimento dos dados originais ou uma boa aproximacao

destes.

Esta ideia e suas deficiencias podem ser mais claramente vistas com o auxılio de

um exemplo. Considere a gramatica a seguir, gerada pelo algoritmo Online LCA,

que teve a regra de seu sımbolo de partida omitida:

A1 → A3A2∗→ A rose is a rose is a

A2 → A6A5∗→ s a rose is a

A3 → A12A7∗→ A rose i

A4 → A9A8∗→ rose.

A5 → A11A10∗→ e is a

A6 → A10A9∗→ s a ros

A7 → A15A11∗→ ose i

A8 → e.

A9 → A16A15∗→ ros

A10 → sA13∗→ s a

A11 → eA14∗→ e i

A12 → AA16∗→ A r

A13 → a

A14 → i

A15 → os

A16 → r

51

Page 65: emprego de gramáticas livres de contexto para a construção de um ...

E trivial verificar que a regra do sımbolo de partida e formada por A1 e A4, dado

que sao os unicos nao-terminais que nao aparecem em nenhuma regra, e a simples

inspecao das expansoes dos dois nao-terminais nos leva a provavel conclusao quanto

ao conteudo da regra do sımbolo de partida e, consequentemente, da sequencia de

entrada:

S → A1A4∗→ A rose is a rose is a rose.

Reduzindo a gramatica utilizando as regras de Yang e Kieffer, podemos obter:

A9 → ros

A18 → A9e is a∗→ rose is a

Com a gramatica irredutıvel obtida, mais informacao e escondida com a omissao

da regra do sımbolo de partida, porem ve-se que pode-se obter, por inspecao, tre-

chos da sequencia original, que podem se mostrar relevantes e comprometer a se-

guranca dos dados ou permitir que um palpite informado se aproxime ou revele a

provavel sequencia original; qualquer um que seja familiarizado com a famosa frase

de Gertrude Stein, sabendo que ” rose is a” e ” ros” sao elementos repetitivos na

sequencia original, poderia deduzir o conteudo como ”A rose is a rose is a rose.”

ou ”Rose is a rose is a rose is a rose.” ou algo similar.

Claramente o exemplo mostrado e demasiado simples e, na pratica, com entradas

mais longas e complexas, a gramatica reduzida dificultaria bastante a obtencao da

sequencia original completa (ou de um palpite razoavel). Contudo, a possibilidade da

obtencao de trechos continua presente, e o acesso a um trecho contendo informacao

sensıvel pode ser o suficiente para um ataque bem-sucedido.

4.2 Regras de Producao

Uma outra opcao, mais interessante, e olhar para o codificador de gramatica do

Online LCA para extrair a chave. O codificador primeiro computa a arvore parcial

de derivacao da gramatica construıda, e entao codifica a sequencia de nos desta

arvore, indicando o tipo de cada no, se interno (ate 2h−1 nos) ou folha (ate 2h nos).

Por ser uma arvore parcial de derivacao, aproximadamente metade dos nos serao

52

Page 66: emprego de gramáticas livres de contexto para a construção de um ...

Figura 4.1: Exemplo de arvore parcial de derivacao de uma gramatica

S

A1

A3

A12

A A16

r

A7

A15

o s

A11

e A14

i

A2

A6

A10

s A13

a

A9

A16 A15

A5

A11 A10

A4

A9 A8

e .

folhas, e dentre eles pode haver tanto sımbolos do alfabeto da sequencia original

como sımbolos nao-terminais da gramatica.

Para codificar a sequencia dos nos, o algoritmo percorre a arvore pos-ordem e,

com a ordem fixa e sendo cada no interno etiquetado por nao-terminais distintos,

apenas indicar a existencia dos nos internos e o suficiente para especifica-los por

completo, enquanto os nos folha necessitam ser codificados nao so com a indicacao

de que sao nos folha como tambem com a etiqueta do no, seja ela um terminal ou

um nao-terminal.

Codificando-se separadamente os nos folha do restante da estrutura da arvore e

os tomando como chave, nao so sera difıcil obter a sequencia original sem a posse

da chave, como sera tambem difıcil recuperar ate parcialmente a sequencia. A

unica informacao a que se tem acesso parcial e a estrutura hierarquica da sequencia,

capturada pela gramatica e presente na arvore parcial de derivacao.

Pode-se ver na Figura 4.2, por exemplo, a arvore parcial de derivacao da gramatica

do exemplo da secao anterior. Seguindo o esquema do algoritmo Online LCA, esta

arvore pode ter sua estrutura representada pela sequencia de bits F que indica, para

cada no da arvore percorrida pos-ordem, se e folha (bit 1) ou nao (bit 0):

F = 11100110111000011100110011000111000

53

Page 67: emprego de gramáticas livres de contexto para a construção de um ...

E os nos folha podem ser representados pela sequencia L de suas etiquetas,

tambem percorrida a arvore pos-ordem:

L = A rose is aA16A15A11A10A9e.

A implementacao de referencia do Online LCA codifica a arvore parcial escrevendo

uma sequencia entrelacando F e L, e o arquivo comprimido pode ser representado

por:

LCA = 1A1 1r001o1s01e1 1i00001s1 1a001A161A15001A111A100001A91e1.000

Simplesmente utilizar L como chave e F como a saıda criptografada seria, contudo,

tambem uma solucao ingenua – embora mais segura que a utilizacao da regra do

sımbolo de partida como chave – pois logo se ve que |L| >> |F |, ou seja, a chave

seria muito maior que o proprio arquivo criptografado.

4.3 Sımbolos terminais

No caso exemplo da secao anterior, como o texto e pequeno, o numero de terminais

na sequencia das folhas |T (L)| e mais que o dobro do numero de nao-terminais

|N(L)|, contudo para casos de sequencias mais longas, que sao os casos de uso

reais, tipicamente teremos que |N(L)| >> |T (L)|. Pode-se tirar proveito desta

observacao e, ao inves de tomar L como chave, tomar T (L). Observando-se que as

folhas etiquetadas por nao-terminais na realidade tambem representam a estrutura

hierarquica dos dados, posto que de maneira abreviada, ve-se que uma separacao

entre estrutura e conteudo se pode dar de maneira completa somente com esta

separacao entre as folhas terminais e nao-terminais.

Pode-se adotar um procedimento bastante simples para efetuar a extracao da

chave e criptografia da sequencia de entrada utilizando a ideia exposta acima ti-

rando proveito do sımbolo fictıcio utilizado para inicializar as filas no Online LCA,

cujo codigo nao e admissıvel nem como terminal nem como nao-terminal. No mo-

mento da codificacao da gramatica, caso a etiqueta da folha a ser gravado seja um

sımbolo terminal, basta substituı-lo pelo sımbolo fictıcio D0 e apensar o terminal

54

Page 68: emprego de gramáticas livres de contexto para a construção de um ...

a chave. Para decodificar o arquivo, a unica mudanca necessaria no algoritmo de

descompressao e a detecao do sımbolo fictıcio e a leitura do sımbolo correto na chave.

Retomando o exemplo da sequencia de entrada ”A rose is a rose is a rose.”,

obterıamos entao duas sequencias de saıda, a sequencia comprimida criptografada

LCA′ e a chave T (L):

L′ = D0D0D0D0D0D0D0D0D0D0D0A16A15A11A10A9D0D0

LCA′ = interleave(F,L′) =

1D01D01D0001D01D001D01D01D000001D01D0...

...1D0001A161A15001A111A100001A91D01D0000

T (L) = A rose is ae.

O efeito desta operacao e, em suma, gerar uma sequencia com o mesmo tama-

nho da sequencia original, porem consistindo de repeticoes de um unico sımbolo

fictıcio, e comprimida utilizando a estrutura da sequencia original. De posse de uma

chave composta pela sequencia dos sımbolos terminais nas etiquetas das folhas da

arvore de derivacao parcial percorrida pos-ordem, pode-se regerar a sequencia ori-

ginal ao reintroduzir os terminais apropriados na gramatica e, em seguida, descom-

primindo a sequencia normalmente pelo processo gerativo de substituicoes paralelas

pela aplicacao das regras de producao da gramatica.

Esta ideia de separar conteudo e estrutura esta relacionada as ideias de Yang e

Kieffer quanto a gramaticas estruturais vs gramaticas representativas[43, 26, 32],

especialmente o codigo de refinamento em que sao enviadas uma gramatica estru-

turalmente identica a que gera a sequencia original e as transformacoes necessarias

para obter a gramatica que gera tal sequencia[26].

4.4 Avaliacao empırica do algoritmo proposto

Uma implementacao do algoritmo proposto, baseada na implementacao de re-

ferencia do algoritmo Online LCA, pode ser consultada no Apendice A. Esta imple-

mentacao foi utilizada para comprimir e criptografar arquivos do corpus Pizza&Chili [51]

em uma avaliacao empırica do algoritmo proposto, batizado Crypto LCA.

55

Page 69: emprego de gramáticas livres de contexto para a construção de um ...

Como metricas para a avaliacao foram utilizados o numero de aprovacoes na

bateria de testes da versao 2.1.2 da STS (Statistical Test Suite), uma suıte de tes-

tes estatısticos de aleatoriedade para aplicacoes criptograficas disponibilizada pelo

NIST, instituto governamental dos Estados Unidos, assim como a medida de taxa

de entropia de Shannon em bits de informacao por byte.

Com a STS, pode-se aplicar uma bateria de 188 testes a amostras de fluxos de bits

para determinar se diferentes caracterısticas estatısticas das amostras se adequam

aos valores esperados de fluxos aleatorios de bits, e a suıte se destina a validacao

de geradores de numeros aleatorios e pseudo-aleatorios utilizados em algoritmos

criptograficos[52].

Para reproduzir os testes, sao necessarios os seguintes comandos, que presumem

que os arquivos a serem testados estao no diretorio test inputs, os resultados serao

guardados no diretorio test outputs e a STS esta instalada no diretorio sts-2.1.2,

todos os tres diretorios estando no mesmo nıvel:

1 cd sts-2.1.2

2

3 for file in $(ls ../test_inputs/*); do

4 echo "0

5 $file

6 1

7 0

8 100

9 1" | ./assess 10000

10

11 cp ./experiments/AlgorithmTesting/finalAnalysisReport.txt

../test_outputs/assess_10k_$(basename $file).txt

12 done

Foram amostrados 100 fluxos de 10000 bits cada de cada arquivo para os testes,

utilizando os parametros sugeridos por padrao onde necessario. Dos 188 testes

56

Page 70: emprego de gramáticas livres de contexto para a construção de um ...

disponıveis, 26 nao obtiveram resultados definidos para a maioria das amostras (por

sua limitacao de tamanho) e foram excluıdos da avaliacao, restando 162 testes cujos

resultados foram levados em conta. Para que um arquivo seja considerado aprovado

num teste, foi seguida a recomendacao da STS de que ao menos 96 das 100 sequencias

amostradas do arquivo tenham sido aprovadas pelo teste.

O algoritmo proposto neste trabalho nao se utiliza de geradores de numeros

(pseudo-)aleatorios, contudo se espera que sequencias criptografadas tambem exi-

bam caracterısticas estatısticas de aleatoriedade e, portanto, as aprovacoes na suıte

de testes do NIST sao empregadas aqui como uma indicacao de quanto os arquivos

criptografados produzidos se aproximam da aleatoriedade estatıstica e, consequente-

mente, da dificuldade de predicao das sequencias produzidas. E neste mesmo sentido

que e interpretada a entropia das sequencias que, quanto mais proxima de 8 bits

por byte, mais a sequencia se aproxima da aleatoriedade. A entropia foi medida

utilizando o utilitario ent[53], e esta medicao pode ser reproduzida para todos os

arquivos de um diretorio atraves dos comandos abaixo:

1 for file in $(ls ./test_inputs/*); do

2 ent $file > ./test_outputs/ent_$(basename $file).txt

3 done

Os numeros de aprovacoes nos testes da STS, a entropia e o tamanho dos arqui-

vos do Pizza&Chili originais, comprimidos pelo Online LCA e criptografados pelo

Crypto LCA se encontram, respectivamente, nas Tabelas 4.1, 4.2 e 4.3. Na Tabela

4.4 estao listados o tamanho e a entropia das chaves geradas pelo Crypto LCA.

Como era esperado dada a natureza da operacao de compressao, ve-se que a

compressao pelo algoritmo Online LCA aumenta significativamente a entropia dos

arquivos, tendo sido aumentada em media em 141%, sendo o menor acrescimo, de

44%, para o arquivo coreutils, que e o que possui maior entropia original, e o maior

acrescimo, de 301%, para o arquivo influenza, que possui a menor entropia original.

A entropia dos arquivos comprimidos ficou, na media, aproximadamente 0.166 bits

abaixo dos 8 bits esperados para sequencias perfeitamente aleatorias.

57

Page 71: emprego de gramáticas livres de contexto para a construção de um ...

Tambem de acordo com o esperado, pode-se observar que a aplicacao do algoritmo

criptografico proposto, Crypto LCA, diminui ligeiramente a entropia dos arquivos,

sendo o valor observado em media 0.009 bits menor em relacao a simples compressao.

Em termos percentuais, este valor representa uma diminuicao media 0.001% da

entropia em decorrencia da criptografia. Esta diminuicao e esperada pois a sequencia

produzida pelo algoritmo criptografico e muito similar a sequencia produzida pela

compressao, com a unica diferenca sendo a substituicao de todas as ocorrencias de

sımbolos terminais, que podem ser quaisquer sımbolos do alfabeto, pelo sımbolo

fictıcio, que sera sempre o mesmo.

Analisando o resultado pelo numero de aprovacoes na bateria de testes da STS,

vemos que este numero aumentou ou ao menos se manteve estavel se compararmos

os arquivos criptografados em relacao aos comprimidos. Isto indica que, mesmo

com a diminuicao da entropia em relacao a compressao, a criptografia ajudou a

mascarar certos tipos de padroes dos dados melhor do que a compressao pura e

simples, tambem de acordo com o efeito desejado.

Contudo, a mesma analise do resultado pela otica do numero de aprovacoes numa

comparacao entre os arquivos originais e os comprimidos ou criptografados mostra

que para 7 (dos 11) arquivos o numero de aprovacoes aumentou apos o processa-

mento, contudo para 4 arquivos este numero diminuiu. Estes arquivos sao coreutils,

einstein.de.txt, einstein.en.txt e influenza.

Os arquivos einstein.de.txt e einstein.en.txt consistem de varias repeticoes dos

artigos da Wikipedia sobre Albert Einstein em alemao e ingles, respectivamente,

coreutils e uma concatenacao de arquivos de codigo fonte, e influenza e o sequen-

ciamento genetico do vırus da gripe.

Todos os 4 tem, por sua natureza, conteudos altamente estruturados e repetiti-

vos, seja por serem repeticoes (einstein.de.txt, einstein.en.txt), textos sujeitos a

fortes restricoes sintaticas e vocabulares e de natureza hierarquica (coreutils) ou

uma sequencia com longas estruturas repetitivas e complementares (influenza)[54].

Como a compressao pelo Online LCA (e tambem, por extensao, a criptografia pelo

58

Page 72: emprego de gramáticas livres de contexto para a construção de um ...

Tabela 4.1: Testes estatısticos nos arquivos originais do corpus Pizza&Chili

Arquivo Tamanho (bytes) Aprovacoes STS (/162) Entropia (bits/byte)

cere 461286644 67 2.191510

coreutils 205281778 75 5.465309

dblp.xml 296135874 78 5.262064

einstein.de.txt 92758441 94 5.038626

einstein.en.txt 467626544 95 4.962309

english 2210395553 79 4.525110

Escherichia Coli 112689515 87 2.000835

influenza 154808555 110 1.973055

kernel 257961616 90 5.379011

para 429265758 109 2.124905

world leaders 46968181 112 3.471487

Crypto LCA) busca representar justamente a estrutura dos dados, e de se espe-

rar que estas estruturas repetitivas gerem padroes no resultado final, o que pode

acarretar este efeito observado.

59

Page 73: emprego de gramáticas livres de contexto para a construção de um ...

Tabela 4.2: Testes estatısticos nos arquivos comprimidos pelo Online LCA

Arquivo Tamanho (bytes) Aprovacoes STS (/162) Entropia (bits/byte)

cere.lca 14871788 101 7.807951

coreutils.lca 10688340 31 7.917588

dblp.xml.lca 68854732 97 7.818900

einstein.de.txt.lca 282488 73 7.924042

einstein.en.txt.lca 781380 61 7.902004

english.lca 759864780 104 7.652208

Escherichia Coli.lca 14003896 105 7.688689

influenza.lca 7030156 56 7.917138

kernel.lca 5605988 123 7.872786

para.lca 19119780 93 7.765356

world leaders.lca 1574904 128 7.905300

Tabela 4.3: Testes estatısticos nos arquivos criptografados pelo Crypto LCA

Arquivo Tamanho (bytes) Aprovacoes STS (/162) Entropia (bits/byte)

cere.clca 14871788 101 7.807703

coreutils.clca 10688340 37 7.908567

dblp.xml.clca 68854732 105 7.817553

einstein.de.txt.clca 282488 80 7.880171

einstein.en.txt.clca 781380 67 7.875517

english.clca 759864780 108 7.651920

Escherichia Coli.clca 14003896 105 7.688579

influenza.clca 7030156 93 7.917038

kernel.clca 5605988 124 7.861296

para.clca 19119780 93 7.765122

world leaders.clca 1574904 135 7.895641

60

Page 74: emprego de gramáticas livres de contexto para a construção de um ...

Tabela 4.4: Testes estatısticos nas chaves criptograficas geradas pelo Crypto LCA

Arquivo Tamanho (bytes) Entropia (bits/byte)

cere.clca.key 5248 3.978653

coreutils.clca.key 179576 5.205402

dblp.xml.clca.key 150944 4.820551

einstein.de.txt.clca.key 13984 5.977262

einstein.en.txt.clca.key 25908 5.658158

english.clca.key 323300 4.244618

Escherichia Coli.clca.key 1852 4.491471

influenza.clca.key 1300 4.974419

kernel.clca.key 89400 5.219574

para.clca.key 6104 4.028607

world leaders.clca.key 21792 5.611751

61

Page 75: emprego de gramáticas livres de contexto para a construção de um ...

Capıtulo 5

Conclusoes

Neste trabalho foi demonstrada viabilidade da construcao de um algoritmo crip-

tografico baseado em gramaticas livres de contexto em que a propria gramatica

representa o texto criptografado.

Tanto quanto se sabe, a abordagem aqui utilizada e original, e difere de outras

abordagens baseadas em gramaticas livres de contexto pois nao utiliza gramaticas

arbitrarias como chave ou segredo, mas infere uma gramatica a partir dos dados a

serem criptografados e extrai, desta gramatica inferida, elementos que impecam a

obtencao dos dados originais, de modo que a propria gramatica seja a representacao

criptografada e comprimida dos dados.

5.1 Consideracoes finais

Esta abordagem e inspirada nas aplicacoes de compressao de dados baseadas em

gramaticas livres de contexto e na observacao de que a gramatica livre de contexto

inferida e, sobretudo, uma representacao da estrutura dos dados, exprimida por

suas regras de producao e sımbolos nao-terminais, e o conteudo dos dados, que ori-

ginalmente consiste somente dos sımbolos terminais que neles aparecem, e destilado

de modo a que se reduza a um mınimo de sımbolos terminais e padroes curtos de

sımbolos terminais que precisam ser inseridos, reinseridos e repetidos na aplicacao

das regras de producao para que se gere os dados originais.

62

Page 76: emprego de gramáticas livres de contexto para a construção de um ...

Sem este conjunto de sımbolos e padroes curtos de sımbolos, que representam

uma pequena parcela da gramatica, se torna impossıvel gerar os dados originais,

pois as regras de producao e os sımbolos nao-terminais perdem todas as referencias

que os ligam ao conteudo dos dados. Este conjunto de sımbolos e padroes terminais

se torna, entao, a chave do algoritmo criptografico aqui proposto.

Para atender aos objetivos iniciais de que o algoritmo criptografico seja simples,

de baixa complexidade computacional tanto temporal quanto espacial, foi escolhido

como base um algoritmo de compressao com estas caracterısticas. Adicionalmente,

pelo fato de o algoritmo criptografico proposto manter as caracterısticas de com-

pressao do algoritmo de compressao subjacente – o que e, por si so, bastante in-

teressante uma vez que, de modo geral, algoritmos criptograficos nao comprimem

os dados – foi levada em conta tambem a capacidade de compressao do algoritmo

escolhido.

Por apresentar um bom compromisso entre todas as caracterısticas desejaveis, foi

escolhido oOnline LCA como base para a construcao do algoritmo criptografico, e di-

ferentes maneiras de adaptar este algoritmo foram avaliadas do ponto de vista teorico

quanto as possibilidades de ataques e comparada a outras abordagens possıveis para

chegar ao algoritmo proposto Crypto LCA.

Uma implementacao do algoritmo foi desenvolvida e resultados de testes empıricos

demonstram que o conceito apresentado e viavel e sobre o qual maiores investigacoes

sao desejaveis, tanto teoricas quanto praticas.

Os casos de uso inicialmente vislumbrados para o algoritmo criptografico introdu-

zido neste trabalho sao os que envolvem a transmissao segura e eficiente de grandes

volumes de dados por um canal inseguro, tirando vantagem da compressao obtida

com a criptografia. A chave, relativamente pequena, pode transmitida fora de banda

ou por um canal seguro mas de baixa capacidade.

63

Page 77: emprego de gramáticas livres de contexto para a construção de um ...

5.2 Trabalhos Futuros

Trabalhos futuros sugeridos abrangem: uma analise da robustez do algoritmo em

relacao a ataques diversos, tais como analisar quais informacoes se poderia extrair

da estrutura, precisar o nıvel de dificuldade para encontrar a chave ou uma chave

suficientemente proxima que permita uma aproximacao dos dados originais; a in-

vestigacao mais aprofundada das propriedades das gramaticas como representacoes

de estruturas (que muitas vezes apresentam fortes padroes) e sua relacao com os

resultados dos testes estatısticos de aleatoriedade e forca criptografica; adicionar a

chave permutacoes na ordem de codificacao dos nos para dificultar a obtencao da

estrutura correta e uma apoximacao dos dados originais por busca da chave, aumen-

tar a entropia e aumentar a taxa de aprovacao nos testes estatısticos do NIST; a

introducao de aleatoriedade na inferencia da gramatica, de modo que sejam produ-

zidas diferentes gramaticas para uma mesma sequencia de entrada, diminuindo as

chances de ataques em que candidatos sao criptografados e suas saıdas comparadas

ao alvo para determinar possıveis correspondencias; e pesquisar a possibilidade de

estender o algoritmo de modo a prover tambem garantias quanto a integridade dos

dados ou, ainda, tolerancia a erros de transmissao.

64

Page 78: emprego de gramáticas livres de contexto para a construção de um ...

Referencias Bibliograficas

[1] SHANNON, C. E., “A mathematical theory of communication”, The Bell Sys-

tem Technical Journal, v. 27, n. 3, pp. 379–423, July 1948.

[2] CHOMSKY, N., “Three models for the description of language”, IRE Transac-

tions on Information Theory, v. 2, n. 3, pp. 113–124, September 1956.

[3] KIEFFER, J. C., YANG, E.-H., “Grammar-Based Codes: A New Class of Uni-

versal Lossless Source Codes”, IEEE Trans. Inform. Theory, v. 46, pp. 737–754,

May 2000.

[4] WAYNER, P., Disappearing Cryptography: Information Hiding: Steganography

& Watermarking, The Morgan Kaufmann Series in Software Engineering and

Programming. Elsevier Science, 2009.

[5] BASSIL, Y., “An Image Steganography Scheme using Randomized Algorithm

and Context-Free Grammar”, Journal of Advanced Computer Science & Tech-

nology, v. 1, n. 4, pp. 291–305, 2012.

[6] SINGH, A., DOS SANTOS, A. L. M., “Grammar Based off Line Generation

of Disposable Credit Card Numbers”. In: Proceedings of the 2002 ACM Sym-

posium on Applied Computing, SAC ’02, pp. 221–228, New York, NY, USA,

2002.

[7] ANGLUIN, D., KHARITONOV, M., “When Won’t Membership Queries

Help?”, Journal of Computer and System Sciences, v. 50, n. 2, pp. 336 – 355,

1995.

[8] GOLD, E. M., “Language identification in the limit”, Information and Control,

v. 10, n. 5, pp. 447 – 474, 1967.

65

Page 79: emprego de gramáticas livres de contexto para a construção de um ...

[9] BUCCAFURRI, F., LAX, G., “A Light Number-Generation Scheme for Fea-

sible and Secure Credit-Card-Payment Solutions”. In: Psaila, G., Wagner, R.

(eds.), E-Commerce and Web Technologies: 9th International Conference, EC-

Web 2008 Turin, Italy, September 3-4, 2008 Proceedings, pp. 11–20, Berlin,

Heidelberg, 2008.

[10] MOLLOY, I., LI, J., LI, N., “Dynamic Virtual Credit Card Numbers”. In:

Dietrich, S., Dhamija, R. (eds.), Financial Cryptography and Data Security:

11th International Conference, FC 2007, and 1st International Workshop on

Usable Security, USEC 2007, Scarborough, Trinidad and Tobago, February 12-

16, 2007. Revised Selected Papers, pp. 208–223, Berlin, Heidelberg, 2007.

[11] BUCCAFURRI, F., LAX, G., “Implementing disposable credit card numbers

by mobile phones”, Electronic Commerce Research, v. 11, n. 3, pp. 271–296,

2011.

[12] SINGH, A., DOS SANTOS, A. L. M., “Context Free Grammar for the Ge-

neration of a One Time Authentication Identity”. In: Proceedings of the 17th

International FLAIRS Conference, 2004.

[13] YANG, E.-H., KIEFFER, J. C., “Efficient Universal Lossless Data Compresion

Algorithms Based on a Greedy Sequential Grammar Transform –Part One:

Without Context Models”, IEEE Trans. Inform. Theory, v. 46, pp. 755–777,

May 2000.

[14] YANG, E.-H., KALTCHENKO, A., KIEFFER, J. C., “Universal Lossless Data

Compression With Side information by Using a Conditional MPM Grammar

Transform”, IEEE Trans. Inform. Theory, v. 47, pp. 2130–2150, September

2001.

[15] NEVILL-MANNING, C., WITTEN, I., “Identifying hierarchical structure in

sequences: A linear-time algorithm”, J. Artificial Intell. Res., v. 7, pp. 67–82,

1997.

[16] KONTOYIANNIS, I., “Pointwise redundancy in lossy data compression and

universal lossy data compression”, IEEE Trans. Inform. Theory, v. 46,

pp. 136–152, 2000.

66

Page 80: emprego de gramáticas livres de contexto para a construção de um ...

[17] COVER, T., “Enumerative source encoding”, IEEE Trans. Inform. Theory,

v. IT-19, pp. 73–77, January 1973.

[18] KIEFFER, J. C., YANG, E.-H., “Lossless data compression algorithms based

on substitution tables”. In: Proc. IEEE 1998 Canadian Conf. Electrical and

Computer Engineering, pp. 629–632, Waterloo, Ont., Canada, May 1998.

[19] YANG, E.-H., JIA, Y., “Efficient grammar-based data compression algorithms:

Complexity, implementation, and simulation results”. paper in preparation.

[20] KIEFFER, J. C., YANG, E.-H., NELSON, G., et al., “Lossless compres-

sion via multilevel pattern matching”, IEEE Trans. Inform. Theory, v. 46,

pp. 1227–1245, July 2000.

[21] YANG, E.-H., JIA, Y., “Universal lossless coding of sources with large or un-

bounded alphabets”. In: et al., I. A. (ed.), Numbers, Information and Comple-

xity, Norwell, MA, Kluwer, pp. 421–442, 2000.

[22] YANG, E.-H., HE, D.-K., “Interactive Encoding and Decoding for One Way Le-

arning: Near Lossless Recovery With Side Information at the Decoder”, IEEE

Transactions on Information Theory, v. 56, pp. 1808–1824, April 2010.

[23] YANG, E.-H., HE, D.-K., “Two results on interactive lossless source encoding

and decoding with side information at the decoder”. In: Third International

Conference on Communications and Networking in China. ChinaCom 2008,

pp. 90–94, Hangzhou, August 2008.

[24] MENG, J., YANG, E.-H., “Interactive Encoding and Decoding Based on Binary

LDPC Codes With Syndrome Accumulation”, IEEE Transactions on Informa-

tion Theory, v. 59, pp. 3068–3103, May 2013.

[25] MENG, J., YANG, E.-H., HE, D.-K., “Linear Interactive Encoding and Deco-

ding for Lossless Source Coding With Decoder Only Side Information”, IEEE

Transactions on Information Theory, v. 57, pp. 5281–5297, August 2011.

[26] KIEFFER, J. C., YANG, E.-H., “Grammar-Based Lossless Universal Refi-

nement Source Coding”, IEEE Transactions on Information Theory, v. 50,

pp. 1415–1424, July 2004.

67

Page 81: emprego de gramáticas livres de contexto para a construção de um ...

[27] DEBOWSKI, L., “On the Vocabulary of Grammar-Based Codes and the Lo-

gical Consistency of Texts”, IEEE Transactions on Information Theory, v. 57,

pp. 4589–4599, July 2011.

[28] DEBOWSKI, L., “A Preadapted Universal Switch Distribution for Testing

Hilberg’s Conjecture”, IEEE Transactions on Information Theory, v. 61,

pp. 5708–5715, October 2015.

[29] DORIER, M., IBRAHIM, S., ANTONIU, G., et al., “Omnisc’IO: A Grammar-

Based Approach to Spatial and Temporal I/O Patterns Prediction”. In: Pro-

ceedings of the International Conference for High Performance Computing,

Networking, Storage and Analysis, pp. 623–634, Piscataway, NJ, 2014.

[30] DOSHI, J., GANDHI, S., “Enhanced arithmetic coding using total frequency in

power of 2 amp; processing multi-bits at a time”, Sixth International Conference

on Contemporary Computing (IC3), pp. 1–6, Aug 2013.

[31] JAIN, S., BANSAL, R. K., “On Match Lengths, Zero Entropy, and Large

Deviations–With Application to Sliding Window Lempel-Ziv Algorithm”, IEEE

Transactions on Information Theory, v. 61, pp. 120–132, January 2015.

[32] ZHANG, J., YANG, E.-H., KIEFFER, J. C., “A Universal Grammar-Based

Code for Lossless Compression of Binary Trees”, IEEE Transactions on Infor-

mation Theory, v. 60, pp. 1373–1386, March 2014.

[33] ZHANG, J., YANG, E.-H., KIEFFER, J. C., “Redundancy analysis in lossless

compression of a binary tree via its minimal DAG representation”. In: 2013

IEEE International Symposium on Information Theory Proceedings (ISIT), pp.

1914–1918, July 2013.

[34] KUZUOKA, S., WATANABE, S., “An Information-Spectrum Approach to

Weak Variable-Length Source Coding With Side-Information”, IEEE Transac-

tions on Information Theory, v. 61, pp. 3559–3573, June 2015.

[35] ZHENG, L., YANG, E.-H., “On optimum fixed-rate causal scalar quantization

design for causal video coding”. In: 12th Canadian Workshop on Information

Theory (CWIT), pp. 58–61, 2011.

68

Page 82: emprego de gramáticas livres de contexto para a construção de um ...

[36] MARUYAMA, S., TAKEDA, M., NAKAHARA, M., et al., “An Online Algo-

rithm for Lightweight Grammar-Based Compression”. In: First International

Conference on Data Compression, Communications and Processing (CCP), pp.

19–28, June 2011.

[37] HU, N., YANG, E.-H., “Fast Mode Selection for HEVC Intra-Frame Coding

With Entropy Coding Refinement Based on a Transparent Composite Mo-

del”, IEEE Transactions on Circuits and Systems for Video Technology, v. 25,

pp. 1521–1532, September 2015.

[38] WANG, N., HAN, J., FANG, J., “An Anomaly Detection Algorithm Based

on Lossless Compression”. In: 7th International Conference on Networking,

Architecture and Storage (NAS), pp. 31–38, 2012.

[39] YAMAGIWA, S., SAKAMOTO, H., “A reconfigurable stream compression

hardware based on static symbol-lookup table”. In: 2013 IEEE International

Conference on Big Data, pp. 86–93, On page(s), 2013.

[40] LI, Y., CHEN, J. X., “A nondeterministic approach to infer context free gram-

mar from sequence”. In: 11th International Computer Conference on Wavelet

Active Media Technology and Information Processing (ICCWAMTIP), pp. 1–9,

2014.

[41] CHARIKAR, M., LEHMAN, E., LIU, D., et al., “The smallest grammar pro-

blem”, IEEE Transactions on Information Theory, v. 51, pp. 2554–2576, July

2005.

[42] SAKR, S., “XML Compression Techniques: A Survey and Comparison”, Jour-

nal of Computer and System Sciences (JCSS), v. 75, pp. 303–322, August 2009.

[43] KIEFFER, J. C., YANG, E.-H., “Structured grammar-based codes for universal

lossless data compression”, Commun. Inform. and Syst., v. 2, n. 1, pp. 29–52,

June 2002.

[44] SAKAMOTO, H., “A fully linear-time approximation algorithm for grammar-

based compression”, J. Discrete Algorithms, v. 3, pp. 416–430, June 2005.

69

Page 83: emprego de gramáticas livres de contexto para a construção de um ...

[45] LARSSON, N. J., MOFFAT, A., “Offline dictionary-based compression”. In:

Proceedings of the IEEE, pp. 1722–1732, November 2000.

[46] NAVARRO, G., RUSSO, L., “Re-pair Achieves High-Order Entropy”. In: 2008

Data Compression Conference (DCC 2008), pp. 537–537, Snowbird, UT, 2008.

[47] SAKAMOTO, H., KIDA, T., SHIMOZONO, S., String Processing and Infor-

mation Retrieval: 11th International Conference, SPIRE 2004, Padova, Italy,

October 5-8, 2004. Proceedings, chapter A Space-Saving Linear-Time Algorithm

for Grammar-Based Compression, Berlin, Heidelberg, Springer Berlin Heidel-

berg, pp. 218–229, 2004.

[48] RYTTER, W., “Application of lempel-ziv factorization to the approximation of

grammar-based compression”, Theor. Comput. Sci., v. 302, pp. 211–222, June

2003.

[49] APOSTOLICO, A., LONARDI, S., “Off-line compression by greedy textual

substitution”, Proc. IEEE, v. 88, n. 11, pp. 1733–1744, November 2000.

[50] LI, Y., LIN, J., OATES, T., “Visualizing Variable-Length Time Series Motifs”.

In: Proceedings of the 2012 SIAM International Conference on Data Mining

(SDM 2012), pp. 895–906, April 2012.

[51] FERRAGINA, P., GONZaLEZ, R., NAVARRO, G., et al., “Compressed

Text Indexes: From Theory to Practice”, J. Exp. Algorithmics, v. 13,

pp. 12:1.12–12:1.31, Feb. 2009.

[52] RUKHIN, A., SOTO, J., NECHVATAL, J., et al., A Statistical Test Suite for

Random and Pseudorandom Number Generators for Cryptographic Applicati-

ons, Report, National Institute of Standards and Technology, Gaithersburg,

MD, 2010.

[53] WALKER, J., “Ent - A Pseudorandom Sequence Test”, http://www.fourmi-

lab.ch/random/, 2008, (Acesso em 29 de Marco de 2016).

[54] CHERNIAVSKY, N., LADNER, R., Grammar-based Compression of DNA Se-

quences, Report, University of Washington, 2004.

70

Page 84: emprego de gramáticas livres de contexto para a construção de um ...

Apendice A

Implementacao do algoritmo

Crypto LCA

Neste apendice se encontra o codigo-fonte completo de uma implementacao do

algoritmo criptografico Crypto LCA, proposto neste trabalho. O algoritmo e baseado

no algoritmo de compressao Online LCA, cuja implementacao escrita e disponibili-

zada por Maruyama[36] no endereco eletronico http://code.google.com/p/lcacomp/

serviu de base para esta aqui apresentada.

71

Page 85: emprego de gramáticas livres de contexto para a construção de um ...

A.1 bits.c

1 /*2 * Copyright (c) 2011-2012 Shirou Maruyama3 *4 * Redistribution and use in source and binary forms, with

or without5 * modification, are permitted provided that the following

conditions6 * are met:7 *8 * 1. Redistributions of source code must retain the above

Copyright9 * notice, this list of conditions and the following

disclaimer.10 *11 * 2. Redistributions in binary form must reproduce the

above Copyright12 * notice, this list of conditions and the following

disclaimer in the13 * documentation and/or other materials provided with the

distribution.14 *15 * 3. Neither the name of the authors nor the names of its

contributors16 * may be used to endorse or promote products derived from

this17 * software without specific prior written permission.18 */19

20

21 #include "bits.h"22

23 #define INLINE __inline24 //#define DEBUG25

26 #define W_BITS 3227 #define BITIN_BUF_LEN 32768 /* BITIN_BUF_LEN*sizeof(uint)

bytes */28 #define BITOUT_BUF_LEN 32768 /* BITOUT_BUF_LEN*sizeof(uint)

bytes */29

30 #ifdef DEBUG31 // function for debug32 static33 void printBinary(uint x) 34 int bit = 1, i;35 char c[W_BITS];36

37 for (i = 0; i < W_BITS; i++) 38 if (x & bit)39 c[i] = ’1’;40 else41 c[i] = ’0’;42 bit <<= 1;

72

Page 86: emprego de gramáticas livres de contexto para a construção de um ...

43 44 for (i = W_BITS - 1; i >= 0; i--) 45 putchar(c[i]);46 47 printf("\n");48 49 #endif50

51 BITOUT *createBitout(FILE *output) 52 BITOUT *b = (BITOUT*)malloc(sizeof(BITOUT));53

54 b->output = output;55 b->emplen = W_BITS;56 b->bitbuf = 0;57 b->buftop = (uint*)calloc(BITOUT_BUF_LEN+1, sizeof(uint));58 b->bufpos = b->buftop;59 b->bufend = b->buftop + BITOUT_BUF_LEN;60 return b;61 62

63 INLINE64 void writeBits(BITOUT *b, uint x, uint wblen) 65 uint s;66

67 #ifdef DEBUG68 if (wblen > W_BITS) 69 fprintf(stderr, "Error: length of write bits (%d) is

longer than %d\n",70 wblen, W_BITS);71 exit (1);72 73 if (wblen == 0) 74 return;75 76 #endif77

78 if (wblen < b->emplen) 79 b->emplen -= wblen;80 b->bitbuf |= x << b->emplen;81 82 else 83 s = wblen - b->emplen;84 b->bitbuf |= x >> s;85 *(b->bufpos) = b->bitbuf;86 b->bufpos++;87 b->emplen = W_BITS - s;88 if (b->emplen != W_BITS) 89 b->bitbuf = x << b->emplen;90 91 else 92 b->bitbuf = 0;93 94

95 if (b->bufpos == b->bufend)

73

Page 87: emprego de gramáticas livres de contexto para a construção de um ...

96 fwrite(b->buftop, sizeof(uint), BITOUT_BUF_LEN,b->output);

97 memset(b->buftop, 0, sizeof(uint)*BITOUT_BUF_LEN);98 b->bufpos = b->buftop;99

100 101 102

103 void flushBitout(BITOUT *b)104 105 uint n;106 if (b->emplen != W_BITS) 107 *(b->bufpos) = b->bitbuf;108 b->bufpos++;109 110 n = fwrite(b->buftop, sizeof(uint), b->bufpos -

b->buftop, b->output);111 memset(b->buftop, 0, sizeof(uint)*BITOUT_BUF_LEN);112 b->bufpos = b->buftop;113 b->bitbuf = 0;114 b->emplen = W_BITS;115 116

117 BITIN *createBitin(FILE *input) 118 BITIN *b = (BITIN*)malloc(sizeof(BITIN));119

120 b->input = input;121 b->bitlen = 0;122 b->bitbuf = 0;123 b->buftop = (uint*)calloc(BITIN_BUF_LEN, sizeof(uint));124 b->bufpos = b->bufend = b->buftop;125

126 return b;127 128

129 INLINE130 uint readBits(BITIN *b, uint rblen) 131 uint x;132 uint s, n;133

134 #ifndef DEBUG135 if (rblen > W_BITS) 136 fprintf(stderr, "Error: length of read bits (%d) is

longer than %d \n",137 rblen, W_BITS);138 exit (1);139 140 if (rblen == 0) 141 return 0;142 143 #endif144

145 if (rblen < b->bitlen) 146 x = b->bitbuf >> (W_BITS - rblen);147 b->bitbuf <<= rblen;

74

Page 88: emprego de gramáticas livres de contexto para a construção de um ...

148 b->bitlen -= rblen;149 150 else 151 if (b->bufpos == b->bufend) 152 n = fread(b->buftop, sizeof(uint), BITIN_BUF_LEN,

b->input);153 b->bufpos = b->buftop;154 b->bufend = b->buftop + n;155 if (b->bufend < b->buftop) 156 fprintf(stderr, "Error: new bits buffer was not

loaded.\n");157 exit(1);158 159 160

161 s = rblen - b->bitlen;162 x = b->bitbuf >> (W_BITS - b->bitlen - s);163 b->bitbuf = *(b->bufpos);164 b->bufpos++;165 b->bitlen = W_BITS - s;166 if (s != 0) 167 x |= b->bitbuf >> b->bitlen;168 b->bitbuf <<= s;169 170 171

172 return x;173

75

Page 89: emprego de gramáticas livres de contexto para a construção de um ...

A.2 bits.h

1 /*2 * Copyright (c) 2011-2012 Shirou Maruyama3 *4 * Redistribution and use in source and binary forms, with

or without5 * modification, are permitted provided that the following

conditions6 * are met:7 *8 * 1. Redistributions of source code must retain the above

Copyright9 * notice, this list of conditions and the following

disclaimer.10 *11 * 2. Redistributions in binary form must reproduce the

above Copyright12 * notice, this list of conditions and the following

disclaimer in the13 * documentation and/or other materials provided with the

distribution.14 *15 * 3. Neither the name of the authors nor the names of its

contributors16 * may be used to endorse or promote products derived from

this17 * software without specific prior written permission.18 */19

20 #ifndef BITS_H21 #define BITS_H22

23 #include <stdlib.h>24 #include <stdio.h>25 #include <string.h>26 #include <limits.h>27 #include "lcacommon.h"28

29 typedef struct bit_input 30 FILE *input;31 uint bitlen;32 uint bitbuf;33 uint *bufpos;34 uint *buftop;35 uint *bufend;36 BITIN;37

38 typedef struct bit_output 39 FILE *output;40 uint emplen;41 uint bitbuf;42 uint *bufpos;43 uint *buftop;44 uint *bufend;

76

Page 90: emprego de gramáticas livres de contexto para a construção de um ...

45 BITOUT;46

47

48 BITIN *createBitin(FILE *input);49 uint readBits(BITIN *bitin, uint readBitLen);50

51 BITOUT *createBitout(FILE *output);52 void writeBits(BITOUT *bitout, uint symbol, uint

writeBitLen);53 void flushBitout(BITOUT *bitout);54

55

56 /*57 //upper bits mask for uint58 static const uint UBM[] = 59 0x00000000,60 0x00000001, 0x00000003, 0x00000007, 0x0000000F,61 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,62 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,63 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,64 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,65 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,66 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,67 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF68 ;69

70 //lower bits mask for uint71 static const uint LBM[] = 72 0x00000000,73 0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,74 0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,75 0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000,76 0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,77 0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,78 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00,79 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0,80 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF,81 ;82 */83

84

85 #endif /* BITS_H */

77

Page 91: emprego de gramáticas livres de contexto para a construção de um ...

A.3 cfg2enc.c

1 /*2 * Copyright (c) 2016 Joao Faria3 * Copyright (c) 2011-2012 Shirou Maruyama4 *5 * Redistribution and use in source and binary forms, with

or without6 * modification, are permitted provided that the following

conditions7 * are met:8 *9 * 1. Redistributions of source code must retain the above

Copyright10 * notice, this list of conditions and the following

disclaimer.11 *12 * 2. Redistributions in binary form must reproduce the

above Copyright13 * notice, this list of conditions and the following

disclaimer in the14 * documentation and/or other materials provided with the

distribution.15 *16 * 3. Neither the name of the authors nor the names of its

contributors17 * may be used to endorse or promote products derived from

this18 * software without specific prior written permission.19 */20

21 #include "cfg2enc.h"22

23 #define INLINE __inline24

25 static void encodeCFG_rec (CODE code, EDICT *ed, BITOUT*output);

26 static void putLeaf (uint num_code, CODE lv_code, BITOUT*output);

27 static void putParen (uchar b, BITOUT *output);28

29 static INLINE30 uint bits (uint n)31 uint b = 0;32 while (n)33 b++; n >>= 1; 34 return b;35 36

37 static INLINE38 void putLeaf(uint num_code, uint lvcode, BITOUT *output) 39 uint bits_len = bits(num_code);40 writeBits(output, lvcode, bits_len);41 42

78

Page 92: emprego de gramáticas livres de contexto para a construção de um ...

43 static INLINE44 void putParen(uchar b, BITOUT *output) 45 if (b == OP) 46 writeBits(output, OP, 1);47 48 else 49 writeBits(output, CP, 1);50 51 52

53 static54 void encodeCFG_rec(uint code, EDICT *ed, BITOUT *output) 55 if (ed->tcode[code] == DUMMY_CODE) 56 encodeCFG_rec(ed->rule[code].left, ed, output);57 encodeCFG_rec(ed->rule[code].right, ed, output);58 ed->tcode[code] = ++ed->newcode;59 putParen(CP, output);60 61 else 62 putParen(OP, output);63 if (code < CHAR_SIZE) 64 putLeaf(ed->newcode, code, output);65 66 else 67 putLeaf(ed->newcode, ed->tcode[code], output);68 69 70 71

72 static73 void encodeCFG_crypt_rec(uint code, EDICT *ed, BITOUT

*output, BITOUT *key) 74 if (ed->tcode[code] == DUMMY_CODE) 75 encodeCFG_crypt_rec(ed->rule[code].left, ed, output,

key);76 encodeCFG_crypt_rec(ed->rule[code].right, ed, output,

key);77 ed->tcode[code] = ++ed->newcode;78 putParen(CP, output);79 80 else 81 putParen(OP, output);82 if (code < CHAR_SIZE) 83 putLeaf(ed->newcode, code, key);84 putLeaf(ed->newcode, DUMMY_CODE, output);85 86 else 87 putLeaf(ed->newcode, ed->tcode[code], output);88 89 90 91

92 void EncodeCFG(EDICT *ed, FILE *output) 93 BITOUT *bitout;94 printf("Encoding CFG ... ");

79

Page 93: emprego de gramáticas livres de contexto para a construção de um ...

95 fflush(stdout);96 ed->newcode = CHAR_SIZE;97 fwrite(&ed->txt_len, sizeof(uint), 1, output);98 fwrite(&ed->num_rules, sizeof(uint), 1, output);99 bitout = createBitout(output);

100 encodeCFG_rec(ed->start, ed, bitout);101 putParen(CP, bitout);102 flushBitout(bitout);103 printf("Done!\n");104 105

106 void EncodeCFG_crypt(EDICT *ed, FILE *output, FILE *key) 107 BITOUT *bitout, *bitkey;108 printf("Encoding and encrypting CFG ... ");109 fflush(stdout);110 ed->newcode = CHAR_SIZE;111 fwrite(&ed->txt_len, sizeof(uint), 1, output);112 fwrite(&ed->num_rules, sizeof(uint), 1, output);113 bitout = createBitout(output);114 bitkey = createBitout(key);115 encodeCFG_crypt_rec(ed->start, ed, bitout, bitkey);116 putParen(CP, bitout);117 flushBitout(bitout);118 flushBitout(bitkey);119 printf("Done!\n");120 121

122 EDICT *ReadCFG(FILE *input) 123 uint i;124 uint num_rules, txt_len;125 EDICT *ed;126 RULE *rule;127 CODE *tcode;128

129 fread(&txt_len, sizeof(uint), 1, input);130 fread(&num_rules, sizeof(uint), 1, input);131 rule = (RULE *)malloc(sizeof(RULE) * num_rules);132

133 printf("num_rules = %d\n", num_rules);134

135 for (i = 0; i <= CHAR_SIZE; i++) 136 rule[i].left = (CODE)i;137 rule[i].right = DUMMY_CODE;138 139

140 fread(rule+CHAR_SIZE+1, sizeof(RULE),num_rules-(CHAR_SIZE+1), input);

141

142 tcode = (CODE*)malloc(sizeof(CODE)*num_rules);143 for (i = 0; i <= CHAR_SIZE; i++) 144 tcode[i] = i;145 146 for (i = CHAR_SIZE+1; i < num_rules; i++) 147 tcode[i] = DUMMY_CODE;148

80

Page 94: emprego de gramáticas livres de contexto para a construção de um ...

149

150 ed = (EDICT *)malloc(sizeof(EDICT));151 ed->txt_len = txt_len;152 ed->num_rules = num_rules;153 ed->start = num_rules-1;154 ed->rule = rule;155 ed->tcode = tcode;156 ed->newcode = CHAR_SIZE;157 return ed;158 159

160 void DestructEDict(EDICT *ed)161 162 if (ed == NULL) return;163 if (ed->rule != NULL) free(ed->rule);164 if (ed->tcode != NULL) free(ed->tcode);165 free(ed);166

81

Page 95: emprego de gramáticas livres de contexto para a construção de um ...

A.4 cfg2enc.h

1 /*2 * Copyright (c) 2016 Joao Faria3 * Copyright (c) 2011-2012 Shirou Maruyama4 *5 * Redistribution and use in source and binary forms, with

or without6 * modification, are permitted provided that the following

conditions7 * are met:8 *9 * 1. Redistributions of source code must retain the above

Copyright10 * notice, this list of conditions and the following

disclaimer.11 *12 * 2. Redistributions in binary form must reproduce the

above Copyright13 * notice, this list of conditions and the following

disclaimer in the14 * documentation and/or other materials provided with the

distribution.15 *16 * 3. Neither the name of the authors nor the names of its

contributors17 * may be used to endorse or promote products derived from

this18 * software without specific prior written permission.19 */20

21 #ifndef CFG2ENC_H22 #define CFG2ENC_H23

24 #include<stdio.h>25 #include<stdlib.h>26 #include<string.h>27 #include<math.h>28 #include"bits.h"29 #include"lcacommon.h"30

31 typedef struct EncodeDictionary32 33 uint txt_len;34 uint num_rules;35 CODE start;36 RULE *rule;37 CODE *tcode;38 CODE newcode;39 EDICT;40

41 EDICT *ReadCFG(FILE *input);42 void EncodeCFG(EDICT *dict, FILE *output);43 void EncodeCFG_crypt(EDICT *dict, FILE *output, FILE *key);44 void DestructEDict(EDICT *dict);

82

Page 96: emprego de gramáticas livres de contexto para a construção de um ...

45

46 #endif /* CFG2ENC_H */

83

Page 97: emprego de gramáticas livres de contexto para a construção de um ...

A.5 cfg2txt.c

1 /*2 * Copyright (c) 2011-2012 Shirou Maruyama3 *4 * Redistribution and use in source and binary forms, with

or without5 * modification, are permitted provided that the following

conditions6 * are met:7 *8 * 1. Redistributions of source code must retain the above

Copyright9 * notice, this list of conditions and the following

disclaimer.10 *11 * 2. Redistributions in binary form must reproduce the

above Copyright12 * notice, this list of conditions and the following

disclaimer in the13 * documentation and/or other materials provided with the

distribution.14 *15 * 3. Neither the name of the authors nor the names of its

contributors16 * may be used to endorse or promote products derived from

this17 * software without specific prior written permission.18 */19

20 // Restore CFG_file to the TXT_file21

22 #include <stdio.h>23 #include <stdlib.h>24 #include <string.h>25 #include <math.h>26 #include "lcacommon.h"27

28 static29 void restoreString(RULE *rule, CODE code, FILE *output)30 31 CODE left, right;32

33 left = rule[code].left;34 right = rule[code].right;35 if (code == left && right == DUMMY_CODE) 36 fputc(code, output);37 else 38 restoreString(rule, left, output);39 restoreString(rule, right, output);40 41 42

43 int main(int argc, char *argv[])44

84

Page 98: emprego de gramáticas livres de contexto para a construção de um ...

45 FILE *input, *output;46 CODE start;47 uint num_rules;48 uint txt_len;49 uint i;50 RULE *rule;51

52 if (argc != 3) 53 printf("usage: %s target_cfg_file output_txt_file\n",

argv[0]);54 exit(1);55 56

57 input = fopen(argv[1], "rb");58 output = fopen(argv[2], "w");59 if (input == NULL || output == NULL) 60 puts("File open error at the beginning.");61 exit(1);62 63

64 fread(&txt_len, sizeof(uint), 1, input);65 fread(&num_rules, sizeof(uint), 1, input);66 start = num_rules - 1;67

68 rule = (RULE*)malloc(sizeof(RULE)*num_rules);69 if (rule == NULL) 70 puts("Memory allocate error.");71 exit(1);72 73

74 for (i = 0; i <= CHAR_SIZE; i++) 75 rule[i].left = i;76 rule[i].right = DUMMY_CODE;77 78

79 fread(rule+CHAR_SIZE+1, sizeof(RULE),num_rules-(CHAR_SIZE+1), input);

80 printf("Expanding CFG...");81 fflush(stdout);82 restoreString(rule, start, output);83 printf("done!!\n");84

85 fclose(input);86 fclose(output);87 free(rule);88 return;89

85

Page 99: emprego de gramáticas livres de contexto para a construção de um ...

A.6 enc2txt.c

1 /*2 * Copyright (c) 2016 Joao Faria3 * Copyright (c) 2011-2012 Shirou Maruyama4 *5 * Redistribution and use in source and binary forms, with

or without6 * modification, are permitted provided that the following

conditions7 * are met:8 *9 * 1. Redistributions of source code must retain the above

Copyright10 * notice, this list of conditions and the following

disclaimer.11 *12 * 2. Redistributions in binary form must reproduce the

above Copyright13 * notice, this list of conditions and the following

disclaimer in the14 * documentation and/or other materials provided with the

distribution.15 *16 * 3. Neither the name of the authors nor the names of its

contributors17 * may be used to endorse or promote products derived from

this18 * software without specific prior written permission.19 */20

21 #include"enc2txt.h"22

23 #define INLINE __inline24 #define OUTPUT_BUFF_SIZE 3276825

26 static char wbuffer[OUTPUT_BUFF_SIZE];27 static uint buf_pos = 0;28

29 static uint bits(uint n);30 static void expandLeaf(RULE *rule, CODE code, FILE *output);31

32 static INLINE33 uint bits (uint n)34 35 uint b = 0;36 while (n)37 b++; n >>= 1; 38 return b;39 40

41 static INLINE42 void expandLeaf(RULE *rule, CODE leaf, FILE *output) 43 if (leaf < CHAR_SIZE) 44 wbuffer[buf_pos++] = (char)leaf;

86

Page 100: emprego de gramáticas livres de contexto para a construção de um ...

45 if (buf_pos == OUTPUT_BUFF_SIZE) 46 fwrite(wbuffer, 1, OUTPUT_BUFF_SIZE, output);47 buf_pos = 0;48 49 50 else 51 expandLeaf(rule, rule[leaf].left, output);52 expandLeaf(rule, rule[leaf].right, output);53 54 55

56 void DecodeCFG(FILE *input, FILE *output) 57 uint i;58 RULE *rule;59 uint num_rules, txt_len;60 BITIN *bitin;61 uint exc, sp;62 uint stack[256];63 CODE newcode, leaf;64 uint bit_len;65 uchar paren;66

67 fread(&txt_len, sizeof(uint), 1, input);68 fread(&num_rules, sizeof(uint), 1, input);69 printf("txt_len = %d, num_rules = %d\n", txt_len,

num_rules);70 rule = (RULE*)malloc(sizeof(RULE)*num_rules);71 for (i = 0; i <= CHAR_SIZE; i++) 72 rule[i].left = (CODE)i;73 rule[i].right = DUMMY_CODE;74 75

76 for (i = CHAR_SIZE+1; i < num_rules; i++) 77 rule[i].left = DUMMY_CODE;78 rule[i].right = DUMMY_CODE;79 80

81 printf("Decompressing ... ");82 fflush(stdout);83 bitin = createBitin(input);84 newcode = CHAR_SIZE;85 exc = 0; sp = 0;86 while (1) 87 paren = readBits(bitin, 1);88 if (paren == OP) 89 exc++;90 bit_len = bits(newcode);91 leaf = readBits(bitin, bit_len);92 expandLeaf(rule, leaf, output);93 stack[sp++] = leaf;94 95 else 96 if (--exc == 0) break;97 newcode++;98 rule[newcode].right = stack[--sp];

87

Page 101: emprego de gramáticas livres de contexto para a construção de um ...

99 rule[newcode].left = stack[--sp];100 stack[sp++] = newcode;101 102 103 fwrite(wbuffer, 1, buf_pos, output);104 printf("Done!\n");105 free(rule);106 107

108 void DecodeCFG_crypt(FILE *input, FILE *output, FILE *key) 109 uint i;110 RULE *rule;111 uint num_rules, txt_len;112 BITIN *bitin, *bitkey;113 uint exc, sp;114 uint stack[256];115 CODE newcode, leaf;116 uint bit_len;117 uchar paren;118

119 fread(&txt_len, sizeof(uint), 1, input);120 fread(&num_rules, sizeof(uint), 1, input);121 printf("txt_len = %d, num_rules = %d\n", txt_len,

num_rules);122 rule = (RULE*)malloc(sizeof(RULE)*num_rules);123 for (i = 0; i <= CHAR_SIZE; i++) 124 rule[i].left = (CODE)i;125 rule[i].right = DUMMY_CODE;126 127

128 for (i = CHAR_SIZE+1; i < num_rules; i++) 129 rule[i].left = DUMMY_CODE;130 rule[i].right = DUMMY_CODE;131 132

133 printf("Decompressing ... ");134 fflush(stdout);135 bitin = createBitin(input);136 bitkey = createBitin(key);137 newcode = CHAR_SIZE;138 exc = 0; sp = 0;139 while (1) 140 paren = readBits(bitin, 1);141 if (paren == OP) 142 exc++;143 bit_len = bits(newcode);144 leaf = readBits(bitin, bit_len);145 if(leaf == DUMMY_CODE) 146 leaf = readBits(bitkey, bit_len);147 148 expandLeaf(rule, leaf, output);149 stack[sp++] = leaf;150 151 else 152 if (--exc == 0) break;

88

Page 102: emprego de gramáticas livres de contexto para a construção de um ...

153 newcode++;154 rule[newcode].right = stack[--sp];155 rule[newcode].left = stack[--sp];156 stack[sp++] = newcode;157 158 159 fwrite(wbuffer, 1, buf_pos, output);160 printf("Done!\n");161 free(rule);162

89

Page 103: emprego de gramáticas livres de contexto para a construção de um ...

A.7 enc2txt.h

1 /*2 * Copyright (c) 2016 Joao Faria3 * Copyright (c) 2011-2012 Shirou Maruyama4 *5 * Redistribution and use in source and binary forms, with

or without6 * modification, are permitted provided that the following

conditions7 * are met:8 *9 * 1. Redistributions of source code must retain the above

Copyright10 * notice, this list of conditions and the following

disclaimer.11 *12 * 2. Redistributions in binary form must reproduce the

above Copyright13 * notice, this list of conditions and the following

disclaimer in the14 * documentation and/or other materials provided with the

distribution.15 *16 * 3. Neither the name of the authors nor the names of its

contributors17 * may be used to endorse or promote products derived from

this18 * software without specific prior written permission.19 */20

21

22 #ifndef ENCODE2CFG_H23 #define ENCODE2CFG_H24

25 #include<stdio.h>26 #include<stdlib.h>27 #include<string.h>28 #include<math.h>29 #include"bits.h"30 #include"lcacommon.h"31

32 void DecodeCFG(FILE *input, FILE *output);33 void DecodeCFG_crypt(FILE *input, FILE *output, FILE *key);34

35 #endif /* ENCODE2CFG_H */

90

Page 104: emprego de gramáticas livres de contexto para a construção de um ...

A.8 lcacommon.h

1 /*2 * Copyright (c) 2011-2012 Shirou Maruyama3 *4 * Redistribution and use in source and binary forms, with

or without5 * modification, are permitted provided that the following

conditions6 * are met:7 *8 * 1. Redistributions of source code must retain the above

Copyright9 * notice, this list of conditions and the following

disclaimer.10 *11 * 2. Redistributions in binary form must reproduce the

above Copyright12 * notice, this list of conditions and the following

disclaimer in the13 * documentation and/or other materials provided with the

distribution.14 *15 * 3. Neither the name of the authors nor the names of its

contributors16 * may be used to endorse or promote products derived from

this17 * software without specific prior written permission.18 */19

20 #include <stdbool.h>21

22 #ifndef LCACOMMON_H23 #define LCACOMMON_H24

25 #ifndef LOG226 # define LOG2(X) (log((double)(X))/log((double)2))27 #endif28

29 #ifndef uchar30 typedef unsigned char uchar;31 #endif32 #ifndef uint33 typedef unsigned int uint;34 #endif35 #ifndef ulong36 typedef unsigned long ulong;37 #endif38

39 #ifndef __bool_true_false_are_defined40 #define __bool_true_false_are_defined41 typedef _Bool bool;42 #define false 043 #define true 144 #endif

91

Page 105: emprego de gramáticas livres de contexto para a construção de um ...

45

46 #ifndef CODE47 typedef unsigned int CODE;48 #endif49

50 typedef struct Rule 51 CODE left;52 CODE right;53 RULE;54

55 #define CHAR_SIZE 25656 #define DUMMY_CODE (CODE)25657

58 #define OP 159 #define CP 060

61 static const uint primes[] = 62 /* 0*/ 8 + 3,63 /* 1*/ 16 + 3,64 /* 2*/ 32 + 5,65 /* 3*/ 64 + 3,66 /* 4*/ 128 + 3,67 /* 5*/ 256 + 27,68 /* 6*/ 512 + 9,69 /* 7*/ 1024 + 9,70 /* 8*/ 2048 + 5,71 /* 9*/ 4096 + 3,72 /*10*/ 8192 + 27,73 /*11*/ 16384 + 43,74 /*12*/ 32768 + 3,75 /*13*/ 65536 + 45,76 /*14*/ 131072 + 29,77 /*15*/ 262144 + 3,78 /*16*/ 524288 + 21,79 /*17*/ 1048576 + 7,80 /*18*/ 2097152 + 17,81 /*19*/ 4194304 + 15,82 /*20*/ 8388608 + 9,83 /*21*/ 16777216 + 43,84 /*22*/ 33554432 + 35,85 /*23*/ 67108864 + 15,86 /*24*/ 134217728 + 29,87 /*25*/ 268435456 + 3,88 /*26*/ 536870912 + 11,89 /*27*/ 1073741824 + 85,90 091 ;92

93 #endif /* LCACOMMON_H */

92

Page 106: emprego de gramáticas livres de contexto para a construção de um ...

A.9 lcacomp.c

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include "txt2cfg_online.h"5 #include "cfg2enc.h"6 #include "enc2txt.h"7

8 EDICT *convertDict(DICT *dict)9

10 EDICT *edict = (EDICT*)malloc(sizeof(EDICT));11 uint i;12 edict->txt_len = dict->txt_len;13 edict->start = dict->num_rules-1;14 edict->rule = dict->rule;15 edict->num_rules = dict->num_rules;16 edict->tcode = dict->h_list;17 edict->newcode = CHAR_SIZE;18

19 for (i = 0; i <= CHAR_SIZE; i++) 20 edict->tcode[i] = i;21 22 for (i = CHAR_SIZE+1; i < dict->num_rules; i++) 23 edict->tcode[i] = DUMMY_CODE;24 25

26 free(dict->h_entry);27 free(dict);28 return edict;29 30

31 int decompression(char *input_filename, char*output_filename)

32 33 FILE *input, *output;34

35 input = fopen(input_filename, "rb");36 output = fopen(output_filename, "w");37 if (input == NULL || output == NULL) 38 printf("File open error.\n");39 return 0;40 41 DecodeCFG(input, output);42 fclose(input); fclose(output);43 return 1;44 45

46 int compression(char *input_filename, char *output_filename)47 48 FILE *input, *output;49 DICT *dict;50 EDICT *edict;51

52 input = fopen(input_filename, "r");

93

Page 107: emprego de gramáticas livres de contexto para a construção de um ...

53 output = fopen(output_filename, "wb");54 if (input == NULL || output == NULL) 55 puts("File open error at the beginning.");56 return 0;57 58

59 dict = GrammarTrans_LCA(input);60 edict = convertDict(dict);61

62 EncodeCFG(edict, output);63 DestructEDict(edict);64 fclose(input);65 fclose(output);66 return 1;67 68

69 void printUsage(char *program_name)70 71 printf("\n");72 printf("---Usage-------------------------------------------------------------\n");73 printf("%s (c|d) <input_file> <output_file>\n",

program_name);74 printf("c = Compresses <input_file> with LCA-online and

creates <output_file>.\n");75 printf("d = Decompresses <input_file> and creates

<output_file>.\n");76 printf("---------------------------------------------------------------------\n");77 printf("\n");78 79

80 int main(int argc, char *argv[])81 82

83 if (argc != 4) 84 printUsage(argv[0]);85 exit(0);86 87

88 if (!strcmp(argv[1], "c")) 89 compression(argv[2], argv[3]);90 91 else if (!strcmp(argv[1], "d")) 92 decompression(argv[2], argv[3]);93 94 else 95 printf("Unexpected argment!\n");96 printUsage(argv[0]);97 exit(1);98 99

100 exit(0);101

94

Page 108: emprego de gramáticas livres de contexto para a construção de um ...

A.10 lcacrypt.c

1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include "txt2cfg_online.h"5 #include "cfg2enc.h"6 #include "enc2txt.h"7

8 EDICT *convertDict(DICT *dict)9

10 EDICT *edict = (EDICT*)malloc(sizeof(EDICT));11 uint i;12 edict->txt_len = dict->txt_len;13 edict->start = dict->num_rules-1;14 edict->rule = dict->rule;15 edict->num_rules = dict->num_rules;16 edict->tcode = dict->h_list;17 edict->newcode = CHAR_SIZE;18

19 for (i = 0; i <= CHAR_SIZE; i++) 20 edict->tcode[i] = i;21 22 for (i = CHAR_SIZE+1; i < dict->num_rules; i++) 23 edict->tcode[i] = DUMMY_CODE;24 25

26 free(dict->h_entry);27 free(dict);28 return edict;29 30

31 int decompression(char *input_filename, char*output_filename, char *key_filename)

32 33 FILE *input, *output, *key;34

35 input = fopen(input_filename, "rb");36 key = fopen(key_filename, "rb");37 output = fopen(output_filename, "w");38 if (input == NULL || output == NULL || key == NULL) 39 printf("File open error.\n");40 return 0;41 42 DecodeCFG_crypt(input, output, key);43 fclose(input); fclose(output); fclose(key);44 return 1;45 46

47 int compression(char *input_filename, char*output_filename, char *key_filename)

48 49 FILE *input, *output, *key;50 DICT *dict;51 EDICT *edict;

95

Page 109: emprego de gramáticas livres de contexto para a construção de um ...

52

53 input = fopen(input_filename, "r");54 output = fopen(output_filename, "wb");55 key = fopen(key_filename, "wb");56 if (input == NULL || output == NULL || key == NULL) 57 puts("File open error at the beginning.");58 return 0;59 60

61 dict = GrammarTrans_LCA(input);62 edict = convertDict(dict);63

64 EncodeCFG_crypt(edict, output, key);65 DestructEDict(edict);66 fclose(input);67 fclose(output);68 fclose(key);69 return 1;70 71

72 void printUsage(char *program_name)73 74 printf("\n");75 printf("---Usage--------------------------------------------------------------------------------------\n");76 printf("%s (c|d) <input_file> <output_file>

<key_file>\n", program_name);77 printf("c = Compresses/encrypts <input_file> with

LCA-online and creates <output_file> and<key_file>.\n");

78 printf("d = Decompresses/decrypts <input_file> with<key_file> and creates <output_file>.\n");

79 printf("----------------------------------------------------------------------------------------------\n");80 printf("\n");81 82

83 int main(int argc, char *argv[])84 85

86 if (argc != 5) 87 printUsage(argv[0]);88 exit(0);89 90

91 if (!strcmp(argv[1], "c")) 92 compression(argv[2], argv[3], argv[4]);93 94 else if (!strcmp(argv[1], "d")) 95 decompression(argv[2], argv[3], argv[4]);96 97 else 98 printf("Unexpected argment!\n");99 printUsage(argv[0]);

100 exit(1);101 102

96

Page 110: emprego de gramáticas livres de contexto para a construção de um ...

103 exit(0);104

97

Page 111: emprego de gramáticas livres de contexto para a construção de um ...

A.11 txt2cfg online.c

1 /*2 * Copyright (c) 2011-2012 Shirou Maruyama3 *4 * Redistribution and use in source and binary forms, with

or without5 * modification, are permitted provided that the following

conditions6 * are met:7 *8 * 1. Redistributions of source code must retain the above

Copyright9 * notice, this list of conditions and the following

disclaimer.10 *11 * 2. Redistributions in binary form must reproduce the

above Copyright12 * notice, this list of conditions and the following

disclaimer in the13 * documentation and/or other materials provided with the

distribution.14 *15 * 3. Neither the name of the authors nor the names of its

contributors16 * may be used to endorse or promote products derived from

this17 * software without specific prior written permission.18 */19

20 #include "txt2cfg_online.h"21

22 //#define DEBUG23 #define INLINE __inline24

25 #define INIT_RLBUF_LEN (256*1024) //initial size of bufferfor rule[]

26 #define RLBUF_RESIZE_FACTOR (1.5) //resize factor of bufferfor rule[].

27 #define INIT_PRIMES_INDEX (13) //initial value of primes[].28 #define HASH_LOAD_FACTOR (1.0) //load factor of hash entry.29 #define INPUT_BUFFER_SIZE (32*1024) // size of input buffer.30 #define MAX_LEN_QUE (8) // maximum length of queue.31 #define MOD(X) ((X) % MAX_LEN_QUE) //compute index of que[].32 #define hash_val(BUF_LEN, A, B) (((A)*(B))%BUF_LEN)33 //#define hash_val(BUF_LEN, A, B)

((((A)<<16)|(B)>>16)%BUF_LEN)34 //#define hash_val(BUF_LEN, A, B) ((A+(A<<16)^B)%BUF_LEN)35

36 typedef struct Queue 37 CODE w[MAX_LEN_QUE];38 uint bpos;39 uint epos;40 uint num;41 struct Queue *next;

98

Page 112: emprego de gramáticas livres de contexto para a construção de um ...

42 QU;43

44 //Inner function declaration.45 static QU *createQueue ();46 static void destructQueues (QU *q);47 static void enQueue (QU *q, CODE c);48 static CODE deQueue (QU *q);49 static CODE refQueue (QU *q, uint i);50 static bool isRepetition (QU *q, uint i);51 static bool isMinimal (QU *q, uint i);52 static uint computeLCAd (CODE i, CODE j);53 static bool isMaximal (QU *q, uint i);54 static bool isPair (QU *q);55 static void resizeDict (DICT *d);56 static void rehash (DICT *d);57 static CODE addRule2Dictionary (DICT *d, CODE left, CODE

right);58 static CODE searchRule (DICT *d, CODE left, CODE right);59 static CODE reverseAccess (DICT *d, CODE left, CODE right);60 static DICT *createDictionary ();61 static void grammarTrans_rec (DICT *d, QU *q, CODE c);62

63 static64 QU *createQueue() 65 uint i;66 QU *q = (QU*)malloc(sizeof(QU));67

68 for (i = 0; i < MAX_LEN_QUE; i++) 69 q->w[i] = DUMMY_CODE;70 71 q->bpos = 0;72 q->epos = 0;73 q->num = 1;74 q->next = NULL;75

76 return q;77 78

79 static INLINE80 void enQueue(QU *q, CODE c)81 82 q->epos = MOD(q->epos+1);83 q->w[q->epos] = c;84 q->num++;85 86

87 static INLINE88 CODE deQueue(QU *q)89 90 register CODE x = q->w[q->bpos];91

92 q->bpos = MOD(q->bpos+1);93 q->num--;94 return x;95

99

Page 113: emprego de gramáticas livres de contexto para a construção de um ...

96

97 static INLINE98 CODE refQueue(QU *q, uint i)99

100 return q->w[MOD(q->bpos+i)];101 102

103 static104 void destructQueues(QU *q)105 106 if (q == NULL) 107 return;108 109 destructQueues(q->next);110 free(q);111 112

113 static INLINE114 bool isRepetition(QU *q, uint i)115 116 register CODE w1 = refQueue(q, i);117 register CODE w2 = refQueue(q, i+1);118

119 if (w1 == w2) 120 return true;121 122 return false;123 124

125 static INLINE126 bool isMinimal(QU *q, uint i)127 128 register CODE w0 = refQueue(q, i-1);129 register CODE w1 = refQueue(q, i);130 register CODE w2 = refQueue(q, i+1);131

132 if ((w0 > w1) && (w1 < w2)) 133 return true;134 else 135 return false;136 137 138

139 static INLINE140 uint computeLCAd(CODE i, CODE j)141 142 register uint Ni, Nj;143 register uint x;144

145 Ni = 2*i - 1;146 Nj = 2*j - 1;147 x = Ni ^ Nj;148 x = (uint)floor(LOG2(x));149 return x;150

100

Page 114: emprego de gramáticas livres de contexto para a construção de um ...

151

152 static INLINE153 bool isMaximal(QU *q, uint i)154 155 register CODE w0 = refQueue(q, i-1);156 register CODE w1 = refQueue(q, i);157 register CODE w2 = refQueue(q, i+1);158 register CODE w3 = refQueue(q, i+2);159

160 if (!(w0 < w1 && w1 < w2 && w2 < w3) &&161 !(w0 > w1 && w1 > w2 && w2 > w3))162 163 return false;164 165

166 if (computeLCAd(w1,w2) > computeLCAd(w0,w1) &&167 computeLCAd(w1,w2) > computeLCAd(w2,w3))168 169 return true;170 171 else172 173 return false;174 175 176

177 static INLINE178 bool isPair(QU *q) 179 if (isRepetition(q, 1)) 180 return true;181 182 else if (isRepetition(q, 2)) 183 return false;184 185 else if (isRepetition(q, 3)) 186 return true;187 188 else if (isMinimal(q, 1) || isMaximal(q, 1)) 189 return true;190 191 else if (isMinimal(q, 2) || isMaximal(q, 2)) 192 return false;193 194 return true;195 196

197 static INLINE198 void rehash(DICT *d)199 200 uint i;201 uint h;202 CODE temp;203

204 if ((d->hebuf_len = primes[++d->p_idx]) == 0) 205 puts("size of hash table is overflow.");

101

Page 115: emprego de gramáticas livres de contexto para a construção de um ...

206 exit(1);207 208 d->h_entry = (CODE*)realloc(d->h_entry,

d->hebuf_len*sizeof(CODE));209 if (d->h_entry == NULL) 210 puts("Memory reallocate error (h_entry) at rehash.");211 exit(1);212 213 for (i = 0; i < d->hebuf_len; i++) 214 d->h_entry[i] = (uint)DUMMY_CODE;215 216 for (i = CHAR_SIZE+1; i < d->num_rules; i++) 217 d->h_list[i] = DUMMY_CODE;218 219 for (i = d->num_rules-1; i > CHAR_SIZE; i--) 220 h = hash_val(d->hebuf_len, d->rule[i].left,

d->rule[i].right);221 temp = d->h_entry[h];222 d->h_entry[h] = i;223 if (temp != DUMMY_CODE) 224 d->h_list[i] = temp;225 226 227 228

229 static INLINE230 void resizeDict(DICT *d)231 232 d->rlbuf_len *= RLBUF_RESIZE_FACTOR;233 d->rule = (RULE*)realloc(d->rule,

d->rlbuf_len*sizeof(RULE));234 if (d->rule == NULL) 235 puts("Memory reallocate error (rule) at resizeDict.");236 exit(1);237 238 d->h_list = (CODE*)realloc(d->h_list,

d->rlbuf_len*sizeof(CODE));239 if (d->h_list == NULL) 240 puts("Memory reallocate error (h_list) at resizeDict.");241 exit(1);242 243 244

245 static INLINE246 CODE addRule2Dictionary(DICT *d, CODE left, CODE right)247 248 CODE new_key = d->num_rules++;249 CODE temp;250 uint h;251

252 if (d->num_rules > d->rlbuf_len) 253 resizeDict(d);254 255 if (d->num_rules > (uint)(d->hebuf_len*HASH_LOAD_FACTOR))

102

Page 116: emprego de gramáticas livres de contexto para a construção de um ...

256 rehash(d);257 258

259 d->rule[new_key].left = left;260 d->rule[new_key].right = right;261

262 if (new_key > DUMMY_CODE) 263 h = hash_val(d->hebuf_len, left, right);264 temp = d->h_entry[h];265 d->h_entry[h] = new_key;266 if (temp != DUMMY_CODE) 267 d->h_list[new_key] = temp;268 269 else 270 d->h_list[new_key] = DUMMY_CODE;271 272 273 return new_key;274 275

276 static INLINE277 CODE searchRule(DICT *d, CODE left, CODE right)278 279 register CODE key;280 register uint h;281

282 h = hash_val(d->hebuf_len, left, right);283 key = d->h_entry[h];284 while (key != DUMMY_CODE) 285 if (d->rule[key].left == left && d->rule[key].right ==

right) 286 return key;287 else 288 key = d->h_list[key];289 290 291 return DUMMY_CODE;292 293

294 static INLINE295 CODE reverseAccess(DICT *d, CODE left, CODE right)296 297 register CODE R;298

299 if ((R = searchRule(d, left, right)) == DUMMY_CODE) 300 R = addRule2Dictionary(d, left, right);301 302 return R;303 304

305 static306 DICT *createDictionary()307 308 uint i;309 DICT *d;

103

Page 117: emprego de gramáticas livres de contexto para a construção de um ...

310

311 d = (DICT*)malloc(sizeof(DICT));312 d->rlbuf_len = INIT_RLBUF_LEN;313 d->p_idx = INIT_PRIMES_INDEX;314 d->hebuf_len = primes[d->p_idx];315

316 d->rule = (RULE*)malloc(d->rlbuf_len*sizeof(RULE));317 if (d->rule == NULL) 318 puts("Memory allocate error (rule) at

createDictionary.");319 exit(1);320 321 d->h_entry = (CODE*)malloc(d->hebuf_len*sizeof(CODE));322 if (d->h_entry == NULL) 323 puts("Memory allocate error (h_entry) at

createDictionary.");324 exit(1);325 326 for (i = 0; i < d->hebuf_len; i++) 327 d->h_entry[i] = DUMMY_CODE;328 329

330 d->h_list = (CODE*)malloc(d->rlbuf_len*sizeof(CODE));331 if (d->h_list == NULL) 332 puts("Memory allocate error (h_list) at

createDictionary.");333 exit(1);334 335 for (i = 0; i < d->rlbuf_len; i++) 336 d->h_list[i] = DUMMY_CODE;337 338 for (i = 0; i < CHAR_SIZE; i++) 339 addRule2Dictionary(d, i, DUMMY_CODE);340 341 addRule2Dictionary(d, DUMMY_CODE, DUMMY_CODE);342 return d;343 344

345 static INLINE346 void grammarTrans_rec(DICT *d, QU *p, CODE c)347 348 QU *q;349 CODE v, x1, x2, x3;350

351 if (p->next == NULL) 352 q = p->next = createQueue();353 354 else 355 q = p->next;356 357

358 enQueue(q, c);359 if (q->num == MAX_LEN_QUE) 360 if (isPair(q) == true) 361 deQueue(q);

104

Page 118: emprego de gramáticas livres de contexto para a construção de um ...

362 x1 = deQueue(q); x2 = refQueue(q, 0);363 v = reverseAccess(d, x1, x2);364 grammarTrans_rec(d, q, v);365 366 else 367 deQueue(q);368 x1 = deQueue(q);369 grammarTrans_rec(d, q, x1);370 x2 = deQueue(q); x3 = refQueue(q, 0);371 v = reverseAccess(d, x2, x3);372 grammarTrans_rec(d, q, v);373 374 375 376

377 DICT *GrammarTrans_LCA(FILE *input)378 379 uchar *w, *w_top;380 uint lg;381 QU *dummy_que, *que;382 CODE v, x1, x2;383 DICT *d;384 long cnt = 0;385

386 dummy_que = createQueue();387 d = createDictionary();388

389 printf("Grammar Transforming ...\n");390 w_top = (uchar*)malloc(sizeof(uchar)*INPUT_BUFFER_SIZE);391 while ((lg = fread(w_top, sizeof(uchar),

INPUT_BUFFER_SIZE, input)) > 0) 392 cnt += lg;393 w = w_top;394 do 395 grammarTrans_rec(d, dummy_que, *w++);396 while (--lg > 0);397 printf("\r");398 printf("[ %12ld ] bytes -> [ %10d ] rules.", cnt,

d->num_rules);399 fflush(stdout);400 401 d->txt_len = cnt;402

403 que = dummy_que->next;404 while (que->next != NULL || que->num > 2) 405 deQueue(que);406 while (que->num > 1) 407 x1 = deQueue(que); x2 = deQueue(que);408 v = reverseAccess(d, x1, x2);409 grammarTrans_rec(d, que, v);410 411 if (que->num == 1) 412 x1 = deQueue(que);413 grammarTrans_rec(d, que, x1);414

105

Page 119: emprego de gramáticas livres de contexto para a construção de um ...

415 que = que->next;416 417

418 printf("\r");419 printf("[ %12ld ] bytes -> [ %10d ] rules.\n", cnt,

d->num_rules);420 free(w_top);421 destructQueues(dummy_que);422 return d;423 424

425 void OutputGeneratedCFG(DICT *d, FILE *output)426 427 fwrite(&d->txt_len, sizeof(uint), 1, output);428 fwrite(&d->num_rules, sizeof(uint), 1, output);429 fwrite(d->rule+CHAR_SIZE+1, sizeof(RULE),430 d->num_rules-(CHAR_SIZE+1), output);431 432

433 void DestructDict(DICT *d)434 435 if (d == NULL) return;436 if (d->rule != NULL) free(d->rule);437 if (d->h_entry != NULL) free(d->h_entry);438 if (d->h_list != NULL) free(d->h_list);439 free(d);440

106

Page 120: emprego de gramáticas livres de contexto para a construção de um ...

A.12 txt2cfg online.h

1 /*2 * Copyright (c) 2011-2012 Shirou Maruyama3 *4 * Redistribution and use in source and binary forms, with

or without5 * modification, are permitted provided that the following

conditions6 * are met:7 *8 * 1. Redistributions of source code must retain the above

Copyright9 * notice, this list of conditions and the following

disclaimer.10 *11 * 2. Redistributions in binary form must reproduce the

above Copyright12 * notice, this list of conditions and the following

disclaimer in the13 * documentation and/or other materials provided with the

distribution.14 *15 * 3. Neither the name of the authors nor the names of its

contributors16 * may be used to endorse or promote products derived from

this17 * software without specific prior written permission.18 */19

20 #ifndef TXT2CFG_ONLINE_H21 #define TXT2CFG_ONLINE_H22

23 #include <stdio.h>24 #include <stdlib.h>25 #include <string.h>26 #include <math.h>27 #include "lcacommon.h"28

29 typedef struct Dictionary 30 uint txt_len;31 uint num_rules;32 RULE *rule;33 CODE *h_entry;34 CODE *h_list;35 uint rlbuf_len;36 uint p_idx;37 uint hebuf_len;38 DICT;39

40 // function prototype declarations41 DICT *GrammarTrans_LCA (FILE *input);42 void OutputGeneratedCFG (DICT *d, FILE *output);43 void DestructDict (DICT *d);44

107

Page 121: emprego de gramáticas livres de contexto para a construção de um ...

45 #endif /* TXT2CFG_ONLINE_H */

108