JADE提升篇


以下如果未特殊聲明,都在JADE管理器中運行,然后再Eclipse控制台中查看!
JADE行為類
在前面的例子中,Agent所作的工作都定義在了setup方法中,實際上它具有的行為和執行的動作都應該定義在Behavious類中,我們可以對Behavior類生成實例,然后將任務或者動作代碼放在對Behavious類中的action方法中,action方法是必須要有的。Behavious類還有很多子類,分別對應着不同類型的Behaviour,包括SimpleBehaviour,SequencesBehaviour, ParallelBehavior, CyclicBehavior等。
一個Agent的行為表示它能夠執行的任務,通過繼承jade.core.behaviours.Behaviour來實現。然后在Agent類中通過addBehaviour()方法將行為加入進來。當一個Agent啟動(通過setup()方法后,行為可以在任何時間加入進來。
要定義Behaviour必須實現其action()方法,它定義了Agent的執行時的實際動作,而done()方法指名了一個行為是否已執行完畢,是否要從行為池中刪除。
一個Agent可以並發執行多個behaviour。每個Agent線程啟動后執行的過程如下:

wpsC75A.tmp

SimpleBehaviour簡單行為

下面的例子中我們不在setup()中打印信息,而是把它放在一個簡單行為中:
在jadetest包里面新建一個java類命名為HelloWorldBehaviour,輸入下面代碼。配置中把變量改為-gui sb:jadetest.SimpleBehaviour,運行

package jadetest;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午5:20:11 
 */
import jade.core.Agent;
import jade.core.Location;
import jade.core.behaviours.SimpleBehaviour;

public class HelloWorldBehaviours extends Agent {
    public void setup() {
        SimpleBehaviour hello_behaviour = new SimpleBehaviour(this) {
            boolean finished = false;

            // 覆蓋 Behaviour 類的action這一抽象方法
            public void action() {
                System.out.println("HelloWorldBehaviour run: Hello World!");
                System.out.println("-----About Me:-----");
                System.out.println("My local name is:" + getLocalName());
                System.out.println("My globally unique name is:" + getName());
                System.out.println("-----About Here:-----");
                Location l = here();
                System.out.println("I am running in a location called:" + l.getName());
                System.out.println("Which is identified uniquely as:" + l.getID());
                System.out.println("And is contactable at:" + l.getAddress());
                System.out.println("Using the protocol:" + l.getProtocol());
                finished = true;
            }

            // done()在父類中也是一個抽象方法
            public boolean done() {
                return finished;
            }
        };
        addBehaviour(hello_behaviour);
    } // setup()
}

然后使用智能體管理器添加智能體並運行:

wps804C.tmp

wps804D.tmp

輸出結果為:
HelloWorldBehaviour run: Hello World!
-----About Me:-----
My local name is:hwb
My globally unique name is:hwb@172.17.98.217:1099/JADE
-----About Here:-----
I am running in a location called:Main-Container
Which is identified uniquely as:Main-Container@172.17.98.217
And is contactable at:172.17.98.217
Using the protocol:jicp
這個程序相較於前面的例子多了action, done兩個函數,它們分別執行自己的操作。HelloWorldBehaviours類加載時定義一個簡單行為,這個簡單行為執行的操作由action,done來實現。然后,再通過加載語句(addBehaviour(hello_behaviour))執行這個簡單行為

簡單行為和循環行為(CyclicBehaviour)組合的例子

一個Agent中可以加入各種Behaviour構成CompositeBehaviour。
在Eclipse的jade工程中編寫下列程序,過程如前所描述。

package jadetest;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午8:46:29 
 */
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;

public class SimpleAgent extends Agent {
    private class FourStepBehaviour extends Behaviour {
        // SimpleBehaviour hello_behaviour = new SimpleBehaviour(this){
        // 這兩條語句有很大不同嗎?上面的定義一個新的類,下面的修改了標准行為的執行內容
        private int step = 1;

        public void action() {
            switch (step) {
            case 1:
                System.out.println("Operation 1");
                break;
            case 2:
                System.out.println("Operation 2. Adding one-shot behaviour");
                myAgent.addBehaviour(new OneShotBehaviour(myAgent) {
                    // 增加了一個新的動作,即快照
                    public void action() {
                        System.out.println("One-shot");
                    }
                });// myAgent.addbehaviour
                break;
            case 3:
                System.out.println("Operation 3");
                break;
            case 4:
                System.out.println("Operation 4");
                break;
            }// switch
            step++;
        } // action

        public boolean done() {
            return step == 5; // 判斷語句
        }

        public int onEnd() {
            myAgent.doDelete();
            System.out.println("Finished!");
            return super.onEnd();
        }
    } // class FourStepBehaviour

    /** Creates a new instance of SimpleAgent */
    protected void setup() {
        System.out.println("Agent " + getLocalName() + " started.");
        addBehaviour(new CyclicBehaviour(this) { // 增加了一個循環行為
            public void action() {
                System.out.println("Cycling");
            }
        }); // //增加的循環行為
        // Add the generic behaviour
        addBehaviour(new FourStepBehaviour());
    }// //setup()
}

輸出結果:
Agent sa started.
Cycling
Operation 1
Cycling
Operation 2. Adding one-shot behaviour
Cycling
Operation 3
One-shot
Cycling
Operation 4
Finished!
注意每個Agent內部都有一個ParallelBehaviour,我們如果加入多個behaviour到Agent中,他們會並行執行。behaviours加入到隊列的順序就是他們執行的次序。最后,behaviours可以動態的加入到Agent以及CompositeBehaviour。
總結:每個主體的執行都是從setup() 開始順序執行的。主體可以執行自定義的行為,如上例中的hello_behaviour ,FourStepBehaviour,也可以執行標准化的行為如OneShotBehaviour。
Agent通訊:ACL(Agent communication language)
JADE的Agent之間進行通信使用的acl語言遵循fipa acl規范。一個acl消息通常包含這些參數:sender:消息的發送者,用Agent標志AID表示; receivers,接受Agent消息的Agent可以是多個;Reply-to,應收到回應的接受者;Performative:標志發送消息的目的,即發送者想要通過發送消息干什么,通常有這樣一些常值:REQUEST, INFORM, ACCEPT_PROPOSAL, REJECT_PROPOSAL, PROPOSE;Content,消息的內容;內容語言,比如內容的編碼格式;ontology,雙方都能夠理解的消息內容的概念說明和語義描述。
簡單實例
發送者:

package jadetest;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午9:00:25 
 */
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;

public class SimpleSender extends Agent {
    protected void setup() {
        addBehaviour(new Behaviour(this) {
            private boolean finished = false;

            public void action() {
                System.out.println(getLocalName() + ": about to inform bob hello");
                // we sleep here to give bob a chance to start.
                doWait(5000);
                AID r = new AID();// 作用是什么?表示消息的發送者
                r.setLocalName("bob");
                ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
                // set performative
                msg.setSender(getAID());
                msg.addReceiver(r);
                msg.setContent("Hello_BOB");
                send(msg);
                System.out.println(getLocalName() + ": Send hello to bob");
                System.out.println("the content is:" + msg.getContent()); // finished = true;
                doWait(5000);
                doDelete();
            } // action

            public boolean done() {
                return finished;
            }
        }); // addbehavior
    }// setup
}// Agent

這段代碼的主要執行過程為:構建一個AID,以此來指出該消息的目的Agent。這里我們指定目的為一個本地的Agent,名字為bob。建立一個ACL消息標志其performative為INFORM。設定Sender為自身,指定接收者為bob。然后發送消息內容。打印相關信息。
接收者:他的名字必須為bob

package jadetest;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午9:01:36 
 */
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;

public class SimpleReceiver extends Agent {
    class DoSimpleReceiveBehaviour extends SimpleBehaviour {
        private boolean finished = false;

        public DoSimpleReceiveBehaviour(Agent Agent) {
            super(Agent);
        }

        public void action() {
            ACLMessage msg = receive();
            if (msg != null) {
                System.out.println(getLocalName() + ": received the following message : ");
                System.out.println(msg.toString());
                finished = true;
                myAgent.doDelete();
            } else {
                System.out.println(getLocalName()
                        + ":No message received, Blocking the behaviour till one is");
                block();
            }
        }// action

        public boolean done() {
            return finished;
        }
    }// DoSimpleReceiveBehaviour

    protected void setup() {
        DoSimpleReceiveBehaviour behaviour = new DoSimpleReceiveBehaviour(this);
        addBehaviour(behaviour);
    }
}// Agent

接收者的代碼流程為:添加一個簡單行為,這一行為檢查現在是否有受到消息,若沒有,則執行block()方法組織目前的behaviour執行,直到有新的消息到達。
復雜實例
FIPA定義了一組交互協議,包括FIPA-request, FIPA-query, FIPA-request-when, FIPA-contract-net, FIPA-Iterater-net, FIPA-Auction-English, FIPA-Auction-Dutch.其中:
REQUEST-INFORM:A請求B做一些工作,B可以同意或拒絕。如果B同意,則會去完成並告訴A該工作已經完成。等等。
Query:A想知道一些事情,B可以同意或不同意,並將B的回應告訴A。
Propose:在給定一些precondition的條件下,提出一個proposal去執行某些動作。
在Eclipse中創建文件夾ips:其代碼文件有兩個,分別為

package ips;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午9:03:05 
 */
import jade.core.AID;
import jade.core.Agent;
import jade.domain.FIPANames.InteractionProtocol;
import jade.lang.acl.ACLMessage;
import jade.proto.SimpleAchieveREInitiator;

public class SimpleRequestInitiator extends Agent {
    static class MarriageProposer extends SimpleAchieveREInitiator {
        protected MarriageProposer(Agent Agent, ACLMessage msg) {
            super(Agent, msg);
        }

        protected void handleAgree(ACLMessage msg) {
            System.out.println(myAgent.getLocalName() + ": 吼吼! " + msg.getSender().getLocalName()
                    + " 已經同意嫁給我了, I'm so excited!");
        }

        protected void handleRefuse(ACLMessage msg) {
            System.out.println(myAgent.getLocalName() + ": Oh no! "
                    + msg.getSender().getLocalName() + " 拒絕了我, i feel sad.");
        }

        protected void handleInform(ACLMessage msg) {
            System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                    + " has informed me of the status of my request." + " They said : "
                    + msg.getContent());
        }

        protected void handleNotUnderstood(ACLMessage msg) {
            System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                    + " has indicated that they didn't understand.");
        }

        protected void handleOutOfSequence(ACLMessage msg) {
            System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                    + "has sent me a message which I wasn't" + " expecting in this conversation");
        }
    }

    protected void setup() {
        System.out.println(getLocalName() + ": about to propose marriage to bob ");
        doWait(5000); // wait for bob to be started.
        ACLMessage msg = new ACLMessage(ACLMessage.REQUEST);
        AID to = new AID();

        to.setLocalName("bob");
        msg.setSender(getAID());
        msg.addReceiver(to);
        msg.setContent("Marry Me!");
        msg.setProtocol(InteractionProtocol.FIPA_REQUEST);
        addBehaviour(new MarriageProposer(this, msg));
    }
}

