Hi,
I think there's not much you can do here. The complexity of the test
you created is extremely exponential, both in time and in space. Here
are the results I get from using another rule engine:
(nb Triples in query, nb Triples in result, execution time in msec)
(2, 3, 0)
(5, 39, 0)
(10, 9901, 46)
(11, 33615, 156)
(12, 116115, 578)
(13, 406627, 2380)
(14, ?, ?)
Here the point at which the memory just can't hold all the objects
needed comes at 14, the same will happen to Drools at some point. Or
maybe with Drools the first problem encountered will be the time
complexity. At some point one of them just has to become to bad for a
system to be of any practical use, but that's the case with all
exponential problems. I doubt any rule engine will hold its own longer
then, say, 20 with this test!
Greets,
Pé
Andreas Andreakis wrote:
Hallo,
In order to test the Reasoning performance of the rule engine, I wrote
a small performance test.
Using a Triple BeanClass, containing Resource-Property-Object
attributes all of them as String, I defined a rule which does the
following:
(X, link, Y) and (Y, link, Z) -> (X, link, Z)
Now I create a specific count of Triples (here 2), which are lineary
connected:
(Triple1, link, Triple2)
(Triple2, link, Triple3)
the result I get when I fire the rule and read the Objects is as
expected:
(Triple1, link, Triple2)
(Triple2, link, Triple3)
(Triple1, link, Triple3) //<---- new Fact, inferenced one
But currently, the performance is very poor.
If I set 8 Triples (lineryy connected one after another) it takes: 484
ms
9 Triples need: 2156 ms
10 Triples need: 20828 ms (!)
see the attachments for the rules file (rule.xml), the Triple Class and
the Main class.
Is there a way to tune the process ? I doing something wrong ?
thanx in advance,
Andreas
package transitivity2;
public class Triple {
private String resource;
private String property;
private String object;
public String getObject() {
return this.object;
}
public void setObject(String object) {
this.object = object;
}
public String getProperty() {
return this.property;
}
public void setProperty(String property) {
this.property = property;
}
public String getResource() {
return this.resource;
}
public void setResource(String resource) {
this.resource = resource;
}
public String toString() {
return "<" + resource + "> <" + property + "> <" + object + ">";
}
}
<rule-set name="cheese rules" 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">
<import>java.lang.String</import>
<import>transitivity2.Triple</import>
<rule name="Generic TransLink Rule">
<parameter identifier="X">
<class>transitivity2.Triple</class>
</parameter>
<parameter identifier="Y">
<class>transitivity2.Triple</class>
</parameter>
<parameter identifier="linkName">
<class>java.lang.String</class>
</parameter>
<java:condition>Y.getResource().equals(X.getObject())</java:condition>
<java:consequence>
Triple newTriple = new Triple();
newTriple.setResource(X.getResource());
newTriple.setProperty(linkName);
newTriple.setObject(Y.getObject());
drools.assertObject(newTriple);
</java:consequence>
</rule>
</rule-set>
package transitivity2;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.drools.FactHandle;
import org.drools.RuleBase;
import org.drools.WorkingMemory;
import org.drools.io.RuleBaseLoader;
public class Main {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
RuleBase base = RuleBaseLoader.loadFromInputStream(Triple.class
.getResourceAsStream("rules.xml"));
WorkingMemory memory = base.newWorkingMemory();
//set here the linkName
String linkName = "subClassOf";
//set here the list depth
int triplesCount = 9;
List<Triple> tripleList = new ArrayList<Triple>();
for (int i = 1; i <=triplesCount; i++) {
Triple t = new Triple();
t.setResource(String.valueOf(i-1));
t.setProperty(linkName);
t.setObject(String.valueOf(i));
tripleList.add(t);
}
// hold time
long time = System.currentTimeMillis();
//assert all Triples into WorkingMemory
for (Triple t : tripleList) {
FactHandle handle = memory.assertObject(t);
}
memory.assertObject(linkName);
memory.fireAllRules();
//Display calculation time:
System.out.println("Trans-calculation: "+(System.currentTimeMillis()-time)+" ms");
//Display all Triples. Old + new infered (over transitivity)
List objects = memory.getObjects(Triple.class);
for (Object object : objects) {
Triple currentTriple = (Triple)object;
System.out.println(currentTriple);
}
}//end main
}//end class
|