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

本篇介绍如何实现多代理系统的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
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值