1

JADE マルチエージェント フレームワークを使用した場合のContractNet (Interaction Protocol) と GUIの使用に問題があります。

特に、handleProposeメソッドのオーバーライドでは。私の問題は、GUI の使用に起因することを知っています。説明させてください:

私のエージェント (イニシエーター) は最初の GUI を使用し、クリック後、2 番目のエージェント (レスポンダー) との会話が始まります。プロトコルによると、イニシエーターは CFP をレスポンダーに送信しました。エージェントの Responder は、異なるデータを含む PROPOSE で応答します。

ここから、すべてOK。今...

エージェントのイニシエーターが、応答を返す前にデータを調べてくれることを願っています...つまり、ユーザーのために JTable でデータを公開します! ユーザーは GUI を介して提案を調べ、ボタンをクリックして受け入れるかどうかを選択します。

  • 受け入れた場合、イニシエーターは ACCEPT_PROPOSAL を送信します。
  • 受け入れない場合、イニシエータは REJECT_PROPOSAL を送信します。

これは、メソッドhandleProposalで行う必要があります。これは私のコードです:

@Override
protected void handlePropose(final ACLMessage propose, final Vector acceptances) {
    try {
        System.out.println("Agent "+getLocalName()
            +": receive PROPOSE from "+propose.getSender().getLocalName());

        final ACLMessage reply = propose.createReply();

        Vector<Goods> goods = (Vector<Goods>) propose.getContentObject();

        // the JTable's GUI for visualize the list of data:
        final GoodsChoiceBox gcb = new GoodsChoiceBox(propose.getSender().getName(), goods);

        // the problem:
        gcb.getExecuteJButton().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
               reply.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
               System.out.println("Agent "+getLocalName()+": send ACCEPT PROPOSAL ");
               acceptances.addElement(reply);
            }
        });

        // similar case, but for REJECT:
        // gcb.getAbortJButton().addActionListener(... bla bla

        gcb.setVisible(true);

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

.....しかし、明らかに機能しません。

イニシエーター エージェントでは、ContractNet の動作が中止されます。そのため、handleInform、handleRefuse、handleFailure (回答の処理用) も機能しません。イニシエータのプリンシパル GUI がブロックされています。そして他の問題...

代わりに、これを行うと(JButton、別のGUI、ActionListenerなし):

@Override
protected void handlePropose(final ACLMessage propose, final Vector acceptances) {
    try {
        System.out.println("Agent "+getLocalName()
            +": received PROPOSE from "+propose.getSender().getLocalName());
        final ACLMessage reply = propose.createReply();

        Vector<Goods> goods = (Vector<Goods>) propose.getContentObject();

        // the JTable's GUI for visualize the list of data:
        final GoodsChoiceBox gcb = new GoodsChoiceBox(propose.getSender().getName(), goods);

        reply.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
        System.out.println("Agente "+getLocalName()+": ACCEPT PROPOSAL di "+propose.getSender().getLocalName());
        acceptances.addElement(reply);

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

ちゃんと動きます。

問題は ActionListener とそのマルチスレッドの性質にあることはわかっています。しかし、そこにGUIが必要です。

どうすれば修正できますか?

4

3 に答える 3

1

私は自分自身に答えようとします。それが最善の解決策かどうかはわかりませんが、確かに機能します。

このソリューションにたどり着く前に、( 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)

さらに進むと、私が取らなければならなかった変更に気付くでしょう。

  1. ShipperAgent は各 BuyerAgent に CFP を送信します。

  2. 各 BuyerAgent:

    2.1 彼が商品を持っている場合、PROPOSE を ShipperAgent に送信します。

    2.2 商品を持っていない場合は、ShipperAgent に REFUSE を送信します。そして買い手にとって、プロトコルは終了します。

ここは簡単だから。スニファーを使用すると、次のことを観察できます。

ここに画像の説明を入力

今:

  1. 荷送人エージェント:

    3.1 購入者から 1 つまたは複数の提案を受け取り、表示します (下の画像を参照)。

    3.2 拒否を受信した場合 (または一定時間経過しても何も受信しない場合)、それらの購入者との通信を終了します。

Shipper がプロポーザルをグラフィカルに表示する方法を次に示します。

ここに画像の説明を入力

現在、どの商品が必要で、何が必要でないかを選択するのはユーザー次第です。

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

ここに画像の説明を入力

  1. 荷送人エージェント:

     4.1 ユーザーが 1 つまたは複数の商品提案を選択した (そして [実行] をクリックした) 場合、対応する BuyerAgent に ACCEPT_PROPOSAL を送信します。

     4.2 ユーザーが商品を選択しない場合 (または [キャンセル] をクリックしない場合)、対応する BuyerAgent に REJECT_PROPOSAL を送信します。その購入者への通信を終了します。

  2. バイヤーエージェント:

     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
     */
}

私は知っています、私はたくさん住んでいますが、他にどのように説明すればよいかわかりませんでした。しかし、今私のプロジェクトの仕事。しかし、私はどんな提案にもオープンです。

于 2015-01-13T18:59:55.333 に答える
0

私はよくこの種の問題に遭遇します。これらは有限状態マシンの動作であるため、動作を一時停止および再開できるはずですが、その方法はわかりません。私が行っているのは、イニシエーター側とレスポンダー側に 1 つの 2 つの個別の対話動作を作成することです。

Initiator                      Responder
|                                |
|                                |
| First behaviour                |The responder only has 1 behaviour
||        CFP->                 ||
||        <-Proposal            ||
|                               ||
| Second behaviour              ||
||        Accept prop->         ||
||        <-Response            ||
|                                |

覚えておきたい2つのポイント

(1)

会話IDを必ず保存してください

msgRecieved.getConversationID

最初の動作から取得し、2 番目の動作で使用します。

msg.setConversationID().

(2) 2 番目の動作は別のコントラクト ネット イニシエータですが、prepareCFPs メソッドで MESSAGE パフォーマティブを設定して提案を受け入れるようにします

クラス ContractServiceList は ContractNetInitiator を拡張します {

    protected Vector prepareCfps(ACLMessage cfp) {

        ACLmessage AP= new ACLmessage(ACLmessage.ACCEPT_PROPOSAL)
.....

これらのことは説明するのが難しいので、写真を添付し​​ようとしましたが、2 つの小さな担当者ポイントがあります。

私は今、私がやっている写真を添付するのに十分な担当者ポイントを持っています.

ここに画像の説明を入力

于 2014-12-21T16:31:16.473 に答える