11 maio 2017

Listing items when these items are also lists

A way to list items which also are lists is by "nth" internal action asking for each register. Having the register another "nth" call may get the fields of the register like this:

products([

["Banana",1], 
["Apple",2], 
["Pinapple",2.5]
]).
!start.

+!start : products(List) <-
.length(List,LLenght);
-+listSize(0);
while(listSize(Sz) & Sz < LLenght)
{        
.random(Y);
.nth(Sz,List,Item);
.nth(0,Item,Name);
.nth(1,Item,Price);
.print("Product(",Sz,"): ",Name," $",Price);
-+listSize(Sz+1);
    }.

Another way is using "member" internal action which returns with each item of a list (which can be seen as a register if it is a two dimensions array):

products([
["Banana",1], 
["Apple",2], 
["Pinapple",2.5]
]).
!start.

+!start : products(List) <-
for (.member(Item,List)){
.random(Y);
.nth(0,Item,Name);
.nth(1,Item,Price);
.print("Product: ",Name," $",Price);
}.

15 março 2017

Listing items of a list

Int his case, when it is necessary to just list items of a list, a loop and the nth function may be used. To control the loop a variable can be started with 0 (zero) incrementing by 1 until the size of the list minus 1. To get the length of the list, the internal function length can be used.
The following code is showing a simple example with a list o products declared as a belief. In the start goal a variable "Count" in the first iteration is unified with 0 and compared, being less than "ListLength" (in this example is number 3). After this, the function "nth" returns the nth item List, first 0, than 1 and finally 2 in the last iteration. nth function unifies the nth item in the variable List. Finally the code just print the result and increment Count.

products(["Banana", "Apple", "Pineapple"]).
!start.

+!start : products(List) <-
 .length(List,ListLength);
-+listSize(0);
while(listSize(Count) & Count < ListLength)
{        
.nth(Count,List,Item);
.print("Product(",Count,"): ",Item);
-+listSize(Count+1);
 }.

19 novembro 2015

Exemplo de integracao com interface Java: Thank you sponsor!

O programa do robô que traz a cerveja ao dono parecia perfeito, o owner solicitava uma cerveja, o robô obedientemente ia até o refrigerador, pegava a cerveja e levava a seu mestre. Porém, o estoque de cerveja vai reduzindo até que o robô responde que não poderia mais levar cerveja, o que fazia com que não houvessem novas operações após isto.
Esta situação precisava ser resolvida, o dono então ganhou uma interface onde seu patrocinador pode doar cervejas a ele, preenchendo o estoque no refrigerador e fazendo a alegria do malandro.
Obrigado pela cerveja! http://pt.slideshare.net/Bryagh/old-beer-trucks-6834062

Neste programa foi criado um novo agente, o "sponsor" que está ligado a uma aplicação java que tem uma interface gráfica bem simples. O agente recebe da interface o comando que notifica que novas cervejas foram entregues, envia esta informação por broadcast para os demais agentes. Ambos, O robô e o dono, realizam atividades ao receber esta notificação.

Projeto "beersponsor.mas2j"

No projeto há a adição do agente sponsor que está ligado a classe java SponsorGUI.
MAS beersponsor {

infrastructure: Centralised
    agents:
                robot;
                owner;
        sponsor agentArchClass SponsorGUI;
aslSourcePath:
"src/asl";
}

O agente "owner.asl"

O agente owner é quem inicia o processo, através da chama !ask(beer). Em relação ao código original apenas foi adicionada a tratativa da adição de uma crença que ocorre ao receber a mensagem broadcast de que chegou mais cerveja. Sua ação é educadamente agradecer a doação e sem perder tempo, solicitar ao robô que o abasteça.

// Agent owner in project beer.mas2j
/* Initial beliefs and rules */

/* Initial goals */
!ask(beer).

/* Plans */
@a1
+!ask(beer) : true 
<- .send(robot, achieve, bringbeer(owner,beer));
.print("Go robot, bring a beer!").

@h1
+has(owner,beer)[source(robot)] : true
<- !drink(beer);
.print("I want more!");
!ask(beer).

@d1
+!drink(beer) : has(owner,beer)
<- .send(robot, achieve, masterdrunkabeer(owner));
.print("Yeah, I have drunk a cold beer!").

@s1
+addstock(beer,N) : true
<- .print("Since there is beer, bring it!");
.send(sponsor, tell, thanks(sponsor));
!ask(beer).

O agente "robot.asl"

Da mesma forma que o agente owner, o agente robô passou a tratar a mensagem broadcast "+addstock(beer,N)", atualizando o estoque local o que permite que o dono realize novas solicitações.

// Agent robot in project beersponsor.mas2j

/* Initial beliefs and rules */
// initially, I believe that there are 5 beers in the fridge
available(beer,fridge).
stock(beer,3).

