題記
世界是事實的總體,而不是事物的總體。
世界為諸事實所規定,為它們既是全部事實所規定。
——路德維?!ぞS特根斯坦,《邏輯哲學論》
The answer, please?
"請回答我..."
The stern voice startles you.
一個嚴厲的聲音把你嚇個半死.
You were dozing in Mrs. Rosencrantz's high school math class again. You realize at once that she's been talking to you.
你又在Mrs. Rosencrantz的數學課堂上和周公聊天了. 你立刻意識到, 她是在和你說話.
Well? You look at the blackboard. It's one of those word puzzles, the logic kind. Mrs.
什么? 你看看黑板, 原來是那些無聊的邏輯類填字題目.
Rosencrantz is waiting for you to solve it. You quickly scan what she's scrawled on the board with her crone's hand:
Rosencrantz女士正等著你的答案. 你飛快的掃描了一遍她用她那又老又丑的手在黑板上的涂鴉:
1. A foursome of golfers is standing at a tee, in a line from left to right. Each
golfer wears different colored pants; one is wearing red pants. The golfer to
Fred's immediate right is wearing blue pants.
1. 四個高爾夫選手從右向左排成一排, 站在樹下. 每個選手穿著不通顏色的褲子.其中一個穿黑色. 在Fred右邊的一個選手穿藍色.
2.Joe is second in line.
2.Joe在隊列中排第二.
3.Bob is wearing plaid pants.
3.Bob穿著彩色格呢的褲子.
4.Tom isn't in position one or four, and he isn't wearing the hideous orange
pants.
4.Tom不在第一或者第四, 他沒有穿那種讓人惡心的桔黃色褲子.
In what order will the four golfers tee off, and what color are each golfer's
pants?
那么, 問題是, 這四個人在隊列中的順序是什么? 他們各自穿什么顏色的褲子?
問題出來, 可能你唯一能想到的就是拿出一張紙, 一支筆, 坐下來, 仔仔細細的把邏輯理清楚.
你會說: "這種問題簡直是小case....".
OK, 那你聽說過愛因斯坦的難題吧(Deep同志貼出來過)?
這下, 除非你有超強的推理能力以外, 你還能做出來(你肯定知道,Google可以回答
)?
仔細看看題目.
我們知道, 總共有四個人, 這是Facts
除了這些事實, 我們還有一堆的"if then" 樣式的規則(Rule), 這一系列的規則成為我們的知識庫(KB).
當然我們自己不會把這些東西在腦子里做推理的. 我們還需要一個推理機.
這就是Drools可以做的事情.
簡單回顧一下:
首先有一個應用的規則集,包含很多規則。
推理引擎用規則左邊的模式去匹配facts列表中的fact
如果有匹配成功的話,這條規則就被激活,放到議程(已激活的規則集合)中去。
最后所有的規則都匹配完成后,規則引擎就開始觸發這些規則
規則引擎根據規則左邊的匹配執行右邊的動作,這些動作執行的過程中規則引擎會根據優先級
和一定的算法根絕左邊匹配的事實放入到右邊的上下文中。
也就是指針對匹配的事實執行右部的動作。
OK. 我們來讓Drools干活.
有一點比較繞的是, 按照OO的思想, 我們可能搞出來不少的對象(人, 褲子, 顏色....). 這里我們只需要簡化一下.
先來個顏色的類...
public class PantsColor {
public String of = null; // A person's name
public String is = null; // A pants color.
public PantsColor(String of, String is) {
this.of = of;
this.is = is;
}
}
我們還需要一個表示順序的Position類:
public class Position {
public String of = null; // A person's name
public int is = 0; // A position (from left to right: 1, 2, 3, 4)
public Position(String of, int is) {
this.of = of;
this.is = is;
}
}
現在看看, 是不是比抽象出來N個對象更加簡便了? 其實這兩個才是我們真正想要得到的東西.
我們需要把手上一堆的規則描述出來, 讓Drools認識這些東西.
這是一個規則描述文件, 我會用不正確的注釋格式在里面作出說明.
xml version="1.0"?>
<rule-set name="golfer"
xmlns="http://drools.org/rules"
xmlns:java="http://drools.org/semantics/java"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://drools.org/rules rules.xsd
http://drools.org/semantics/java java.xsd">
<java:import>com.zyyang.golfer.PantsColorjava:import> //讓引擎知道這兩個類的位置.
<java:import>com.zyyang.golfer.Positionjava:import>
<rule name="find-solution"> //規則名, 唯一的ID
//根據題目中描述的, 我們一口氣聲明出5對...(P和C是他們中的任意兩個)
Unknown golfer's position and pants color -->
<parameter identifier="p"><class>Positionclass>parameter>
<parameter identifier="c"><class>PantsColorclass>parameter>
Fred's position and pants color -->
<parameter identifier="p1"><class>Positionclass>parameter>
<parameter identifier="c1"><class>PantsColorclass>parameter>
Joe's position and pants color -->
<parameter identifier="p2"><class>Positionclass>parameter>
<parameter identifier="c2"><class>PantsColorclass>parameter>
Bob's position and pants color -->
<parameter identifier="p3"><class>Positionclass>parameter>
<parameter identifier="c3"><class>PantsColorclass>parameter>
Tom's position and pants color -->
<parameter identifier="p4"><class>Positionclass>parameter>
<parameter identifier="c4"><class>PantsColorclass>parameter>
Ensure each position is unique -->
<java:condition>p1.is != p2.isjava:condition>
<java:condition>p1.is != p3.isjava:condition>
<java:condition>p1.is != p4.isjava:condition>
<java:condition>p2.is != p3.isjava:condition>
<java:condition>p2.is != p4.isjava:condition>
<java:condition>p3.is != p4.isjava:condition>
Ensure each pants color is unique -->
<java:condition>!c1.is.equals(c2.is)java:condition>
<java:condition>!c1.is.equals(c3.is)java:condition>
<java:condition>!c1.is.equals(c4.is)java:condition>
<java:condition>!c2.is.equals(c3.is)java:condition>
<java:condition>!c2.is.equals(c4.is)java:condition>
<java:condition>!c3.is.equals(c4.is)java:condition>
Ensure the unknown golfer's position and pants color
matches one of the known golfers -->
<java:condition>
((p == p1) || (p == p2) || (p == p3) || (p == p4))
java:condition>
<java:condition>
((c == c1) || (c == c2) || (c == c3) || (c == c4))
java:condition>
Unknown golfer -->
<java:condition>p.of.equals(c.of)java:condition>
The golfer to Fred's immediate right is wearing blue pants. -->
<java:condition>"Fred".equals(p1.of)java:condition>
<java:condition>"Fred".equals(c1.of)java:condition>
<java:condition>p1.is + 1 == p.isjava:condition>
<java:condition>"blue".equals(c.is)java:condition>
Joe is second in line. -->
<java:condition>"Joe".equals(p2.of)java:condition>
<java:condition>"Joe".equals(c2.of)java:condition>
<java:condition>2 == p2.isjava:condition>
Bob is wearing plaid pants. -->
<java:condition>"Bob".equals(p3.of)java:condition>
<java:condition>"Bob".equals(c3.of)java:condition>
<java:condition>"plaid".equals(c3.is)java:condition>
Tom isn't in positions one or four,
and he isn't wearing the orange pants. -->
<java:condition>"Tom".equals(p4.of)java:condition>
<java:condition>"Tom".equals(c4.of)java:condition>
<java:condition>1 != p4.isjava:condition>
<java:condition>4 != p4.isjava:condition>
<java:condition>!"orange".equals(c4.is)java:condition>
Print out the solution. -->
<java:consequence> //打印出來咯.
System.out.println("Fred " + p1.is + " " + c1.is);
System.out.println("Joe " + p2.is + " " + c2.is);
System.out.println("Bob " + p3.is + " " + c3.is);
System.out.println("Tom " + p4.is + " " + c4.is);
java:consequence>
rule>
rule-set>
好, 規則也描述出來了, 下面讓Drools干活.
/**
* @param args
* @throws IOException
* @throws SAXException
* @throws IntegrationException
* @throws FactException
*/
public static void main(String[] args) throws IntegrationException, SAXException, IOException, FactException {
URL url = GolfersExample.class.getResource("golf.drl"); //規則文件的URL
RuleBase ruleBase = RuleBaseLoader.loadFromUrl(url); //把規則讀出.
WorkingMemory workingMemory = ruleBase.newWorkingMemory(); //這就是一個推理的地方.
String[] names = new String[] { "Fred", "Joe", "Bob", "Tom" }; //四個人...
String[] pantsColors = new String[] { "red", "blue", "plaid", "orange" }; //四種顏色.
int[] positions = new int[] { 1, 2, 3, 4 }; //位置的代號.
//一個一個的assert到workingmemoruy中.
for (int i = 0; i < names.length; i++) {
for (int j = 0; j < pantsColors.length; j++){
workingMemory.assertObject(new PantsColor(names[i], pantsColors[j]));
}
for (int j = 0; j < positions.length; j++) {
workingMemory.assertObject(new Position(names[i], positions[j]));
}
}
workingMemory.fireAllRules(); //激活.
}
由于Drools是Forword方式的, 它以事件向外部提供結果.
結果為:
Fred 1 orange
Joe 2 blue
Bob 4 plaid
Tom 3 red
現在你應該知道怎么去解決愛因斯坦的題目了.
無非就是多幾個對象, 多幾個規則而已嘛.