《关于多代理系统的研究》03

来源:互联网 发布:淘宝日本直邮是真的吗 编辑:程序博客网 时间:2024/05/21 02:52

本篇介绍如何实现多代理系统的Goal。

1. Goals的简单介绍

面向Goal的编程是Agent Programming的一个核心概念。它表示一个Agent把自己托付给一个托管者,尝试所有的可能性来实现目标。Goal的分类为四种。
1. achieve goal:比如飞机着落。这个Agent会尝试所有的Plans,直到飞机安全着落。否则是没有机会去尝试其他的可能性,造成飞机坠毁。这种就是Agent必须要到达某种事物的状态。
2. query goal:顾名思义就是要查询某个目标,检索某些信息。比如清洁工Agent,无时不刻在寻找垃圾这个目标。
3. maintain goal:维持目标。一直使事物能够保持某种状态。比如核反应堆。当反应的状态不满足的时候,就会调用相应的Plan来维持这种状态。
4. perform goal:Agent必须要执行的某个动作。比如边境官兵的巡逻,只有执行巡逻这个动作,才能保证边疆的安全。
从这些生活中得例子可以看出,多代理的应用在我们的生活中,无处不在。只有从生活中得例子得到启发,才能从理论上更好的改进提升我们的生活空间。
那么,Goal的表示方法有几种呢?
1. 内部类:如果一个Goal是某个Agent的私有物,比人是不可以也不能用到的话,那么就是用内部类。简单并且方便参数的传递。
2. 类:这个Goal没有直接的联系与某个agent。

2. 开始使用Goal

是用Goal作为内部类。添加@Goal标记。

package a1;import java.util.HashMap;import java.util.Map;import jadex.bdiv3.BDIAgent;import jadex.bdiv3.annotation.Belief;import jadex.bdiv3.annotation.Goal;import jadex.bdiv3.annotation.Plan;import jadex.bdiv3.annotation.Trigger;import jadex.micro.annotation.Agent;import jadex.micro.annotation.AgentBody;import jadex.micro.annotation.AgentCreated;import jadex.micro.annotation.Description;@Agent@Description("<h1>Translate English to Chinese</h1>")// @Plans(@Plan(body=@Body(TranslatePlan.class)))public class TranslateEngChBDI {    @Agent    protected BDIAgent translateAgent;    @Belief    protected Map<String, String> wordTable;    @AgentCreated    public void init() {        this.wordTable = new HashMap<String, String>();        // add some examples of word pairs        wordTable.put("milk", "牛奶");        wordTable.put("banana", "香蕉");        wordTable.put("school", "学校");        wordTable.put("teacher", "老师");        wordTable.put("science", "科学");    }    @Goal    public class TranslateEngCh {        protected String eword;        protected String cword;        public TranslateEngCh(String eword) {            this.eword = eword;        }        public String getEword() {            return eword;        }        public void setEword(String eword) {            this.eword = eword;        }        public String getCword() {            return cword;        }        public void setCword(String cword) {            this.cword = cword;        }    }    @Plan(trigger = @Trigger(goals = TranslateEngCh.class))    public void translateEngChPlan(TranslateEngCh goal) {        goal.setCword(wordTable.get(goal.getEword()));    }    @AgentBody    public void body() {        String ewordString = "school";        TranslateEngCh goal = (TranslateEngCh) translateAgent.dispatchTopLevelGoal(                new TranslateEngCh(ewordString)).get();        System.out.println("翻译结果:" + ewordString + "--->" + goal.getCword());    }}

goal定义完成之后,是被agent来调用的。为了实现这个goal,那么就需要有Plan来支持,最终完成某个目的。
记住两点:
1. agent.dispatchTopLevelGoal();
2. 调用goal以后,需要Plan来对goal进行处理。
上述程序的结果,显示为了达成某个目标,定义Plan来处理goal。
这里我们是用了类的get和set方法来操作goal的成员变量。如何能够实现在类的外部直接对成员变量进行操作呢?

3. 使用Goal的参数和结果(optionally)

使用目标的参数和结果能够节省很多代码。并且保证目标的安全性。
主要的实现形式为:@GoalParameter 和@GoalResult

package a1;import java.util.HashMap;import java.util.Map;import jadex.bdiv3.BDIAgent;import jadex.bdiv3.annotation.Belief;import jadex.bdiv3.annotation.Goal;import jadex.bdiv3.annotation.GoalParameter;import jadex.bdiv3.annotation.GoalResult;import jadex.bdiv3.annotation.Plan;import jadex.bdiv3.annotation.Trigger;import jadex.micro.annotation.Agent;import jadex.micro.annotation.AgentBody;import jadex.micro.annotation.AgentCreated;import jadex.micro.annotation.Description;@Agent@Description("<h1>Translate English to Chinese</h1>")// @Plans(@Plan(body=@Body(TranslatePlan.class)))public class TranslateEngChBDI {    @Agent    protected BDIAgent translateAgent;    @Belief    protected Map<String, String> wordTable;    @AgentCreated    public void init() {        this.wordTable = new HashMap<String, String>();        // add some examples of word pairs        wordTable.put("milk", "牛奶");        wordTable.put("banana", "香蕉");        wordTable.put("school", "学校");        wordTable.put("teacher", "老师");        wordTable.put("science", "科学");    }    @Goal    public class TranslateEngCh {        @GoalParameter        protected String eword;        @GoalResult        protected String cword;        public TranslateEngCh(String eword) {            this.eword = eword;        }    }    @Plan(trigger = @Trigger(goals = TranslateEngCh.class))    public String translateEngChPlan(String ewordString) {        return wordTable.get(ewordString);    }    @AgentBody    public void body() {        String ewordString = "school";        String chString = (String) translateAgent.dispatchTopLevelGoal(new TranslateEngCh(ewordString)).get();        System.out.println("翻译结果:" + ewordString + "--->" + chString);    }}

get()方法的作用是返回异步计算的结果,也就是翻译以后的结果。

4. Goal的Retry

从上述的例子中不难发现,goal其实和Plan是没有什么区别的。相反,goal使用起来还是比较麻烦,因为需要Plan来处理一下。但是goal的唯一好处就是,当使用比较复杂的goal的时候,只需要考虑目标即可,不需要去考虑实现的过程。讲目标分解为n多个plan来实现。不过目前所接触到的问题,都是比较小的规模,不需要尝试不同的plan。但是还是举一个比较小的例子来说明一下。

package a1;import java.util.HashMap;import java.util.Map;import jadex.bdiv3.BDIAgent;import jadex.bdiv3.annotation.Belief;import jadex.bdiv3.annotation.Goal;import jadex.bdiv3.annotation.GoalParameter;import jadex.bdiv3.annotation.GoalResult;import jadex.bdiv3.annotation.Plan;import jadex.bdiv3.annotation.Trigger;import jadex.bdiv3.runtime.impl.PlanFailureException;import jadex.micro.annotation.Agent;import jadex.micro.annotation.AgentBody;import jadex.micro.annotation.AgentCreated;import jadex.micro.annotation.Description;@Agent@Description("<h1>Translate English to Chinese</h1>")// @Plans(@Plan(body=@Body(TranslatePlan.class)))public class TranslateEngChBDI {    @Agent    protected BDIAgent translateAgent;    @Belief    protected Map<String, String> wordTable;    @AgentCreated    public void init() {        this.wordTable = new HashMap<String, String>();        // add some examples of word pairs        wordTable.put("milk", "牛奶");        wordTable.put("banana", "香蕉");        wordTable.put("school", "学校");        wordTable.put("teacher", "老师");        wordTable.put("science", "科学");    }    @Goal    public class TranslateEngCh {        @GoalParameter        protected String eword;        @GoalResult        protected String cword;        public TranslateEngCh(String eword) {            this.eword = eword;        }    }    @Plan(trigger = @Trigger(goals = TranslateEngCh.class))    public String translateEngChPlanA(String ewordString) {        System.err.println("Plan A");        throw new PlanFailureException();        //return wordTable.get(ewordString);    }    @Plan(trigger = @Trigger(goals=TranslateEngCh.class))    public String translateEngChPlanB(String ewordsString){        System.out.println("Plan B");        return wordTable.get(ewordsString);    }    @AgentBody    public void body() {        String ewordString = "school";        String chString = (String) translateAgent.dispatchTopLevelGoal(                new TranslateEngCh(ewordString)).get();        System.out.println("翻译结果:" + ewordString + "--->" + chString);    }}

小的改动,就是增加了另外一个Plan,然后手动使第一个Plan处于失效状态。这样本着能够达到目的的原则,还是去寻找其他的Plan。最终能够完成goal。

5. Goal Creation Condition

package a1;import java.util.HashMap;import java.util.Map;import jadex.bdiv3.BDIAgent;import jadex.bdiv3.annotation.Belief;import jadex.bdiv3.annotation.Goal;import jadex.bdiv3.annotation.GoalCreationCondition;import jadex.bdiv3.annotation.GoalParameter;import jadex.bdiv3.annotation.GoalResult;import jadex.bdiv3.annotation.Plan;import jadex.bdiv3.annotation.Trigger;import jadex.micro.annotation.Agent;import jadex.micro.annotation.AgentBody;import jadex.micro.annotation.AgentCreated;import jadex.micro.annotation.Description;@Agent@Description("<h1>Translate English to Chinese</h1>")// @Plans(@Plan(body=@Body(TranslatePlan.class)))public class TranslateEngChBDI {    @Agent    protected BDIAgent translateAgent;    @Belief    protected String eword;    @Belief    protected Map<String, String> wordTable;    @AgentCreated    public void init() {        this.wordTable = new HashMap<String, String>();        // add some examples of word pairs        wordTable.put("milk", "牛奶");        wordTable.put("banana", "香蕉");        wordTable.put("school", "学校");        wordTable.put("teacher", "老师");        wordTable.put("science", "科学");    }    @Goal    public class TranslateEngCh {        @GoalParameter        protected String eword;        @GoalResult        protected String cword;        @GoalCreationCondition(beliefs = "eword")        public TranslateEngCh(String eword) {            this.eword = eword;        }    }    @Plan(trigger = @Trigger(goals = TranslateEngCh.class))    public String translateEngChPlan(String ewordsString) {        System.out.println("Plan executing");        return wordTable.get(ewordsString);    }    @AgentBody    public void body() {        eword = "laoshi";        eword = "kexue";    }}

上述代码的主要是为了说明,当Belief改变的时候,我们可以创建新的goal。但是感觉原作者对这点功能讲解的不是很好。

6. 简单介绍一下Goal的重复尝试和Maintain Goal

这种方法-目的的推理过程是开始于goal的。这个agent会一直执行所有的plan,知道执行完毕以后成功或者仍旧没有成功,如果仍旧没有成功的话,程序会继续执行plans,直到成功。但是这种是有弊端的。容易造成程序的死锁。 所以默认情况下,这种重复recur是set为false的。如果有需要的话,可以进一步的学习。
关于maintaingoal的用法,这里也不再多做介绍。
总结:关于goal的用法,其实就是使用内部类。单独的一个外部类,作为goal来使用,不是很常见的。可能会根据接触的项目大小,用到的知识可能会比较多。对于目前我的项目来说,使用goal与不使用goal都是一样的。只需要Agent和Plans即可。当然,也可能是设计上有一定的问题,今后对系统进行慢慢的改进。

0 0