還有:

package ips;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午9:03:57 
 */

import jade.core.AID;
import jade.core.Agent;
import jade.domain.FIPANames.InteractionProtocol;
import jade.lang.acl.ACLMessage;
import jade.proto.SimpleAchieveREResponder;

public class SimpleRequestResponder extends Agent {
    static class MarriageResponder extends SimpleAchieveREResponder {
        public MarriageResponder(Agent Agent) {
            super(Agent, createMessageTemplate(InteractionProtocol.FIPA_REQUEST));
        }

        protected ACLMessage prepareResponse(ACLMessage msg) {
            ACLMessage response = msg.createReply();
            if (msg.getContent() != null && msg.getContent().equals("Marry Me!")) {
                System.out.println(myAgent.getLocalName() + ":" + msg.getSender().getLocalName()
                        + " has asked me to marry him!");
                AID sender;
                sender = msg.getSender();
                if (sender.getLocalName().equals("baz")) {
                    response.setPerformative(ACLMessage.AGREE);
                    System.out.println(myAgent.getLocalName() + ":I'm going to agree.");
                } else {
                    response.setPerformative(ACLMessage.REFUSE);
                    System.out.println(myAgent.getLocalName() + ":I'm going to turn him down.");
                }
            } else {
                response.setPerformative(ACLMessage.NOT_UNDERSTOOD);
                System.out.println(myAgent.getLocalName() + ":I didn't understand what "
                        + msg.getSender().getLocalName() + " just said to me.");
            }
            return response;
        }

