LIDA: Entendendo a Arquitetura
LIDA Framework
A LIDA Framework é uma library Java que permite a construção de agentes LIDA, fornecendo um "esqueleto" base para a construção do agente. O comportamento inteligente do agente é implementado por meio do uso de classes Java, sendo também necessário alterar alguns parâmetros de configuração das classes por meio de arquivos XML. O LIDA Framework também disponibiliza uma interface gráfica para a visualização, em tempo real, do conteúdo de cada módulo e dos valores de parâmetros e variáveis, além de outras informações.
LIDA Model
O LIDA Framework baseia-se no LIDA Model, exibido na figura acima, cuja intenção é cobrir uma grande porção da cognição humana. O modelo baseia-se na Global Workspace Theory de Baars. Neste modelo, o Ciclo Cognitivo (estudado anteriormente) será responsável pela percepção, atenção e ação do agente. Durante o ciclo cognitivo, o agente percebe seu ambiente externo e interno, gerando uma representação da situação corrente. Por meio de um processo competitivo, definido pela teoria do Global Workspace de Baars, o agente decide qual porção da situação corrente representada é mais relevante e, portanto, digna da atenção do agente, naquele momento. Ao fazer um broadcast do seu conteúdo consciente, o agente poderá escolher apropriadamente uma ação e então executá-la. O processo de aprendizado do agente também ocorre durante o broadcast.
Os módulos do LIDA Model são implementados, via linguagem Java, no LIDA Framework. Todos os módulos e processos estão disponíveis para uso; no entanto, não precisam ser necessariamente todos implementados pelo agente LIDA. A interface FrameworkModule implementa um módulo genérico. Módulos específicos são implementados por uma interface específica; por exemplo, o módulo Procedural Memory é implementado pela interface ProceduralMemory. Os módulos de processos são implementados por meio de tasks de vários tipos que são implementações da interface FrameworkTask. A execução assíncrona é implementada pela execução concorrente de tasks que são gerenciadas pelo TaskManager. A comunicação entre os módulos é implementada por meio de listeners que implementam a interface ModuleListener. Nodes e Links são implementados usando NodeStructures que consistem de Nodes e Links. A ativação dos Nodes e Links, além de outros elementos do LIDA Model, é realizada pela implementação da interface Activatible. Essa implementação também inclui Strategies que controlam o decaimento e a excitação desses elementos.
Um exemplo de uso seria implementar o broadcast consciente do LIDA Model. O módulo GlobalWorkspace deve ser implementado e todos os módulos do Framework LIDA, que estão sendo usados pelo agente, devem implementar a interface BroadcastListener e se registrarem como listeners no módulo GlobalWorkspace.
LIDA Framework: Aspectos Básicos
Modules and Listeners
Os módulos da arquitetura LIDA são divididos em duas classes: módulos dependentes do domíno do problema, e, módulos independentes do domínio do problema em questão. Os módulos perceptuais e de ação, Sensory Memory e Sensory-Motor Memory, são dependentes do problema abordado. Os módulos independentes do contexto da aplicação (por exemplo, Workspace) possuem implementações default, fornecidas pelo LIDA Framework, que podem ser customizadas. Implementações abstratas dos módulos dependentes do problema também são fornecidas; essas classes devem ser estendidas para cada aplicação em particular. Os módulos podem ainda conter sub-módulos. Por exemplo, Workspace contém o sub-módulo Current Situational Model. Os módulos são especificados pela interface FrameworkModule. Uma implementação default, FrameworkModuleImpl, é fornecida; os módulos que estendem essa classe herdam um nome, nenhum ou alguns sub-módulos, e um TaskSpawner. Esse objeto ajuda a rodar tarefas (tasks). Essa implementação default especifica uma estrutura para o decaimento do módulo e de seus sub-módulos; cada módulo específico deve implementar seu próprio algoritmo de decaimento. A interface FrameworkModuleImpl também define um método default para adicionar listeners que deve ser sobreescrito por cada módulo específico. Cada módulo customizado deve estender esta interface e implementar sua própria interface. Por exemplo, a implementação do módulo Sensory Memory estende a interface FrameworkModuleImpl e implementa a interface SensoryMemory.
Os módulos devem passar informações entre si para assegurar a conectividade do sistema. O LIDA Framework utiliza um padrão de projeto, Observer Pattern, para implementar a comunicação entre os módulos. Muitos módulos no LIDA Framework possuem uma interface Listener que especifica os métodos necessários para receber o conteúdo do módulo. Todo módulo que necessitar receber comunicação de algum outro módulo deve implementar essa interface e se registrar, como "ouvinte", no módulo que enviará as informações. Um exemplo do uso do Observer Pattern é o relacionamento entre o módulo GlobalWorkspace e a interface BroadcastListener. No LIDA Model, todos os módulos devem receber conteúdo consciente do módulo GlobalWorkspace; para isso, os módulos devem implementar a interface BroadcastListener. Cada módulo ouvinte deve se registrar no módulo GlobalWorkspace usando seu próprio método addBroadcastListener. Quando o módulo GlobalWorkspace precisar realizar o broadcast para os outros módulos, basta chamar o método receiveBroadcast de cada módulo (listener) registrado. Os listeners também são usados para implementar a comunicação entre um módulo e seus sub-módulos. Os módulos são associados por meio do método addAssociatedModule da interface FrameworkModule.
Tasks, TaskSpawners, and the TaskManager
No LIDA Framework, os processos do LIDA Model são implementados por meio de FrameworkTasks (tasks). Uma task pode ser associada a figura do demon da teoria do Pandemonium de Jackson’s. Ou ainda, associada ao conceito de codelet. Cada aplicação usando um agente LIDA possui um único objeto TaskManager. Esse objeto usa um pool de threads para a execução das tasks. Os módulos não usam diretamente esse objeto; ao invés disso, cada módulo possui um objeto TaskSpawner associado a ele. Este objeto trabalha diretamente com o TaskManager. O TaskManager controla o tempo da aplicação. A unidade de tempo é denominada tick. Cada task possui um tick programado, um algoritmo contido no seu método runThisFrameworkTask, e um status. As tasks podem rodar uma única vez ou repetidas vezes; essa frequência é definida pelo atributo ticksPerRun da task. Durante a execução da tarefa, seu status pode mudar e, depois da execução, a task retorna para o TaskSpawner que a originou. O TaskSpawner pode então processar o resultado da task e decidir se esta deve ser re-agendada.
O TaskManager recebe as tasks que deve ser rodadas dos TaskSpawner's. Ele programa a execução das tasks numa fila chamada task queue. Essa fila é ordenada pelos ticks e cada posição na fila contém as tasks que devem ser executadas durante aquele tick. O ciclo do TaskManager segue a seguinte sequência: decaimento de todos os módulos; execução de todas as tasks agendadas para o tick corrente, aguardando suas execuções; possível atualização da GUI (Interface Gráfica); e, incremento do tick corrente. Alguns métodos permitem pausar ou interromper a execução do ciclo anterior. A GUI disponibiliza botões que disparam esses métodos. O tempo de duração da simulação pode também ser alterado pela configuração da duração de um tick. No arquivo de declaração do agente, o TaskManager pode ser configurado através de dois parâmetros: tickDuration e maxNumberOfThreads. O primeiro parâmetro determina o tempo de duração de um tick; o segundo parâmetro determina o tamanho do thread pool usado pelo TaskManager. A GUI também permite ajustar a duração do tick.
Nodes, Links, and NodeStructures
Os Nodes e Links são as principais estruturas do LIDA Framework. Ambos possuem uma ativação e uma medida de saliência corrente que podem ser excitadas em muitas situações e que decaem ao longo do tempo. Um Node pode representar traços característicos (features), objetos, eventos, conceitos, sentimentos, ações, etc. Todos os Nodes pertencem a um Node, no PAM, chamado PamNode. Os Nodes são instâncias do PamNode. Cada Node de uma simulação refere-se ao seu PamNode originário em PAM; além de possuir um ID único que o identifica.
Um Link conecta um Node a outro Node ou Link. Os Links tem um atributo LinkCategory que especifica a natureza do relacionamento representado pelo Link. Por exemplo, uma "bola vermelha" pode ser representada por um Node "bola" ligado a um Node "vermelho" por um Link com um LinkCategory "feature". Ambos Nodes e Links implementam a interface Linkable e possuem um identificador único, ExtendedId. Os Nodes e Links são criados dinamicamente pelo ElementFactory.
O NodeStructure é uma estrutura em grafo composta por Nodes e Links e é uma "moeda comum" para a troca de informação entre os módulos. A implementação do NodeStructureImpl provê métodos para adicionar, remover, ou recuperar e manipular os Nodes e Links contidos dentro dele.
Activation and Strategies
Nodes, Links e outros elementos tais como coalisões, codelets, schemes, e comportamentos (behaviors) tem uma ativação. A ativação é representada por um número entre 0 e 1. Geralmente, a ativação representa a saliência de um elemento. Os elementos mencionados acima tem uma ativação corrente que mede sua saliência no momento corrente. Outros elementos possuem uma ativação adicional, chamada base-level activation, que é usada para implementar o aprendizado. Essas funcionalidades são disponibilizadas pelas interfaces Activatible e Learnable.
Um elemento Activatible possui métodos (excite e decay) para regular sua ativação adequadamente. Os elementos são normalmente removidos se sua ativação cai abaixo de um certo valor (removal threshold). O elemento Activatible deve especificar duas Strategies para determinar como seu nível de ativação muda quando seus métodos excite e decay são chamados. Um elemento Learnable é uma extensão de Activatible. Esse elemento adiciona a base-level activation para a implementação do aprendizado. Um PamNode é um exemplo de um elemento Learnable; a base-level activation pode corresponder à utilidade do conceito representado pelo PamNode.
O LIDA Framework usa o padrão de projeto Strategy para implementar a excitação e o decaimento dos elementos Activatible. Há implementações default para excitação linear, excitação sigmóide, decaimento linear e sigmóide providos pelo LIDA Framework. As Strategies são obtidas do ElementFactory.
Framework Tools
O ElementFactory permite criar novas instâncias de muitos dos elementos existentes no LIDA Framework, tais como: Nodes, Links, tasks, Strategies. Cada definição do tipo de elemento a ser instanciado pelo ElementFactory possui um nome que será usado para requisitar uma nova instância desse tipo de elemento. Os tipos de elementos que o ElementFactory pode produzir podem ser configurados no arquivo factoryData.xml.
O LIDA Framework inclui uma GUI (Graphical User Interface) customizável que permite visualizar, em tempo real, o conteúdo de cada módulo da arquitetura, os valores dos parâmetros, as tasks que estão rodando, além de outras variáveis interessantes de se visualizar durante a operação do agente LIDA. O arquivo de propriedades, “GUI Panels”, permite adicionar painéis default ou customizados, além de configurar a aparência dos GUI Panels na GUI do LIDA Framework.
LIDA Framework: Inicialização
O pacote Java, initialization, do LIDA Framework, contém as classes envolvidas na simulação do agente. A classe AgentStarter provê métodos para rodar a simulação do agente. Também provê um método Main que pode ser executado pela linha de comando com um parâmetro especificando o caminho do arquivo primary configuration. O método start do AgentStarter efetua os seguintes passos: Carrega as definições dos tipos de elementos contidos no arquivo factory data; Cria uma instância da classe Agent baseada no conteúdo do arquivo agent declaration; Se a propriedade lida.gui.enable, no arquivo de configuração principal, estiver configurada como true, a GUI será criada usando-se as informações contidas nos arquivos de configuração da GUI; O agente é carregado; A GUI é carregada e exibida.
The Agent Declaration File
Esse arquivo está especificado na propriedade lida.agentdata do arquivo de configuração principal. O arquivo contém a declaração dos componentes do agente. Este arquivo é um documento XML que contém a tag raiz <lida>, além das seguintes tags: <globalparams>, contém os parâmetros usados durante o processo de inicialização dos módulos; <taskmanager>, contém os parâmetros para a configuração do TaskManager; <taskspawners>, contém sub-tags do tipo <taskspawner> que declaram os tipos de TaskSpawner disponíveis para os módulos do agente; <submodules>, contém sub-tags do tipo <module> que especificam as classes e os parâmetros necessários para criar os módulos do agente, além de poderem conter outras sub-tags tais como <associatedmodule>, <initialtasks>, <initializerclass>, ou mesmo <submodules>; <listeners>, contém sub-tags do tipo <listener> que declaram os listeners que conectam os módulos do agente.
AgentXMLFactory
A classe AgentXMLFactory carrega o arquivo de declaração do agente, efetua o seu parser, cria os componentes declarados no arquivo, e monta-o no objeto Agent. O método getAgent efetua as seguintes ações: Os parâmetros globais (opcionais) são lidos e acrescentados à classe GlobalInitializer; É criado o TaskManager; Os TaskSpawners são criados; Os módulos são criados e seus métodos init são chamados; As conexões ModuleListener são estabelecidas; Opcionalmente, os módulos são associados caso isso esteja especificado nas suas declarações; Cada módulo que especifica uma classe inicializadora, na sua declaração, será re-inicializado usando a classe específica; Para cada módulo que possui tasks iniciais especificadas na sua declaração, as tasks especificadas serão criadas e o TaskSpawner do módulo as agendará para execução.
The Factory Data Definition File
Esse arquivo está especificado na propriedade lida.elementfactory.data do arquivo de configuração principal. O arquivo contém as definições dos Nodes, Links, Strategies e tipos de tasks que serão adicionados ao ElementFactory. Este arquivo é um documento XML que contém a tag raiz <LidaFactories>, além das seguintes tags: <strategies>, contém sub-tags do tipo <strategy> que definem os tipos de Strategy que serão carregados no ElementFactory; <nodes>, contém sub-tags do tipo <node> que definem os tipos de Node que serão carregados no ElementFactory; <links>, contém sub-tags do tipo <link> que definem os tipos de Link que serão carregados no ElementFactory; <tasks>, contém sub-tags do tipo <task> que definem os tipos de tasks que serão carregados no ElementFactory.
The Initializable Interface
Muitos elementos no LIDA Framework implementam a interface Initializable. Essa interface provê um modo uniforme de inicializar elementos com parâmetros. As sub-classes que a usam necessitarão apenas sobreescrever o método init, da interface, para efetuar a inicialização customizada do elemento. Dentro desse método, o método getParam recupera os parâmetros definidos nos arquivos de configuração. A interface FullyInitializable estende a interface Initializable. Essa interface permite a associação dos módulos usando o método setAssociatedModule.
LIDA Framework: Implementações Default
O LIDA Framework possui implementações default dos seguintes módulos do LIDA Model: Environment (abstract), Sensory Memory (abstract), Perceptual Associative Memory, Transient Episodic Memory, Declarative Memory, Workspace, Structure-Building Codelets, Attention Codelets, Global Workspace, Procedural Memory, Action Selection, Sensory-Motor Memory.