私は自分自身に答えようとします。それが最善の解決策かどうかはわかりませんが、確かに機能します。
このソリューションにたどり着く前に、( http://jade.tilab.com/にある) ガイドとチュートリアルを十分に文書化し、(メーリング リストhttp://jade.tilab. com/pipermail/jade-develop/ )
答えは複雑なので、網羅しようと思います。
私のプロジェクトでは、2 種類のエージェントを扱う必要があります。
- 1 つの荷送人を表すShipperAgent : 荷送人が所有する車両、利用可能な車両、「予約済み」の商品を追跡します。

- 顧客(または買い手)を表すBuyerAgent :各顧客は、地点 A から地点 B に移動したい商品のリストを持っています。

2 つのエージェントがイエロー ページ サービスに登録されます。
ShipperAgent で、[SEARCH] ボタンをクリックして検索を開始します。Contract Net Interaction Protocolを開始します。
Contract Net Interaction Protocolと私のケースを説明する
標準FIPA: http://www.fipa.org/specs/fipa00029/SC00029H.html

JADE のガイドはこちらにあります: http://jade.tilab.com/doc/programmersguide.pdf (p. 35)
さらに進むと、私が取らなければならなかった変更に気付くでしょう。
ShipperAgent は各 BuyerAgent に CFP を送信します。
各 BuyerAgent:
2.1 彼が商品を持っている場合、PROPOSE を ShipperAgent に送信します。
2.2 商品を持っていない場合は、ShipperAgent に REFUSE を送信します。そして買い手にとって、プロトコルは終了します。
ここは簡単だから。スニファーを使用すると、次のことを観察できます。

今:
荷送人エージェント:
3.1 購入者から 1 つまたは複数の提案を受け取り、表示します (下の画像を参照)。
3.2 拒否を受信した場合 (または一定時間経過しても何も受信しない場合)、それらの購入者との通信を終了します。
Shipper がプロポーザルをグラフィカルに表示する方法を次に示します。

現在、どの商品が必要で、何が必要でないかを選択するのはユーザー次第です。
これを実現するために、エージェント自身との何らかの「内部通信」を作成する必要がありました。GUI (3.1 の場合) は、[実行] をクリックすると、エージェントにメッセージを送信します。洗練されていないように見えるかもしれませんが、プロトコル側の ShipperAgent をクラッシュさせない唯一の方法のようです。

荷送人エージェント:
4.1 ユーザーが 1 つまたは複数の商品提案を選択した (そして [実行] をクリックした) 場合、対応する BuyerAgent に ACCEPT_PROPOSAL を送信します。
4.2 ユーザーが商品を選択しない場合 (または [キャンセル] をクリックしない場合)、対応する BuyerAgent に REJECT_PROPOSAL を送信します。その購入者への通信を終了します。
バイヤーエージェント:
5.1 ACCEPT_PROPOSAL を受信した場合、商品がまだ入手可能であることを確認し (その間、他の荷送人が商品を「予約」している可能性があります)、そうであれば、INFORM を送信します。
5.2 ACCEPT_PROPOSAL を受信した場合、1 つまたは複数の商品が入手できなくなった場合は、FAILURE を送信します。
5.3 REJECT_PROPOSAL を受信した場合、ShipperAgent との通信を終了します。

これを簡単に説明すると(たとえば):

コード
BuyerAgent.java
いつでも CFP を受け取る準備ができているディスパッチャを作成します。プロトコルを受信して開始するとすぐに、バイヤー側: SearchJobResponder を開始します。
/*
* ...
*/
final MessageTemplate template = MessageTemplate.and(
MessageTemplate.MatchProtocol(FIPANames.InteractionProtocol.FIPA_CONTRACT_NET),
MessageTemplate.MatchPerformative(ACLMessage.CFP) );
// SSResponderDispatcher:
SSResponderDispatcher dispatcher = new SSResponderDispatcher(this, template) {
BuyerAgent b = (BuyerAgent) this.myAgent;
protected Behaviour createResponder(ACLMessage initiationMsg) {
// SearchJobResponder for single cfp:
return new SearchJobResponder(b, initiationMsg);
}
};
addBehaviour(dispatcher);
/*
* ...
*/
ShipperAgent.java
すべてのバイヤーを検索し、CFP を作成してプロトコルを開始します。シッパー側: SearchJobInitiator を開始します。
/*
* ...
*/
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
AID[] buyerAgents = searchBuyers(); // search all buyerAgents
for (AID buyer : buyerAgents)
cfp.addReceiver(buyer);
addBehaviour(new SearchJobInitiator(this, cfp));
/*
* ...
*/
SearchJobInitiator.java
これは難しい部分でした...
/*
* ...
*/
public class SearchJobInitiator extends ContractNetInitiator {
ShipperAgent shipperAgent;
public SearchJobInitiator(ShipperAgent a, ACLMessage cfp) {
super(a, cfp);
shipperAgent=a;
// Very important:
registerHandleAllResponses(new HandleProposes());
}
@Override
protected Vector<?> prepareCfps(ACLMessage cfp) {
long now = System.currentTimeMillis();
cfp.setConversationId("contractNet-by-"
+shipperAgent.getAID().getLocalName()+now);
cfp.setContent("Fammi delle proposte di lavoro");
/*
* filtering...
*/
cfp.setProtocol(FIPANames.InteractionProtocol.FIPA_CONTRACT_NET);
cfp.setReplyByDate(new Date(now+10000));
//cfp.setReplyWith("cfp"+System.currentTimeMillis()) //useless, is overwrited at the end
return super.prepareCfps(cfp);
}
//inner class for handling a single proposal
public class HandleProposes extends Behaviour {
private static final long serialVersionUID = 1L;
private Vector<ACLMessage> proposes;
private Vector<ACLMessage> acceptances;
private int numberOfProposes;
public void onStart() {
proposes = (Vector<ACLMessage>) getDataStore().get(ALL_RESPONSES_KEY);
acceptances = (Vector<ACLMessage>) getDataStore().get(ALL_ACCEPTANCES_KEY);
numberOfProposes=proposes.size();
for (Iterator I=proposes.iterator(); I.hasNext();) {
ACLMessage propose = (ACLMessage) I.next();
// Very important:
if (propose.getPerformative()==ACLMessage.PROPOSE)
myAgent.addBehaviour(new HandleSinglePropose(propose, acceptances));
else
numberOfProposes--;
}
}
public void action() {
if (!done())
block();
}
public boolean done() {
return (acceptances.size()==numberOfProposes);
}
/*
* Inner class for handle a single proposal and display it:
*/
public class HandleSinglePropose extends Behaviour {
private ACLMessage propose;
private Vector<ACLMessage> acceptances;
private boolean finish=false;
public HandleSinglePropose (ACLMessage propose, Vector<ACLMessage> acceptances) {
this.propose=propose;
this.acceptances=acceptances;
// This is GUI in 3.1 point
GoodsChoiceBox gcb = new GoodsChoiceBox(shipperAgent, this, propose); // fill the JTable
gcb.setVisible(true);
}
@Override
public void action() {
MessageTemplate mt = MessageTemplate.and(
MessageTemplate.MatchSender(shipperAgent.getAID()),
MessageTemplate.and(
MessageTemplate.MatchReplyWith("response"+propose.getReplyWith()),
MessageTemplate.or(
MessageTemplate.MatchPerformative(ACLMessage.ACCEPT_PROPOSAL),
MessageTemplate.MatchPerformative(ACLMessage.REJECT_PROPOSAL)
) ) ) ;
// Read data from GUI. The user accept or reject:
ACLMessage decisionFromGUI = shipperAgent.receive(mt);
if (decisionFromGUI != null) {
ACLMessage reply = propose.createReply();
// bla bla...
finish=true;
HandleProposes.this.restart();
} else {
block();
}
}
public boolean done() {
return finish;
}
public void handleChoice(ACLMessage propose, boolean bool, Vector<Goods> selectedGoods) {
ACLMessage reply;
if (bool){
reply = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
//...
} else {
reply = new ACLMessage(ACLMessage.REJECT_PROPOSAL);
//...
}
reply.addReceiver(shipperAgent.getAID());
reply.setReplyWith("response"+propose.getReplyWith());
shipperAgent.send(reply);
}
} // closes HandleSinglePropose
} // closes HandleProposes
}
SearchJobResponder.java
レスポンダーは単純です。唯一の注意点: 私は SSContractNetResponder を拡張しますが、ContractNetResponder は拡張しません。
public class SearchJobResponder extends SSContractNetResponder {
BuyerAgent buyerAgent;
public SearchJobResponder(BuyerAgent a, ACLMessage cfp) {
super(a, cfp);
buyerAgent = a;
}
/*
* override methods...
*/
}
GoodsChoiceBox.java
提案を表示するための GUI...
public GoodsChoiceBox(final Agent agent, final HandleSinglePropose behaviour, final ACLMessage propose){
/*
* graphics stuff
*/
// if goods selected and press Execute
behaviour.handleChoice(propose,true,selectedGoods);
//else
behaviour.handleChoice(propose,false,null);
/*
* bla bla
*/
}
私は知っています、私はたくさん住んでいますが、他にどのように説明すればよいかわかりませんでした。しかし、今私のプロジェクトの仕事。しかし、私はどんな提案にもオープンです。