        protected ACLMessage prepareResultNotification(ACLMessage inmsg, ACLMessage outmsg) {
            // what they have asked is now complete (or if it failed)
            ACLMessage msg = inmsg.createReply();
            msg.setPerformative(ACLMessage.INFORM);
            msg.setContent("I Do!");
            return msg;
        }
    }

    protected void setup() {
        System.out.println(getLocalName() + ": I wonder if anybody wants to marry me?");
        addBehaviour(new MarriageResponder(this));
    }//
}

按照以前記載,先打開GUI管理器,主類依然為jade.Boot,參數為-gui,GUI管理打開之后先建立一個名為bob的Agent,對應的類為ips.SimpleRequestResponder,然后再建立一個名為baz的Agent,對應的類為ips.SimpleRequestInitiator,記住順序不能變,以下是輸出結果:
bob: I wonder if anybody wants to marry me?
baz: about to propose marriage to bob
bob:baz has asked me to marry him!
bob:I'm going to agree.
baz: 吼吼! bob 已經同意嫁給我了, I'm so excited!
baz:bob has informed me of the status of my request. They said : I Do!
上例中,應用了SimpleAchieveREInitiator和SimpleAchieveREResponder兩個基類,適用於兩個Agent之間的交互。可以看出發起者對於不同的回應有不同的執行動作。
技巧:從AMS中獲取所有Agent的AID。

package ips;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月16日 下午1:52:33 
 */
import jade.core.Agent;
import jade.domain.AMSService;
import jade.domain.FIPAAgentManagement.AMSAgentDescription;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.lang.acl.ACLMessage;

public class AMSDump extends Agent {
    protected void setup() {
        AMSAgentDescription[] Agents = null;
        try {
            SearchConstraints c = new SearchConstraints();
            c.setMaxResults(new Long(-1));
            Agents = AMSService.search(this, new AMSAgentDescription(), c);
        } catch (Exception e) {
            System.out.println("Problem searching AMS: " + e);
            e.printStackTrace();
        }

        ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
        msg.setContent("Ping");
        for (int i = 0; i < Agents.length; i++) {
            if (Agents[i].getName().equals(getAID())) {
                // 如果不是自己則加入到接收者數組中
                continue;
            }
            msg.addReceiver(Agents[i].getName());
        }
    }
}

ACL高級特性之消息模板:

MessageTemplate class 利用MessageTemplate可以針對ACLMessage的每個屬性設置模式,以達到過濾消息的目的。為了可以構建更復雜的匹配規則,多個模式也可以進行and,or,not運算。最有用的一些規則或方法包括:通信行為匹配,發送者匹配,會話ID匹配。
比如MatchPerformative( performative ) 是通信行為的匹配。
這里 performative 可能是:
ACLMessage.INFORM
ACLMessage.PROPOSE
ACLMessage.AGREE
還有發送者匹配MatchSender( AID ),會話匹配MatchConversationID( String ),通信協議匹配MatchProtocol( String ) ,本體匹配MatchOntology( String)。
    比如:MessageTemplate mt = MessageTemplate.and( 
               MessageTemplate.MatchPerformative( ACLMessage.INFORM ),
               MessageTemplate.MatchSender( new AID( "a1",                                                         AID.ISLOCALNAME))) ;
相當於建立了一個模板,表示消息規則為INFORM行為並且發送者為“a1”。
接收過程如下:ACLMessage msg = receive( mt );
             if (msg != null) { ... handle message }
             block();
示例:

