import java.util.; import java.awt.flowlayout; import java.awt.gridlayout; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.io.; import javax.swing.japplet; import javax.swing.jbutton; import javax.swing.jlabel; import javax.swing.jlist; import javax.swing.joptionpane; import javax.swing.jpanel; import javax.swing.jscrollpane; import javax.swing.jtextarea; / RuleBaseSystem / public class RuleBaseSystem extends JApplet implements ActionListener { static RuleBase rb; JPanel p1 = new JPanel(); JPanel p2 = new JPanel(); String[] s = { "my-car is inexpensive", "my-car is expensive", "my-car is small", "my-car is big", "my-car needs a lot of gas", "my-car is a hybrid car", "my-car has Toyota's logo", "my-car has Honda's logo", "my-car is a popular car", "my-car has a VTEC engine", "my-car has a big engine", "my-car has several seats", "my-car has only 2 seats", "my-car is a wagon", "my-car is a sports car", "my-car has several color models", "my-car is red", "my-car is stylish", "my-car is a good face", "my-car has an aluminium body" ; JLabel la = new JLabel(" ルールベースシステム "); JList li = new JList(s); JButton b = new JButton(" "); JTextArea ta = new JTextArea(); JScrollPane sp1 = new JScrollPane(li); JScrollPane sp2 = new JScrollPane(ta); int width = 600;
int top = 30; int bottom = 250; public static void main(string args[]) { rb = new RuleBase(); rb.forwardchain(); public void init() { setlayout(null); setsize(width, top + bottom); p1.setlayout(new FlowLayout()); p1.add(la); p1.setbounds(0, 0, width, top); p2.setlayout(new GridLayout(1, 3)); p2.add(sp1); b.addactionlistener(this); p2.add(b); p2.add(sp2); p2.setbounds(0, top, width, bottom); add(p1); add(p2); @Override public void actionperformed(actionevent arg0) { if (li.getselectedindex() == -1) JOptionPane.showMessageDialog(null, " 何も選択されていません "); else { rb = new RuleBase(li.getSelectedValues()); printresult((rb.forwardchain())); public void printresult(string result) { StringTokenizer st = new StringTokenizer(result, ",[]"); String s = ""; while (st.hasmoretokens()) s += st.nexttoken() + "\n"; ta.settext(s);
/ ワーキングメモリを表すクラス. / class WorkingMemory { ArrayList<String> assertions; WorkingMemory() { assertions = new ArrayList<String>(); / マッチするアサーションに対するバインディング情報を返す ( 再帰的 ) @param 前件を示す ArrayList @return バインディング情報が入っている ArrayList / public ArrayList<HashMap<String, String>> matchingassertions( ArrayList<String> theantecedents) { // 複数の変数の束縛を保存する ArrayList<HashMap<String, String>> bindings = new ArrayList<HashMap<String, String>>(); return matchable(theantecedents, 0, bindings); private ArrayList<HashMap<String, String>> matchable( ArrayList<String> theantecedents, int n, ArrayList<HashMap<String, String>> bindings) { // 全ての前件に対してチェックが終わったら if (n == theantecedents.size()) { return bindings; // 1 回目 else if (n == 0) { boolean success = false;
for (int i = 0; i < assertions.size(); i++) { // 変数の束縛を保存するハッシュマップ HashMap<String, String> binding = new HashMap<String, String>(); if ((new Matcher()).matching(theAntecedents.get(n), assertions.get(i), binding)) { bindings.add(binding); success = true; if (success) { return matchable(theantecedents, n + 1, bindings); else { return null; else {//add your source code by using ArrayList and HashMap boolean success = false; ArrayList<HashMap<String, String>> newbindings = new ArrayList<HashMap<String, String>>(); for (int i = 0; i < bindings.size(); i++) { for (int j = 0; j < assertions.size(); j++) { if ((new Matcher()).matching(theAntecedents.get(n), assertions.get(j), bindings.get(i))) { newbindings.add(bindings.get(i)); success = true; if (success) { return matchable(theantecedents, n + 1, newbindings); else { return null;
/ アサーションをワーキングメモリに加える. @param アサーションを表す String / public void addassertion(string theassertion) { System.out.println("ADD:" + theassertion); assertions.add(theassertion); / 指定されたアサーションがすでに含まれているかどうかを調べる. @param アサーションを表す String @return 含まれていれば true, 含まれていなければ false / public boolean contains(string theassertion) { return assertions.contains(theassertion); / ワーキングメモリの情報をストリングとして返す. @return ワーキングメモリの情報を表す String / public String tostring() { return assertions.tostring(); / ルールベースを表すクラス. / class RuleBase { String filename;
FileReader f; StreamTokenizer st; WorkingMemory wm; ArrayList<Rule> rules; RuleBase() { // ファイルのパス filename = "src/reasoning/carshop.data"; // ワーキングメモリーの生成 wm = new WorkingMemory(); wm.addassertion("my-car is inexpensive"); wm.addassertion("my-car has a VTEC engine"); wm.addassertion("my-car is stylish"); wm.addassertion("my-car has several color models"); wm.addassertion("my-car has several seats"); wm.addassertion("my-car is a wagon"); rules = new ArrayList<Rule>(); loadrules(filename); / コンストラクタ @param assertion リストで選ばれた状態の一覧 / public RuleBase(Object[] assertion) { // ファイルのパス filename = "reasoning/carshop.data"; // ワーキングメモリーの生成 wm = new WorkingMemory(); for (int i = 0; i < assertion.length; i++) // String 型に直して追加 wm.addassertion(string.valueof(assertion[i])); rules = new ArrayList<Rule>(); // ルールの読み込み loadrules(filename); /
前向き推論を行うためのメソッド / public String forwardchain() { boolean newassertioncreated; // 新しいアサーションが生成されなくなるまで続ける. do { newassertioncreated = false; //add your source code by using ArrayList and HaspMap for (int i = 0; i < rules.size(); i++) { Rule arule = rules.get(i); System.out.println("apply rule:" + arule.getname()); ArrayList<String> antecedents = arule.getantecedents(); String consequent = arule.getconsequent(); ArrayList<HashMap<String, String>> bindings = wm.matchingassertions(antecedents); if (bindings!= null) { for (int j = 0; j < bindings.size(); j++) { // 後件をインスタンシエーション String newassertion = instantiate((string) consequent, bindings.get(j)); // ワーキングメモリーになければ成功 if (!wm.contains(newassertion)) { System.out.println("Success: " + newassertion); wm.addassertion(newassertion); newassertioncreated = true; System.out.println("Working Memory" + wm); while (newassertioncreated); System.out.println("No rule produces a new assertion"); return wm.tostring(); private String instantiate(string thepattern, HashMap thebindings) { String result = new String(); StringTokenizer st = new StringTokenizer(thePattern); for (int i = 0; i < st.counttokens();) {
String tmp = st.nexttoken(); if (var(tmp)) { result = result + " " + (String) thebindings.get(tmp); else { result = result + " " + tmp; return result.trim(); private boolean var(string str1) { // 先頭が? なら変数 return str1.startswith("?"); / ルールを読み込むメソッド @param thefilename ファイルの名前 / private void loadrules(string thefilename) { String line; try { int token; f = new FileReader(theFileName); st = new StreamTokenizer(f); // ファイルを読み終わるまで続ける while ((token = st.nexttoken())!= StreamTokenizer.TT_EOF) { // 読み込んだものによって処理を変える switch (token) { // 文字 case StreamTokenizer.TT_WORD: // 各変数の初期化 String name = null; ArrayList<String> antecedents = null; String consequent = null; // 読み込んだ部分が "rule" のとき if ("rule".equals(st.sval)) { // 次に進める
st.nexttoken(); // ルールの名前を name に保存 name = st.sval; // 次に進める st.nexttoken(); // 読み込んだ部分が "if" のとき if ("if".equals(st.sval)) { antecedents = new ArrayList<String>(); st.nexttoken(); // 前件は複数ある場合があるので "then" と一致する まで保存する while (!"then".equals(st.sval)) { antecedents.add(st.sval); st.nexttoken(); // 同じように後件の保存 if ("then".equals(st.sval)) { st.nexttoken(); consequent = st.sval; // ルールの生成 rules.add(new Rule(name, antecedents, consequent)); break; // 文字以外 ( 数字とか改行とか ) default: System.out.println(" エラー?" + token); break; catch (Exception e) { System.out.println(e); // ルールの表示 for (int i = 0; i < rules.size(); i++) { System.out.println(rules.get(i).toString());
/ ルールを表すクラス. / class Rule { // 名前 String name; // 前件 ArrayList<String> antecedents; // 後件 String consequent; // コンストラクタ Rule(String thename, ArrayList<String> theantecedents, String theconsequent) { this.name = thename; this.antecedents = theantecedents; this.consequent = theconsequent; / ルールの名前を返す. @return 名前を表す String / public String getname() { return name; / ルールを String 形式で返す @return ルールを整形した String / public String tostring() { return name + " " + antecedents.tostring() + "->" + consequent; / ルールの前件を返す. @return 前件を表す ArrayList
/ public ArrayList<String> getantecedents() { return antecedents; / ルールの後件を返す. @return 後件を表す String / public String getconsequent() { return consequent; class Matcher { StringTokenizer st1; StringTokenizer st2; HashMap<String, String> vars; Matcher() { vars = new HashMap<String, String>(); public boolean matching(string string1, String string2, HashMap<String, String> bindings) { this.vars = bindings; return matching(string1, string2); public boolean matching(string string1, String string2) { // 同じなら成功 if (string1.equals(string2)) return true; // 各々トークンに分ける st1 = new StringTokenizer(string1); st2 = new StringTokenizer(string2); // 数が異なったら失敗
if (st1.counttokens()!= st2.counttokens()) return false; // 定数同士 for (int i = 0; i < st1.counttokens();) { if (!tokenmatching(st1.nexttoken(), st2.nexttoken())) { // トークンが一つでもマッチングに失敗したら失敗 return false; // 最後まで O.K. なら成功 return true; boolean tokenmatching(string token1, String token2) { if (token1.equals(token2)) return true; if (var(token1) &&!var(token2)) return varmatching(token1, token2); if (!var(token1) && var(token2)) return varmatching(token2, token1); return false; boolean varmatching(string vartoken, String token) { if (vars.containskey(vartoken)) { if (token.equals(vars.get(vartoken))) { return true; else { return false; else { vars.put(vartoken, token); return true; boolean var(string str1) { // 先頭が? なら変数
return str1.startswith("?");