エージェント名 | ファイル名 | 説明 |
---|---|---|
Sample040 | Sample040.dash | ベースプロセスを持つエージェント |
classes\baseProcess\dashSample\SimpleWindow.class (src\baseProcess\dashSample\SimpleWindow.javaをコンパイルしたもの) | ベースプロセス |
1 (agent Sample040 2 3 (property 4 (create :author "Har@CIT") 5 ) 6 7 (initial_facts 8 (worker :name suzuki) 9 (worker :name hara) 10 ) 11 12 (knowledge 13 14 (rule startup 15 (Msg :performative __INIT_I) 16 (Status :name ?name) 17 --> 18 (inspect nonstop) 19 (loadBP baseProcess.dashSample.SimpleWindow) // BP読み込み 20 (startBP) // run()呼び出し 21 (control startup ()) // startup()呼び出し 22 (control setWindowTitle(?name)) // setWindowTitle()呼び出し 23 ) 24 25 (rule worker 26 (worker :name ?name) 27 ~(Msg :performative __INIT_C) 28 --> 29 (control println (?name)) // println()呼び出し 30 ) 31 32 (rule worker2 33 (worker :name ?name1) 34 (worker :name ?name2) 35 ~(Msg :performative __INIT_C) 36 --> 37 (bind ?member (control cat (?name1 ?name2))) // cat()呼び出し 38 (make (group :member ?member)) 39 ) 40 41 42 // ベースプロセスからのイベントを処理する 43 (rule event-handling 44 (Msg :performative __Event :content (?string)) 45 --> 46 (send :performative notify :to _interface :content (?string)) 47 ) 48 49 ) 50 ) |
14〜23: | ワークプレースエージェントの起動時(15行で判別)に、
ベースプロセスの読み込みと起動を行い、インスペクタを開き、
ベースプロセスのメソッドstartup(), setWindowTitle()を呼び出す。 ワークプレースエージェントの名前は(Status ...)ファクトで取得できる。 |
25〜30: | リポジトリエージェントではない場合(27行で判別)、 ベースプロセスのメソッドprintln()を呼び出す。 |
32〜39: | リポジトリエージェントではない場合に実行する。 |
37: | ベースプロセスのメソッドcat()を呼び出し、 返値を変数?menberにバインドする。 |
38: | ファクトを作る。 |
43〜47: | ベースプロセスが上げたイベントを、 ACLエディタに送信する。 |
44: | イベントはこんな感じで拾う。 |
46: | ACLエディタに送信するには、:toを _interfaceにする。 |
●ベースプロセス (SimpleWindow.java)
1 package baseProcess.dashSample; 2 3 import java.util.*; 4 import java.awt.*; 5 import java.awt.event.*; 6 import javax.swing.*; 7 import javax.swing.border.*; 8 import dash.*; 9 10 public class SimpleWindow extends JFrame implements DashBP, ActionListener { 11 12 private DashAgent agent; 13 14 JTextField textfield; 15 JTextArea textarea; 16 JButton button; 17 JPanel panel; 18 19 /** コンストラクタ。アクション(loadBP)実行時に呼ばれる。 */ 20 public SimpleWindow(){ 21 super( "SimpleWindow" ); 22 } 23 24 /** アクション(loadBP)実行時に呼ばれる。*/ 25 public void setAgent(DashAgent agent){ 26 this.agent = agent; 27 } 28 29 /** アクション(startBP)実行時に呼ばれる */ 30 public void run(){ 31 setup(); 32 } 33 34 /** エージェントの終了時に呼ばれる */ 35 public void finalizeBP(){ 36 dispose(); 37 } 38 39 /** エージェントにイベントを上げる */ 40 public void actionPerformed( ActionEvent ae ){ 41 if(agent != null){ 42 agent.raiseEvent(textfield.getText()); 43 } 44 } 45 46 /** ルールstartup内で呼び出される */ 47 public void startup() { 48 textarea.append( "起動\n" ); 49 } 50 51 /** ルールworker内で呼び出される */ 52 public void println( Object[] str){ 53 textarea.append( (String)str[0] + "\n" ); 54 } 55 56 /** ルールworker2内で呼び出される */ 57 public String cat(Object[] str){ 58 return ( str[0] + " " + str[1] ); 59 } 60 61 /** ルールstartup内で呼び出される */ 62 public void setWindowTitle( Object[] str1 ){ 63 setTitle("sWin:"+str1[0]); 64 } 65 66 /** ウィンドウを作る */ 67 private void setup(){ 68 69 textfield = new JTextField(); 70 textfield.setBorder( new TitledBorder( "入力" ) ); 71 72 textarea = new JTextArea( 6, 20 ); 73 JScrollPane sc = new JScrollPane( textarea ); 74 sc.setBorder( new TitledBorder( "出力" ) ); 75 76 button = new JButton( "エージェントに通知" ); 77 button.addActionListener( this ); 78 79 getContentPane().add( textfield, BorderLayout.NORTH ); 80 getContentPane().add( sc, BorderLayout.CENTER ); 81 getContentPane().add( button, BorderLayout.SOUTH ); 82 83 pack(); 84 setVisible( true ); 85 } 86 87 /** テスト用 */ 88 public static void main( String[] args ){ 89 SimpleWindow window = new SimpleWindow(); 90 window.setup(); 91 } 92 } |
1: | パッケージ名はbaseProcessでなくても可。 |
10: | インタフェースdash.DashBPをimplementsする必要がある。 |
12: | エージェント本体。 ベースプロセスからエージェントにイベントを上げるときに使う(42行)。 |
20〜22: | 引数無しのコンストラクタが必要。 コンストラクタの中では、ウィンドウは作らない方がよい。 インスタンス生成後にrun()メソッドが呼び出されるので、そこで作る。 |
25〜27: | コンストラクタの次に呼ばれる。 エージェント本体を受け取るので、 こんな感じで保管しておく。 |
30〜32: | アクション(startBP)実行時に呼ばれる。 ベースプロセスはスレッドとして動作する。 ここからベースプロセスの処理を記述する。 ただし、この例ではウィンドウ作成処理(67行〜)をした後 直ちに終了する(ウィンドウ内で独自にスレッドをもつため) |
35〜37: | 終了時にエージェントから呼び出される。 |
40〜44: | ベースプロセスからエージェントにイベントを上げる。 ルールevent-handling(43行)で処理される。 |
47〜49: | ルールstartupの21行でエージェントから呼ばれるメソッド。 |
52〜54: | ルールworkerの29行でエージェントから呼ばれるメソッド。 |
57〜59: | ルールworker2の37行でエージェントから呼ばれるメソッド。 |
62〜64: | ルールstartupの22行でエージェントから呼ばれるメソッド。 |
起動 hara suzuki |
(group :member "suzuki hara") (gourp :member "hara suzuki") |
ベースプロセスはエージェントのタスク処理モジュール(TPM)により、 起動/監視/制御/終了される。TPMから直接起動できるのはJavaプログラムのみである。 他の言語で記述したプログラムをベースプロセスとしたい場合には、 そのプログラムを起動するJavaプログラムを作成し、 それをTPMから起動することで行う。
リポジトリエージェントはベースプロセスを持たない。
●ベースプロセス
呼び出しが可能なメソッドの条件を以下に示す。
上記の例題(SimpleWindow.java)の41行目のように、
setAgent()で受け取ったエージェントに対し、
そのメソッドraiseEvent()を呼び出すことで行う。
public void raiseEvent(String string)は、クラスdash.DashAgentに定義されている。
raiseEvent()を呼び出すと、ワーキングメモリに次のようなファクトが生成される。
(Msg :performative __Event … :content (raiseEventの文字列))
イベント処理は、このファクトを通常のメッセージ処理と同じように処理すれば
できる。Sample040.agtでは、次のようなルールで
イベントをACLエディタに送信している。
(1)改行を含む場合: 各行から改行を除いた文字列を要素とするリストを渡すことができる。
(5)ベースプロセスの作成方法
ベースプロセスを起動するには、次のものを記述する。
●知識記述
(loadBP クラス名)
(startBP)
(6)エージェントからベースプロセスのメソッドを呼び出す方法
アクションcontrolを使うことで、
エージェントはベースプロセスのメソッドを呼び出すことができる。
アクションcontrolは、(control メソッド名 リスト)と記述する。
次のように使う。
と記述する。
・0個の場合: (control メソッド名 ()) ・1個の場合: (control メソッド名 (値)) ・2個以上の場合: (control メソッド名 (値 値 ...))
・メソッドの返値の型がvoidの場合:
controlの返値はTRUEという文字列
・メソッドの返値の型がStringの場合:
scontrolの返値はそのString
だし、nullを返して来た場合TはTRUEという文字列
(7)ベースプロセスからエージェントにイベントを上げる方法
イベントとは、ベースプロセスからエージェントへ通知される情報である。
(rule sample
(Msg :performative __Event :content (?string))
-->
(send :performative notify :to _interface :content (?string))
)
raiseEvent()で渡せるもの:
raiseEvent()の引数は1つの文字列(java.lang.String)のみであるが、
文字列を改行や空白で区切ったり、:をつけることで、
イベントの:content(...)にリストやOAVデータを渡すことができる。
改行を含むか否かで、渡す内容がおおきく異なる。
(2)改行を含まない場合: 次のようなデータを渡すことができる。
"one", "two" という文字列を要素に持つリスト。
呼出 agent.raiseEvnet("one\ntwo\n");
イベント (Msg :performative __EVENT :content (one two))
"", "one", "", "two", "" という文字列を要素に持つリスト。
System.out.println("\none\n\ntwo\n\n");すると
呼出 agent.raiseEvnet("\none\n\ntwo\n\n");
イベント (Msg :performative __EVENT :content ("" one "" two ""))
となるが、このとき空行となる部分は""という文字列となる。
(空行)
one
(空行)
two
(空行)
各行がそのまま文字列となる。
以下で述べるリストやOAVデータへの変換は行わない。
呼出 agent.raiseEvnet("one 1\n(two :num 2)\n");
イベント (Msg :performative __EVENT :content ("one 1" "(two :num 2)"))
"one"という文字列を要素に持つリスト。
呼出 agent.raiseEvnet("one");
イベント (Msg :performative __EVENT :content (one))
"one", "two", "three"という文字列を要素に持つリスト。
呼出 agent.raiseEvnet("one two three")
イベント (Msg :performative __EVENT :content (one two threee))
オブジェクト = "object", 属性:attr1 = "v1", 属性:attr2 = "v2"というOAVデータ。
呼出 agent.raiseEvnet("obj :attr1 v1 :attr2 v2")
イベント (Msg :performative __EVENT :content (obj :attr1 v1 :attr2 v2))
属性が「:oav」や「:list」でなくても(期待どおり)渡すことができる。
呼出 agent.raiseEvnet("obj :oav (o :p q) :list (1 2 3))")
イベント (Msg :performative __EVENT
:content (obj :oav (o :p q) :list (1 2 3)))
"one two three"という文字列を要素に持つリスト。
""で囲むと、リストやOAVデータへの変換を抑制できる。
呼出 agent.raiseEvnet("\"one two three\"")
イベント (Msg :performative __EVENT :content (one two threee))