/* Initial goals */

/* Plans */
@b1
+!bringbeer(owner,beer)
: available(beer,fridge)
<- -at(robot,owner); // Have sure this old belief is out
!at(robot,fridge);
.print("Grabbing a beer to my master.");
!at(robot,owner);
.date(YY,MM,DD); .time(HH,NN,SS);
.send(owner, tell, has(owner,beer));
.print("Here is your beer my master.");
?stock(beer,Inventory);
!updateStock(beer,Inventory);
+consumed(YY,MM,DD,HH,NN,SS,beer).

@b2
+!bringbeer(owner,beer)
: not available(beer,fridge)
<- .print("Sorry, there is no beer!").

@a1
+!at(robot,P) : true// : not at(robot,P)
<- -at(robot,_); // Have sure the old belief is out
+at(robot,P);
.print("Robot is at ",P).
@m1
+!masterdrunkabeer(owner) : true
<- .send(owner, untell, has(owner,beer)).

@u1
+!updateStock(beer,Inventory) : Inventory > 1
<- ?stock(beer,Tmp);
Inv = Tmp - 1; 
-+stock(beer,Inv);
.print("Inventory had ",Inventory," beer(s). A beer is being taken, now the fridge has ",Inv," beer(s).").

@u2 //last beer
+!updateStock(beer,Inventory) : Inventory == 1
<- -+stock(beer,0);
-available(beer,fridge);
.print("Inventory had its last beer. Master needs to ask supermarket for more beer!").

@u3
+!updateStock(beer,Inventory) : Inventory == 0
<- -available(beer,fridge);
.print("Did I already told that there is no beer?").

@s1
+addstock(beer,N) : N > 0
<- .print("More ",N," beers just arrived! There are available beer again!");
-+stock(beer,N);
+available(beer,fridge).

O agente "sponsor.asl"

Este agente é a ligação entre a regra de negócio e a aplicação externa que permite comandar uma doação de cervajas. O objetivo giving_beer é um comando externo que ocorre quando um usuário pressiona o botão de doação. A crença thanks(sponsor) é informada pelo owner quando recebeu a doação. Este dado é retornado para a interface gráfica que imprime o agradecimento ao patrocinador.

// Agent sponsor in project beersponsor.mas2j
@g1
+!giving_beer   // this goal is created by the GUI of the agent 
    <- .broadcast(tell, addstock(beer,2));
.print("Broadcasting about the delivery.").
  
@t1 
+thanks(sponsor)[source(owner)] : true
<- thankyou(sponsor);
.print("Thanking sponsor.").

A aplicação "SponsorGUI.java"

A aplicação possui um botão e uma caixa de texto. Ao pressionar o botão adiciona o objetivo giving_beer ao agente sponsor. Ao receber a mensagem thankyou, imprime na tela o agradecimento.

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import jason.architecture.*;
import jason.asSemantics.ActionExec;
import jason.asSyntax.ASSyntax;
import jason.asSyntax.Literal;
import javax.swing.*;

/** example of agent architecture's functions overriding */
public class SponsorGUI extends AgArch {

    JTextArea jt;
    JFrame    f;
    JButton patronize;

    public SponsorGUI() {
        jt = new JTextArea(10, 30);
        patronize = new JButton("Give more beer");
        patronize.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Literal goal = ASSyntax.createLiteral("giving_beer");
                jt.append("\n\rGiving beer to my godson...");
                getTS().getC().addAchvGoal(goal, null);
                patronize.setEnabled(false);
            }
        });
        
        f = new JFrame("Sponsor agent");
        f.getContentPane().setLayout(new BorderLayout());
        f.getContentPane().add(BorderLayout.CENTER, new JScrollPane(jt));
        f.getContentPane().add(BorderLayout.SOUTH, patronize);
        f.pack();
        f.setVisible(true);
    }

    @Override
    public void act(ActionExec action, List<ActionExec> feedback) {
        if (action.getActionTerm().getFunctor().startsWith("thankyou")) {
            jt.append("\n\rThank you "+action.getActionTerm().getTerm(0)+"!");
            action.setResult(true);
            feedback.add(action);
            
            patronize.setEnabled(true); // enable GUI button
        } else {
            super.act(action,feedback); // send the action to the environment to be performed.
        }    
    }

    @Override
    public void stop() {
        f.dispose();
        super.stop();
    }
}

Fontes

  • Este programa foi baseado no exemplo beer.mas2j, melhorias foram implementadas baseadas nos exemplos que acompanham o pacote Jason

22 outubro 2015

Planos

O plano é onde se designa como o agente reage a estímulos e executa ações para realizar seus objetivos. É composto por três partes: o gatilho, o contexto e o corpo do plano, no seguinte formato de diretiva:

gatilho : contexto <- corpo

Planos. Fonte: http://www.produzindo.net/modelo-de-plano-de-negocios-tudo-que-voce-precisa-para-produzir-o-seu/

Eventos "gatilho"

Um agente é uma entidade que pode se comportar de forma reativa ou pró-ativa. No caso de tentarem realizar ações diversas em busca da realização de seus objetivos, demonstra sua pró-atividade, quando por outro lado executam ações como um reflexo a estímulos, demonstra reatividade. Há dois tipos de mudanças de atitudes mentais que o agentes suportam: mudança em suas crenças e mudança em seus objetivos.
Um gatilho é a parte de um plano que é executada quando ocorre certo estímulo e determinadas condições prévias são satisfeitas, neste caso fazendo com que um plano previamente programado seja relevante ao evento ocorrido.
Tipos de gatilho:
  • +l: Adição de crença
  • -l: Remoção de crença
  • +!l: Adição de objetivo a ser atingido
  • -!l: Remoção de objetivo a ser atingido
  • +?l: Adição de objetivo de teste
  • -?l: Remoção de objetivo de teste

Contexto

Também relacionado a planos reativos, refere-se ao ambiente que o agente está inserido e a busca de se obter um plano aplicável para cumprimento de seus objetivos.

Corpo

São as ações que o agente irá desempenhar no plano em questão para realização de seus objetivos.

Fontes

  • Bordini, R., Hübner, J. F., & Wooldridge, M. (n.d.). Programming Multi-Agent Systems in AgentSpeak using Jason.

15 setembro 2015

Exemplo de código: Robot, bring a beer!

Este código foi baseado no exemplo proposto no livro "Programming Multi-Agent Systems in AgentSpeak using Jason". É um divertido programa que possui dois agentes, um é o "owner", ou dono do robô e o outro um fantástico robô que tem por missão atender seu mestre quando ele pede uma cerveja. Isso enquanto o refrigerador não está vazio!
Hommer e seu robô. http://poggoblin.com/?p=2345

Código do agente "owner.asl"

// Agent owner in project beer.mas2j
/* Initial beliefs and rules */

/* Initial goals */
!ask(beer).

/* Plans */
@a1
+!ask(beer) : true 
<- .send(robot, achieve, bringbeer(owner,beer));
.print("Go robot, bring a beer!").
@h1
+has(owner,beer)[source(robot)] : true
<- !drink(beer);
.print("I want more!");
!ask(beer).

@d1
+!drink(beer) : has(owner,beer)
<- -has(owner,beer);
.send(robot, achieve, masterdrunkabeer(owner));
.print("Yeah, I have drunk a cold beer!").

Observe que há um objetivo inicial de solicitar a primeira cerveja, isso dispara o plano "ask(beer)" que envia uma mensagem ao agente robô com o conteúdo "bringbeer(owner,beer)". O robô quando obtém a cerveja e entrega ao mestre envia uma mensagem ao mestre dizendo que ele já tem um cerveja a disposição, alterando a crença do mestre "has(owner,beer)". Uma vez que o mestre sabe que possui uma cerveja, não perde tempo e trata de bebê-la executando o plano "drink(beer)" e enviando uma mensagem ao robô informando que bebeu a cerveja. O mestre ainda não satisfeito conclui enviando uma outra mensagem ao robô solicitando mais cerveja!

Código do agente "robot.asl"

// Agent robot in project beer.mas2j

/* Initial beliefs and rules */
// initially, I believe that there are 5 beers in the fridge
available(beer,fridge).
stock(beer,5).

/* Initial goals */

/* Plans */
@b1
+!bringbeer(owner,beer)
: available(beer,fridge)
<- //-at(robot,owner); // Have sure this old belief is out
!at(robot,fridge);
.print("Grabbing a beer to my master.");
?stock(beer,Inventory);
!updateStock(beer,Inventory);
!at(robot,owner);
.date(YY,MM,DD); .time(HH,NN,SS);
.send(owner, tell, has(owner,beer));
.print("Here is your beer my master.");
+consumed(YY,MM,DD,HH,NN,SS,beer).

@b2
+!bringbeer(owner,beer)
: not available(beer,fridge)
<- .print("Sorry, there is no beer!").
@a1
+!at(robot,P) : true// : not at(robot,P)
<- -at(robot,_); // Have sure the old belief is out
+at(robot,P);
.print("Robot is at ",P).
@m1
+!masterdrunkabeer(owner) : true
<- .send(owner, untell, has(owner,beer)).
@u1
+!updateStock(beer,Inventory) : Inventory > 0
<- ?stock(beer,Tmp);
Inv = Tmp - 1; 
-+stock(beer,Inv);
.print("Inventory had ",Inventory," beer(s). A beer is being taken, now the fridge has ",Inv," beer(s).").
@u2
+!updateStock(beer,Inventory) : Inventory == 0
<- -available(beer,fridge);
.print("Master needs to ask supermarket for more beer!").

O robô inicia com as crenças de que há cervejas no congelador e que o estoque é de 5 unidades. O robô não executa nenhuma atividade até que recebe uma mensagem do owner com o plano "bringbeer". Enquanto há cervejas no refrigerador o robô desloca-se até este, pega a cerveja, atualiza sua crença quanto ao estoque e leva a cerveja até seu mestre enviando uma mensagem tell que adicionará a crença "has(owner,beer)" ao owner. O mestre responde que bebeu a cerveja, o robô então envia uma mensagem para remover a crença do mestre de que ele possui uma cerveja. Quando não há mais cerveja no estoque o robô imprime a mensagem de que não pode executar a ação.

Código do projeto "beer.mas2j"

/* Jason Project */
MAS beer {
    infrastructure: Centralised
    agents:
        robot;
        owner;
}

Fontes

  • Bordini, R., Hübner, J. F., & Wooldridge, M. (n.d.). Programming Multi-Agent Systems in AgentSpeak using Jason.

14 setembro 2015

A linguagem dos agentes

Os agentes compreendem instruções baseadas em ações, compreende que cada enunciado é uma tentativa de obter informações ou alterar o estado de ambiente que está inserido. Searle, 1969, propõe tipos de atos de fala conforme segue:
  • Representativos: para expressar uma informação de um estado de interesse (ex.: "está chovendo")
  • Diretivos: para expressar requisições ou comandos (ex.: "pegue este objeto")
  • Comissivos: uma promessa ou ameaça para realização de acordos de ações futuras (ex: "farei a transferência de dados a meia noite")
  • Expressivos: usado para expressar um estado mental (ex.: "obrigado!")
  • Declarativo: expressa alterações no estado das coisas (ex.: "todos devem parar a execução de seus trabalhos")
A linguagem dos agentes não é portando uma chamada de método com uma lista de argumentos, é por outro lado, uma proposição que é verdadeira ou falsa elevando os agentes a uma comunicação em nível de conhecimento.
A linguagem dos agentes. Fonte: https://www.intelectacursos.com.br/cursos-online/letras/curso-online-de-linguagem-oral-e-escrita-1248

KQML

A linguagem KQML (Knowledge Query and Manipulation Language) é considerada a primeira linguagem para sistemas de inteligencia artificial distribuídos a definir uma comunicação prática para agentes em um alto nível, baseada em ações.

FIPA

O padrão FIPA de comunicação (FIPA Agent Communication Language) foi lançado em 2002 é além de uma linguagem, um conjunto de padrões relacionados a comunicação, gestão e uso dos agentes. Em 2005 foi oficialmente aceita como um padrão IEEE. Não se distancia da linguagem KQML, um esforço para simplificar e racionalizar ao máximo sua performativa.

Fontes

  • Searle JR 1969 Speech Acts: an Essay in the Philosophy of Language. Cambridge Uni- versity Press, Cambridge
  • Bordini, R., Hübner, J. F., & Wooldridge, M. (n.d.). Programming Multi-Agent Systems in AgentSpeak using Jason.
  • http://www.fipa.org/
  • http://www.objs.com/agility/tech-reports/9807-comparing-ACLs.html

10 setembro 2015

Por onde começar?

O programa "Hello World!" é sempre a melhor forma de iniciar. Começamos pela apresentação da ferramenta JEdit que é uma IDE e interpretador Jason que permite escrever e simular códigos Jason. Clique aqui para fazer do download.

Na barra inferior a direita temos os botões para criação do projeto e do agente, no caso criei um projeto chamado "helloworld" e adicionei um agente chamado "hello" (arquivo com extensão asl).
Ao criar o projeto, a própria ferramenta já cria e associa o agente, o código a seguir foi gerado automaticamente no arquivo "helloworld.mas2j":

/* Jason Project */
MAS helloworld {
    infrastructure: Centralised
    agents:
        hello;
}

Já o agente precisa ser codificado, para este exemplo queremos que apenas seja criado o agente e que este escreve no terminal a expressão "Olá mundo", ficando conforme segue:

/* Crenças iniciais */ 
iniciado. 

/* Crenças iniciais */ 
+iniciado 
<- .print("Olá mundo!").

Neste exemplo o que estamos fazendo é gerando uma crença chamada "iniciado" que quando o agente acredita ser verdadeira ele executa a o plano imprimindo na tela a mensagem configurada.

Fontes

  • Bordini, R., Hübner, J. F., & Wooldridge, M. (n.d.). Programming Multi-Agent Systems in AgentSpeak using Jason.