Erlang面向Agent编程的利器:eXAT(4)

来源:互联网 发布:java员工管理系统 页面 编辑:程序博客网 时间:2024/05/26 08:42

四、案例研究
以下介绍几个主体的例子,以及如何在eXAT中实现。
(1)消息模式匹配
这是第一个例子,主体等待特定消息的到来,然后做些事情。具体地,从主体“Alice”发来LISP写的“inform”消息,我们就令主体“Bob”开始action行动。
-module (agent_bob).
-export ([action/3, start/0]).
action ([inform, alice, Receiver, Ontology, lisp, Content, Slots], State, Agent) ->
    % ’inform’ from Alice ... do the action
start () ->
    agent:new (bob, receiver, {agent_bob, action}).
这段代码展示了主体Bob的eXAT实现:
函数start/0调用agent:new/4启动主体Bob。参数意思是:bob:主体名字,receiver:作为行为骨架的FSM模板的名字,agent_bob:实现FSM模板规定行为的函数名字。这里的receiver是eXAT内建的,它只有一个状态,收到消息后它引发行动并返回状态。
消息的模式匹配,通过Erlang的匹配机制实现。消息采用ACL格式:
[ Performative-name, Sender, Receiver,Ontology, Language, Content, Slots ]
上面的那段代码中,函数action的第一个参数,就是以列表表示的消息模式。
再来看看用JADE写的相同示例:
import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.*;
public class ReceiverAgent extends Agent
{
    public void setup ()
    {
        AID aid[] = new AID[1];
        aid [0] = new AID ("Alice", false);
        addBehaviour (new ReceiverBehaviour (this, -1, MessageTemplate.and (
            MessageTemplate.MatchPerformative (ACLMessage.INFORM),
            MessageTemplate.and ( MessageTemplate.MatchReceiver (aid),
            MessageTemplate.MatchLanguage ("lisp"))
            )
        )
        {
            public void action () {
            //.. do something
            }
        });
    }
}
看上去,Erlang代码的可读性明显高于Java的。
(2)多种消息的模式匹配
-module (agent bob).
-export ([action/3, start/0]).
action ([inform, alice, Receiver, Ontology, lisp, Content, Slots], State, Agent) ->
    % ’inform’ from alice: ... do the action
action ([inform, Sender, Receiver, Ontology, lisp, Content, Slots], State, Agent) ->
    % ’inform’ from another agent ... do the action
action (M, State, Agent) ->
    acl:reply (M, notunderstood).
start () ->
    agent:new (bob, receiver, {agent bob, action}).
这是第二个示例,它为第一个示例增加了2个action子句。当收到“Alice”以外的其他主体发来的“inform”时,由第二子句处理;当收到的信息类型不明时,由第三子句予以回复,告知对方,其所发信息“我读不懂”。
这个示例说明,简单地增加函数子句,就能轻松应对各种情况。
(3)用户定义的模板
这是最后一个示例,用以展示开发用户定义的FSM的模板。该模板的事件机制,与ERES引擎相关联。
假设有个主体的行为机制是FSM,如图1所示。


                                        图1
该主体等待在ERES引擎“goods” (state init) 中,事实 {price, computer,X} 的断言出现,其中 X < 1000;然后,该主体向主体
Seller (state s1)发出“request”请求消息,并一直等待答复。“答复”是个“inform”消息(final state stop)。主体收到答复后,停止运行。
为了实现这个主体,我们写个叫做buyeragent的模块,其中有FSM模板。该模块要遵守eXAT引擎规定的格式,定义状态转换机制的多子句函数 templatw/4,并且,template/4 必须返回的,是函数 event/2 处理的与“状态”相关的事件映射。template 形式如下:
template ( Event, State, Agent, AgentFun )
它返回的是FSM的下个状态。参数Agent是主体的名字,AgentFun是实现主体行为的多子句函数。参数Event是函数events返回的元组列表,列表中的元组的格式是{状态名字,事件列表}。
下面是FSM模板的代码:
-module (buyeragent).
-export ([template/4, events/2]).
template (Fact, init, Agent, AgentFun) ->
    apply ( AgentFun, [Fact, init, Agent] ),
    s1;
template ([inform | T] = M, s1, Agent, AgentFun) ->
    apply ( AgentFun, [M, s1, Agent] ),
    stop.
events (Agent, AgentFun) ->
    [ {init, [ {eres, goods, {price, computer, fun (X) -> X < 1000 end }} ] },
    {s1, [ {acl} ] } ].
状态init对应的事件,是在ERES引擎“goods”中宣布的事实,格式为元组:
{eres, goods, {price, computer, fun (X) -> X < 1000 end }}
其中的lambda函数,即“fun”语句表示的匿名函数,要求X的值必须小于1000。如果存在着这一事实,template/4的第一子句得以匹配,它通过函数 apply 调用主体的行为函数AgentFun,并且,返回 s1 作为 FSM 的新状态。
在新状态下,对应的事件是收到ACL消息“inform”。template/4 的第二子句处理此事后,返回状态“stop”,结束主体的运行。
这个FSM模板,可用于前面的2个示例,完整实现图1所示的行为机制。使用这个模板的主体,必须实现“request”消息的发送,和对接收到的“inform”消息进行解释。
最后,应该承认,eXAT目前只能实现几种简单的主体agent,没有谁用它实现过完整的多主体应用程序。
因此,本文说eXAT是Erlang面向Agent编程的利器,有些夸张。

原创粉丝点击