package jadePrime.acl;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午9:07:11 
 */
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class Template extends Agent {
    MessageTemplate mt1 = MessageTemplate.and(MessageTemplate.MatchPerformative(ACLMessage.INFORM),
            MessageTemplate.MatchSender(new AID("a1", AID.ISLOCALNAME)));

    protected void setup() {
        // Send messages to "a1" and "a2"

        ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
        msg.setContent("Ping");
        for (int i = 1; i <= 2; i++)
            msg.addReceiver(new AID("a" + i, AID.ISLOCALNAME));

        send(msg);

        // Set-up Behaviour 1

        addBehaviour(new CyclicBehaviour(this) {
            public void action() {
                System.out.print("Behaviour ONE: ");
                ACLMessage msg = receive(mt1);
                if (msg != null)
                    System.out.println("gets " + msg.getPerformative() + " from "
                            + msg.getSender().getLocalName() + "=" + msg.getContent());
                else
                    System.out.println("gets NULL");
                block();
            }
        });
        // Set-up Behaviour 2
        addBehaviour(new CyclicBehaviour(this) {
            public void action() {
                System.out.print("Behaviour TWO: ");
                ACLMessage msg = receive();
                if (msg != null)
                    System.out.println("gets " + msg.getPerformative() + " from "
                            + msg.getSender().getLocalName() + "=" + msg.getContent());
                else
                    System.out.println("gets NULL");
                block();
            }
        });
    }
}
package jadePrime.acl;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月14日 下午9:10:07 
 */
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;

public class Responder extends Agent {
    protected void setup() {
        addBehaviour(new CyclicBehaviour(this) {
            public void action() {
                ACLMessage msg = receive();
                if (msg != null) {

                    ACLMessage reply = msg.createReply();
                    reply.setPerformative(ACLMessage.INFORM);
                    reply.setContent(" Gossip.....");
                    send(reply);

                    reply.setPerformative(ACLMessage.PROPOSE);
                    reply.setContent(" Really sexy stuff... cheap! ");
                    send(reply);
                }
                block();
            }
        });
    }
}

輸出結果:
Behaviour ONE: gets NULL
Behaviour TWO: gets 6 from ams=( (action ( agent-identifier :name template@192.168.23.1:1099/JADE  :addresses (sequence http://jacksile:7778/acc )) (ACLMessage) ) (MTS-error ( agent-identifier :name a1@192.168.23.1:1099/JADE ) (internal-error "Agent not found: getContainerID() failed to find agent a1@192.168.23.1:1099/JADE")) )
Behaviour ONE: gets NULL

Base64:發送消息為java序列化對象

在JADE中,支持Agents之間通信的消息內容使用序列化的java對象,對本地應用,特別是所有Agent都用java實現的情況下也是很有用的.
看實例:一個ObjectSender負責發送一個Person對象,ObjectReceiver負責接收后打印出接收到的內容。
源文件:Person.java

package examples.Base64;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:34:47 
 */
import java.io.Serializable;
import java.util.Date;

public class Person implements Serializable {
    String name;
    String surname;
    Date birthdate;
    int age;

    Person(String n, String s, Date d, int a) {
        name = n;
        surname = s;
        birthdate = d;
        age = a;
    }

    public String toString() {
        return (name + " " + surname + " born on " + birthdate.toString() + " age = " + age);
    }
}

文件2:ObjectSender.java

package examples.Base64;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:35:47 
 */
import jade.core.AID;
import jade.core.Agent;
import jade.lang.acl.ACLMessage;

import java.io.IOException;
import java.util.Date;

public class ObjectSender extends Agent {
    protected void setup() {

        try {
            ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
            msg.setContent("Ping");

            AID personR = new AID("personR", AID.ISLOCALNAME);
            msg.addReceiver(personR);
            Person p = new Person("Name1", "Surname1", new Date(), 1);
            msg.setContentObject(p);
            msg.setLanguage("JavaSerialization");
            send(msg);
            System.out.println(getLocalName() + " sent 1st msg " + msg);

            send(msg);

        } catch (IOException e) {
            e.printStackTrace();
        }

        doDelete(); // kill itself because it has completed its task.

    }

}

文件三:ObjectReceiver.java

package examples.Base64;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:37:17 
 */
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.UnreadableException;

public class ObjectReceiver extends Agent {
    protected void setup() {
        addBehaviour(new CyclicBehaviour(this) {
            public void action() {
                try {
                    ACLMessage msg = blockingReceive();
                    System.out.println(getLocalName() + " rx msg" + msg);
                    if ("JavaSerialization".equals(msg.getLanguage())) {
                        Person p = (Person) msg.getContentObject();
                        System.out.println(getLocalName() + " 獲取Java對象: ");
                        System.out.println(p.getClass().getName());
                        System.out.println(p.toString());
                    }
                } catch (UnreadableException e3) {
                    System.err.println(getLocalName() + " catched exception " + e3.getMessage());
                }

                block();
            }
        });
    }

}

外部應用程序調用Agent
JADE2.3以后的版本都提供了in-process接口來實現外部應用程序對Agent的調用。
我們可以通過jade.core.Runtime.instance()來獲得jade運行時的一個單獨得實例。有兩種方法可以用來創建一個jade主容器和一個jade遠程容器。主要調用過程如下:

wpsC4FA.tmp

先看簡單的例子:

package inprocess;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:48:37 
 */
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;

/**
 *
 * @author Administrator
 */
public class CustomAgent extends Agent {

    public void setup() {
        SimpleBehaviour helloBehaviour = new SimpleBehaviour(this) {
            boolean finished = false;

            public void action() {
                System.out.println("Hello World Behaviour run: 你好,世界!");
                System.out.println("-----我是:-----");
                System.out.println("我的本地名稱是:" + getLocalName());
                System.out.println("我全局唯一的標志名稱為:" + getName());
                finished = true;
            }

            public boolean done() {
                return finished;
            }

        };
        addBehaviour(helloBehaviour);
    }

}

以上是要調用的Agent類

package inprocess;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:49:43 
 */

import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;

public class InprocessTest {

    public static void main(String args[]) {
        try {
            Runtime rt = Runtime.instance();
            rt.setCloseVM(true);
            Profile pMain = new ProfileImpl(null, 8888, null);
            System.out.println("Launching a whole in-process platform..." + pMain);
            AgentContainer mc = rt.createMainContainer(pMain);
            // set now the default Profile to start a container
            ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
            System.out.println("Launching the Agent container ..." + pContainer);
            AgentController custom = mc.createNewAgent("custom", "inprocess.CustomAgent", null);
            custom.start();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}// 以上是調用者,在Eclipse中調試通過。

再看一個例子,也是main函數中動態創建Agent的例子。可以通過先創建另一個容器,然后再這個容器中創建Aent。比如:

public static void main(String[] args) {
        // TODO code application logic here
        Runtime rt = Runtime.instance();
        rt.setCloseVM(true);
        ContainerController cc =  rt.createAgentContainer(new ProfileImpl(false));
        
        AgentController pingAgent = null;
        try    {
            // create Agent and start it
            (cc.createNewAgent("hello", "jadeclient.HelloWorldAgent", new Object[0])).start();
        } catch (Exception e){}
    }

可以寫如下測試程序,這里用Eclipse平台,一個HelloWorldAgent,他將被動態創建並向主容器中的server發送一個消息:

package jadeclient;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:50:50 
 */
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;

public class HelloWorldAgent extends Agent {
    public void setup() {

        addBehaviour(new SimpleBehaviour(this) {
            boolean finished = false;
            AID server = new AID("server", AID.ISLOCALNAME);

            public void action() {
                System.out.println("我的本地名稱是:" + getLocalName());
                ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
                msg.setContent("消息內容");
                msg.addReceiver(server);
                send(msg);
                System.out.println("已經往主容器中的server發送信息#");
                block(1000);

                finished = true;
            }

            public boolean done() {
                return finished;
            }
        });
    };
}

而server角色是收到消息后打印出來。

/*
 * ReceiverAgent.java
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package jadeclient;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:51:57 
 */
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;

/**
 *
 * @author admin
 */
public class ReceiverAgent extends Agent {

    /** Creates a new instance of ReceiverAgent */

    // 把接收到的信息打印出來
    protected void setup() {
        addBehaviour(new CyclicBehaviour(this) {
            public void action() {
                ACLMessage msg = receive();
                if (msg != null)
                    System.out
                            .println("收到信息 " + myAgent.getLocalName() + " <- " + msg.getContent());
                block();
            }
        });
    }

}

所有類寫完之后,這里運行的時候先打開GUI管理器,然后GUI界面下創建一個名叫server的Agent,其類為jadeclient. ReceiverAgent,然后再創建一個名叫hello的Agent,其類為jadeclient.HelloWorldAgent.,記住,順序不能變
在GUI界面管理器顯示如下,在Eclipse平台中下面顯示的是打印出的信息,可見在同一主機的不同容器中Agent通信與在同一容器中通信並無二樣。

wps3655.tmp

wps3665.tmp

看一個稍微復雜的例子:

package examples.inprocess;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:53:06 
 */

import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.core.behaviours.CyclicBehaviour;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;

public class InProcessTest {

    // Simple class behaving as a Condition Variable
    public static class CondVar {
        private boolean value = false;

        synchronized void waitOn() throws InterruptedException {
            while (!value) {
                wait();
            }
        }

        synchronized void signal() {
            value = true;
            notifyAll();
        }

    } // End of CondVar class

    // This class is a custom Agent, accepting an Object through the
    // object-to-Agent communication channel, and displying it on the
    // standard output.
    public static class CustomAgent extends jade.core.Agent {

        public void setup() {
            // Accept objects through the object-to-Agent communication
            // channel, with a maximum size of 10 queued objects
            setEnabledO2ACommunication(true, 10);

            // Notify blocked threads that the Agent is ready and that
            // object-to-Agent communication is enabled
            Object[] args = getArguments();
            if (args.length > 0) {
                CondVar latch = (CondVar) args[0];
                latch.signal();
            }

            // Add a suitable cyclic behaviour...
            addBehaviour(new CyclicBehaviour() {

                public void action() {
                    // Retrieve the first object in the queue and print it on
                    // the standard output
                    Object obj = getO2AObject();
                    if (obj != null) {
                        System.out.println("Got an object from the queue: [" + obj + "]");
                    } else
                        block();
                }

            });
        }

        public void takeDown() {
            // Disables the object-to-Agent communication channel, thus
            // waking up all waiting threads
            setEnabledO2ACommunication(false, 0);
        }

    } // End of CustomAgent class

    public static void main(String args[]) {

        try {
            Runtime rt = Runtime.instance();// 獲取jade運行時

            // Exit the JVM when there are no more containers around
            rt.setCloseVM(true);

            // 看運行參數中是否有-container
            if (args.length > 0) {
                if (args[0].equalsIgnoreCase("-container")) {
                    // 創建一個默認的profile
                    Profile p = new ProfileImpl(false);
                    // p.setParameter(Profile.MAIN, "false");

                    // Create a new non-main container, connecting to the default
                    // main container (i.e. on this host, port 1099)
                    System.out.println("Launching the Agent container ..." + p);
                    AgentContainer ac = rt.createAgentContainer(p);

                    // 創建一個新的Agent
                    AgentController dummy = ac.createNewAgent("inProcess",
                            "jade.tools.DummyAgent.DummyAgent", new Object[0]);

                    // 啟動它
                    System.out.println("Starting up a DummyAgent...");
                    dummy.start();

                    // 等10秒
                    Thread.sleep(10000);

                    // 殺死這個Agent
                    System.out.println("Killing DummyAgent...");
                    dummy.kill();

                    // 在同一虛擬機上創建另一個容器,NB,
                    // NB. 兩個容器不能共享同一個 Profile對象!!! -->
                    // 所以需再創建一個profile對象
                    p = new ProfileImpl(false);
                    // p.putProperty(Profile.MAIN, "false");
                    AgentContainer another = rt.createAgentContainer(p);

                    // 用兩個參數創建一個移動agnet
                    Object[] arguments = new Object[2];
                    arguments[0] = "Hello World!";
                    arguments[1] = dummy;
                    AgentController mobile = another.createNewAgent("Johnny",
                            "examples.mobile.MobileAgent", arguments);
                    mobile.start();

                    return;
                }
            }

            // 在8888端口運行一個完整的平台t
            // create a default Profile
            Profile pMain = new ProfileImpl(null, 8888, null);

            System.out.println("Launching a whole in-process platform..." + pMain);
            AgentContainer mc = rt.createMainContainer(pMain);

            // 使用默認的profile啟動一個容器
            ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
            System.out.println("Launching the Agent container ..." + pContainer);
            AgentContainer cont = rt.createAgentContainer(pContainer);
            System.out.println("Launching the Agent container after ..." + pContainer);

            System.out.println("Launching the rma Agent on the main container ...");
            AgentController rma = mc.createNewAgent("rma", "jade.tools.rma.rma", new Object[0]);
            rma.start();

            // Launch a custom Agent, taking an object via the
            // object-to-Agent communication channel. Notice how an Object
            // is passed to the Agent, to achieve a startup synchronization:
            // this Object is used as a POSIX 'condvar' or a Win32
            // 'EventSemaphore' object...

            CondVar startUpLatch = new CondVar();

            AgentController custom = mc.createNewAgent("customAgent", CustomAgent.class.getName(),
                    new Object[] { startUpLatch });
            custom.start();

            // Wait until the Agent starts up and notifies the Object
            try {
                startUpLatch.waitOn();
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }

            // Put an object in the queue, asynchronously
            System.out.println("Inserting an object, asynchronously...");
            custom.putO2AObject("Message 1", AgentController.ASYNC);
            System.out.println("Inserted.");

            // Put an object in the queue, synchronously
            System.out.println("Inserting an object, synchronously...");
            custom.putO2AObject(mc, AgentController.SYNC);
            System.out.println("Inserted.");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

現在看看servlet能不能調用這個,在Eclipse中建立一個web工程,添加jade庫,建立一個servlet在servlet中進行調用Agent,看能不能輸出結果。
其中主要文件如下
文件名:StartServlet.java:

package examples;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午12:57:37 
 */

import jade.core.Profile;
import jade.core.ProfileImpl;
import jade.core.Runtime;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class StartServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet StartServlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Servlet StartServlet at " + request.getContextPath() + "</h1>");
        out.println("<font size=10 >你好</font>");
        try {
            Runtime rt = Runtime.instance();
            rt.setCloseVM(true);
            Profile pMain = new ProfileImpl(null, 8888, null);

            AgentContainer mc = rt.createMainContainer(pMain);
            // set now the default Profile to start a container
            ProfileImpl pContainer = new ProfileImpl(null, 8888, null);
            out.println("運行Agent容器 ..." + pContainer);
            AgentController rma = mc.createNewAgent("rma", "jade.tools.rma.rma", null);
            rma.start();
            AgentController custom = mc.createNewAgent("custom", "examples.CustomAgent", null);
            custom.start();

            out.println("我已經啟動了一個小Agent");

        } catch (Exception e) {
            e.printStackTrace();
        }

        out.println("</body>");
        out.println("</html>");

        out.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    public String getServletInfo() {
        return "Short description";
    }
}

CustomAgent.java:

package examples;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午1:03:40 
 */
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;

public class CustomAgent extends Agent {

    public void setup() {
        SimpleBehaviour helloBehaviour = new SimpleBehaviour(this) {
            boolean finished = false;

            public void action() {
                System.out.println("Hello World Behaviour run: 你好,世界!");
                System.out.println("-----我是:-----");
                System.out.println("我的本地名稱是:" + getLocalName());
                System.out.println("我全局唯一的標志名稱為:" + getName());
                finished = true;
                try {
                    Thread.sleep(40000);
                } catch (java.lang.InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("已經過了40秒鍾");
                // 這里是為了測試關掉IE之后控制台上還會不會輸出信息。
            }

            public boolean done() {
                return finished;
            }

        };
        addBehaviour(helloBehaviour);
    }

}

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>jade</display-name>
   <servlet>
        <servlet-name>StartServlet</servlet-name>
        <servlet-class>examples.StartServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>StartServlet</servlet-name>
        <url-pattern>/StartServlet</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

在url:http://localhost:8888/jade/StartServlet中看到如下結果:
Servlet StartServlet at /jade
你好 運行Agent容器 ...(Profile main=true local-host=59.73.87.114 port=8888 services=jade.core.mobility.AgentMobilityService;jade.core.event.NotificationService host=59.73.87.114 local-port=8888 mtps=[jade.mtp.http.MessageTransportProtocol] jvm=j2se) 我已經啟動了一個小Agent
在Tomcat控制台上輸出信息:
Hello World Behaviour run: 你好,世界!
-----我是:-----
我的本地名稱是:custom
我全局唯一的標志名稱為:custom@deepin-84e2a07b:8888/JADE
已經過了40秒鍾
同時圖形化JADE容器運行,其中“已經過了40秒鍾”是在瀏覽器關閉之后顯示,說明Agent容器及Agent啟動后一直運行着。
奇怪的是,我每次退出主容器,總顯示
Exception while removing reference: java.lang.InterruptedException
java.lang.InterruptedException
        at java.lang.Object.wait(Native Method)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
        at sun.java2d.Disposer.run(Disposer.java:107)
        at java.lang.Thread.run(Thread.java:595)
AWT blocker activation interrupted: //后面這個是JADE GUI的bug么?
java.lang.InterruptedException
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:474)
        at sun.awt.AWTAutoShutdown.activateBlockerThread(AWTAutoShutdown.java:309)
        at sun.awt.AWTAutoShutdown.setToolkitBusy(AWTAutoShutdown.java:226)
        at sun.awt.AWTAutoShutdown.notifyToolkitThreadBusy(AWTAutoShutdown.java:118)
        at sun.awt.windows.WToolkit.eventLoop(Native Method)
        at sun.awt.windows.WToolkit.run(WToolkit.java:269)
        at java.lang.Thread.run(Thread.java:595)
不知道什么問題?
一個Agent如何以程序的方式生成另一個Agent:
可以通過以下方式進行創建:

String name = "Alice" ;
        AgentContainer c = getContainerController();
        try {
            AgentController a = c.createNewAgent( name, "Pong", null );
            a.start();
        }
        catch (Exception e){}

其中,createNewAgent方法的第一個參數是要創建的Agent的名稱,第二個是Agent的類名,實際使用時要包括他所在的命名空間(包名),第三個參數是要傳入的參數的名稱。
例子:

package jadePrime.acl;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午1:08:17 
 */
/**
 * Program which creates another Agent and sends 
 ------------     it some messages
 comm2.java
 * 
 */

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.SimpleBehaviour;
import jade.lang.acl.ACLMessage;
import jade.wrapper.AgentContainer;
import jade.wrapper.AgentController;

public class Comm2 extends Agent {
    String name = "Alice";
    AID alice = new AID(name, AID.ISLOCALNAME);

    protected void setup() {

        AgentContainer c = getContainerController();
        System.out.println("find container!");

        try {
            AgentController a = c.createNewAgent(name, "jadePrime.acl.Pong", null);
            a.start();
            System.out.println("++++pong has created:" + alice);

        } catch (Exception e) {
            System.out.println("Create Agent Error!");
            addBehaviour(new SimpleBehaviour(this) {
                int n = 0;

                public void action() {
                    ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
                    msg.setContent("Message #" + n);
                    msg.addReceiver(alice);
                    System.out.println("+++ Sending: " + n);
                    send(msg);
                    block(1000);
                }

                public boolean done() {
                    return ++n > 3;
                }
            });
        }

    }
}

當我們創建一個Comm2的Agent時,在控制台上會打印出創建alice成功的消息。
如何收集當前AMS中Agent列表

package jadePrime.manage;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午1:09:53 
 */

import jade.core.AID;
import jade.core.Agent;
import jade.domain.AMSService;
import jade.domain.FIPAAgentManagement.AMSAgentDescription;
import jade.domain.FIPAAgentManagement.SearchConstraints;

public class AMSDump extends Agent {
    protected void setup() {
        AMSAgentDescription[] Agents = null;
        try {
            SearchConstraints c = new SearchConstraints();
            c.setMaxResults(new Long(-1));
            Agents = AMSService.search(this, new AMSAgentDescription(), c);
        } catch (Exception e) {
            System.out.println("Problem searching AMS: " + e);
            e.printStackTrace();
        }

        AID myID = getAID();
        for (int i = 0; i < Agents.length; i++) {
            AID AgentID = Agents[i].getName();
            System.out.println((AgentID.equals(myID) ? "*** " : "    ") + i + ": "
                    + AgentID.getName());
        }
        doDelete();
        // System.exit(0);
    }

}// end class AMSDump

詳見:http://www.iro.umontreal.ca/%7Evaucher/Agents/JADE/primer4.html#5

wps3BA8.tmp

JADE中如何使用DF(Directory Facilitator)Agent提供的黃頁服務。
這個比較好理解,DF相當於一個目錄服務器,每個提供服務的Agent可以向DF注冊其服務,然后,其他的Agent可以從DF中查詢該類服務,也可以訂閱這類服務,如果是后者,那么一旦這類服務被注冊到DF中,則訂閱方就可以收到。例程如下:
文件一, DFRegisterAgent.java 服務提供方

package yellowpages;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午1:11:14 
 */

import jade.core.Agent;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPANames;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.Property;
import jade.domain.FIPAAgentManagement.ServiceDescription;

public class DFRegisterAgent extends Agent {

    protected void setup() {
        String serviceName = "unknown";

        // 從命令行的參數中讀取服務的名稱,默認為unknown
        Object[] args = getArguments();
        if (args != null && args.length > 0) {
            serviceName = (String) args[0];
        }

        // 注冊服務
        System.out.println("Agent " + getLocalName() + " registering service \"" + serviceName
                + "\" of type \"weather-forecast\"");
        try {
            // 必要的幾個步驟
            DFAgentDescription dfd = new DFAgentDescription();
            dfd.setName(getAID());
            ServiceDescription sd = new ServiceDescription();
            sd.setName(serviceName);
            sd.setType("weather-forecast");// 設置服務類型為天氣預報
            sd.addOntologies("weather-forecast-ontology");
            sd.addLanguages(FIPANames.ContentLanguage.FIPA_SL);
            // 使用服務的一方必須遵循的規范,和具有的本體知識
            sd.addProperties(new Property("country", "Italy"));
            dfd.addServices(sd);

            DFService.register(this, dfd);
        } catch (FIPAException fe) {
            fe.printStackTrace();
        }
    }
}

文件二.
DFSubscribeAgent.java訂閱方

package yellowpages;

/** 
 * @function 
 * @author Jacksile E-mail:tufujietec@foxmail.com 
 * @date 2016年1月15日 下午1:12:26 
 */
import jade.core.AID;
import jade.core.Agent;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.Property;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.proto.SubscriptionInitiator;
import jade.util.leap.Iterator;

public class DFSubscribeAgent extends Agent {

    protected void setup() {
        // Build the description used as template for the subscription
        DFAgentDescription template = new DFAgentDescription();
        ServiceDescription templateSd = new ServiceDescription();
        templateSd.setType("weather-forecast");
        templateSd.addProperties(new Property("country", "Italy"));
        template.addServices(templateSd);

        SearchConstraints sc = new SearchConstraints();
        // 最多能接受10個結果
        sc.setMaxResults(new Long(10));

        addBehaviour(new SubscriptionInitiator(this, DFService.createSubscriptionMessage(this,
                getDefaultDF(), template, sc)) {
            protected void handleInform(ACLMessage inform) {
                System.out.println("Agent " + getLocalName() + ": Notification received from DF");
                try {
                    DFAgentDescription[] results = DFService
                            .decodeNotification(inform.getContent());
                    if (results.length > 0) {
                        for (int i = 0; i < results.length; ++i) {
                            DFAgentDescription dfd = results[i];
                            AID provider = dfd.getName();
                            // 同一個Agent可能提供很多服務,我們只對天氣預報感興趣
                            Iterator it = dfd.getAllServices();
                            while (it.hasNext()) {
                                ServiceDescription sd = (ServiceDescription) it.next();
                                if (sd.getType().equals("weather-forecast")) {
                                    System.out.println("Weather-forecast service for Italy found:");
                                    System.out.println("- Service \"" + sd.getName()
                                            + "\" provided by Agent " + provider.getName());
                                }
                            }
                        }
                    }
                    System.out.println();
                } catch (FIPAException fe) {
                    fe.printStackTrace();
                }
            }
        });
    }
}

這樣,編譯后,我們為了體現發布服務和訂閱服務時間上的一致關系,我們從命令行來運行這些類。假設已編譯成功,文件標志在某目錄下yellowpages\ DFSubscribeAgent.class 和yellowpages\ DFRegisterAgent.class,我們在yellowpages目錄下運行命令
java jade.Boot –gui service1: yellowpages.DFRegisterAgent
系統運行主容器,同時控制台上顯示Agent service1 registering service “noname” of type "weather-forecast"
然后我們在圖形界面下,start new Agent,AgentName:subscriber ClassName:yellowpages.DFSubscribeAgent 添加后,控制台上會顯示相關啟動后的信息,但不會顯示收到服務的消息。然后再start new Agent,AgentName:service2 ClassName:yellowpages.DFRegisterAgent 參數設為:rainny,這是控制台上顯示注冊服務成功的消息和訂閱到服務的消息。顯示如下:

wps5752.tmp

JADE中使用本體:
    Agent之間進行通信要有相同的語言,詞匯和協議。在JADE中,Agents之間通信的方式可以有三種:1.使用字符串表達信息的內容,是最基本的方式.當消息內容是原子數據時,這種方式非常便利.2.消息內容使用序列化的java對象,對本地應用,特別是所有Agent都用java實現的情況下也是很有用的.3.為了jade能夠以FIPA格式隊消息進行編碼和解碼,擴展預先定義好的類,亦即使用本體的方式。這種方式允許jade的Agent可以同其他異質Agent系統進行互操作。這三種方式下對應設置和獲取內容的方法對應如下:
image
現在有一些已經存在的language來描述ontologies,如DAML+OIL和OWL,JADE並不直接支持這些ontologies,而是將ontologies編碼為java類(比如protégé可以將本體直接導出為java類)。
本體提供了Agent交互的語義支持,但必須與內容語言結合使用,后者是Agent交互的語法支持。JADE支持的三種內容語言包括:FIPA-SL類似lisp的語言族;Leap-encoding應用於嵌入式開發;JavaCodec,JADE特定的內容語言。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM