1 10 package com.hp.hpl.jena.reasoner.rulesys.impl; 11 12 import com.hp.hpl.jena.reasoner.*; 13 import com.hp.hpl.jena.reasoner.rulesys.*; 14 import com.hp.hpl.jena.graph.*; 15 import java.util.*; 16 17 import com.hp.hpl.jena.util.OneToManyMap; 18 import com.hp.hpl.jena.util.PrintUtil; 19 import com.hp.hpl.jena.util.iterator.ConcatenatedIterator; 20 21 import org.apache.commons.logging.Log; 22 import org.apache.commons.logging.LogFactory; 23 24 31 public class RETEEngine implements FRuleEngineI { 32 33 34 protected ForwardRuleInfGraphI infGraph; 35 36 37 protected List rules; 38 39 40 protected OneToManyMap clauseIndex; 41 42 43 protected List addsPending = new ArrayList(); 44 45 46 protected List deletesPending = new ArrayList(); 47 48 49 protected HashSet predicatesUsed; 50 51 52 protected boolean wildcardRule; 53 54 55 protected boolean recordDerivations; 56 57 58 long nRulesFired = 0; 59 60 61 boolean processedAxioms = false; 62 63 protected static Log logger = LogFactory.getLog(FRuleEngine.class); 64 65 68 74 public RETEEngine(ForwardRuleInfGraphI parent, List rules) { 75 infGraph = parent; 76 this.rules = rules; 77 } 78 79 85 public RETEEngine(ForwardRuleInfGraphI parent) { 86 infGraph = parent; 87 } 88 89 92 100 public void init(boolean ignoreBrules, Finder inserts) { 101 compile(rules, ignoreBrules); 102 findAndProcessAxioms(); 103 fastInit(inserts); 104 } 105 106 112 public void fastInit(Finder inserts) { 113 findAndProcessActions(); 114 if (infGraph.getRawGraph() != null) { 115 if (wildcardRule) { 117 for (Iterator i = inserts.find(new TriplePattern(null, null, null)); i.hasNext(); ) { 118 addTriple((Triple)i.next(), false); 119 } 120 } else { 121 for (Iterator p = predicatesUsed.iterator(); p.hasNext(); ) { 122 Node predicate = (Node)p.next(); 123 for (Iterator i = inserts.find(new TriplePattern(null, predicate, null)); i.hasNext(); ) { 124 addTriple((Triple)i.next(), false); 125 } 126 } 127 } 128 } 129 runAll(); 131 } 132 133 137 public synchronized void add(Triple t) { 138 addTriple(t, false); 139 runAll(); 140 } 141 142 147 public synchronized boolean delete(Triple t) { 148 deleteTriple(t, false); 149 runAll(); 150 return true; 151 } 152 153 157 public long getNRulesFired() { 158 return nRulesFired; 159 } 160 161 165 public boolean shouldTrace() { 166 return true; 167 } 169 170 173 public void setDerivationLogging(boolean recordDerivations) { 174 this.recordDerivations = recordDerivations; 175 } 176 177 181 public Object getRuleStore() { 182 return new RuleStore(clauseIndex, predicatesUsed, wildcardRule); 183 } 184 185 188 public void setRuleStore(Object ruleStore) { 189 RuleStore rs = (RuleStore)ruleStore; 190 predicatesUsed = rs.predicatesUsed; 191 wildcardRule = rs.wildcardRule; 192 193 RETERuleContext context = new RETERuleContext(infGraph, this); 195 Map netCopy = new HashMap(); 196 clauseIndex = new OneToManyMap(); 197 for (Iterator i = rs.clauseIndex.entrySet().iterator(); i.hasNext(); ) { 198 Map.Entry entry = (Map.Entry)i.next(); 199 clauseIndex.put(entry.getKey(), ((RETENode)entry.getValue()).clone(netCopy, context)); 200 } 201 } 202 203 206 211 public void compile(List rules, boolean ignoreBrules) { 212 clauseIndex = new OneToManyMap(); 213 predicatesUsed = new HashSet(); 214 wildcardRule = false; 215 216 for (Iterator it = rules.iterator(); it.hasNext(); ) { 217 Rule rule = (Rule)it.next(); 218 if (ignoreBrules && rule.isBackward()) continue; 219 220 int numVars = rule.getNumVars(); 221 boolean[] seenVar = new boolean[numVars]; 222 RETESourceNode prior = null; 223 224 for (int i = 0; i < rule.bodyLength(); i++) { 225 Object clause = rule.getBodyElement(i); 226 if (clause instanceof TriplePattern) { 227 ArrayList clauseVars = new ArrayList(numVars); 229 RETEClauseFilter clauseNode = RETEClauseFilter.compile((TriplePattern)clause, numVars, clauseVars); 230 Node predicate = ((TriplePattern)clause).getPredicate(); 231 if (predicate.isVariable()) { 232 clauseIndex.put(Node.ANY, clauseNode); 233 wildcardRule = true; 234 } else { 235 clauseIndex.put(predicate, clauseNode); 236 if (! wildcardRule) { 237 predicatesUsed.add(predicate); 238 } 239 } 240 241 ArrayList matchIndices = new ArrayList(numVars); 243 for (Iterator iv = clauseVars.iterator(); iv.hasNext(); ) { 244 int varIndex = ((Node_RuleVariable)iv.next()).getIndex(); 245 if (seenVar[varIndex]) matchIndices.add(new Byte ((byte)varIndex)); 246 seenVar[varIndex] = true; 247 } 248 249 if (prior == null) { 251 prior = clauseNode; 253 } else { 254 RETEQueue leftQ = new RETEQueue(matchIndices); 255 RETEQueue rightQ = new RETEQueue(matchIndices); 256 leftQ.setSibling(rightQ); 257 rightQ.setSibling(leftQ); 258 clauseNode.setContinuation(rightQ); 259 prior.setContinuation(leftQ); 260 prior = leftQ; 261 } 262 } 263 } 264 265 if (prior != null) { 267 RETETerminal term = new RETETerminal(rule, this, infGraph); 268 prior.setContinuation(term); 269 } 270 271 } 272 273 if (wildcardRule) predicatesUsed = null; 274 } 275 276 279 285 public synchronized void addTriple(Triple triple, boolean deduction) { 286 if (infGraph.shouldTrace()) { 287 logger.debug("Add triple: " + PrintUtil.print(triple)); 288 } 289 if (deletesPending.size() > 0) deletesPending.remove(triple); 290 addsPending.add(triple); 291 if (deduction) { 292 infGraph.addDeduction(triple); 293 } 294 } 295 296 301 public synchronized void deleteTriple(Triple triple, boolean deduction) { 302 addsPending.remove(triple); 303 deletesPending.add(triple); 304 if (deduction) { 305 infGraph.getCurrentDeductionsGraph().delete(triple); 306 Graph raw = infGraph.getRawGraph(); 307 if (raw.contains(triple)) { 310 deletesPending.remove(triple); 313 } 314 } 315 } 316 317 321 protected void incRuleCount() { 322 nRulesFired++; 323 } 324 325 329 protected synchronized Triple nextAddTriple() { 330 int size = addsPending.size(); 331 if (size > 0) { 332 return (Triple)addsPending.remove(size - 1); 333 } 334 return null; 335 } 336 337 341 protected synchronized Triple nextDeleteTriple() { 342 int size = deletesPending.size(); 343 if (size > 0) { 344 return (Triple)deletesPending.remove(size - 1); 345 } 346 return null; 347 } 348 349 353 public void runAll() { 354 while(true) { 355 boolean isAdd = false; 356 Triple next = nextDeleteTriple(); 357 if (next == null) { 358 next = nextAddTriple(); 359 if (next == null) return; isAdd = true; 361 } 362 if (infGraph.shouldTrace()) { 363 logger.debug((isAdd ? "Inserting" : "Deleting") + " triple: " + PrintUtil.print(next)); 364 } 365 Iterator i1 = clauseIndex.getAll(next.getPredicate()); 366 Iterator i2 = clauseIndex.getAll(Node.ANY); 367 Iterator i = new ConcatenatedIterator(i1, i2); 368 while (i.hasNext()) { 369 RETEClauseFilter cf = (RETEClauseFilter) i.next(); 370 cf.fire(next, isAdd); 372 } 373 } 374 } 375 376 377 382 public void testTripleInsert(Triple t) { 383 Iterator i1 = clauseIndex.getAll(t.getPredicate()); 384 Iterator i2 = clauseIndex.getAll(Node.ANY); 385 Iterator i = new ConcatenatedIterator(i1, i2); 386 while (i.hasNext()) { 387 RETEClauseFilter cf = (RETEClauseFilter) i.next(); 388 cf.fire(t, true); 389 } 390 } 391 392 395 protected void findAndProcessAxioms() { 396 for (Iterator i = rules.iterator(); i.hasNext(); ) { 397 Rule r = (Rule)i.next(); 398 if (r.bodyLength() == 0) { 399 for (int j = 0; j < r.headLength(); j++) { 401 Object head = r.getHeadElement(j); 402 if (head instanceof TriplePattern) { 403 TriplePattern h = (TriplePattern) head; 404 Triple t = new Triple(h.getSubject(), h.getPredicate(), h.getObject()); 405 addTriple(t, true); 406 } 407 } 408 } 409 } 410 processedAxioms = true; 411 } 412 413 416 protected void findAndProcessActions() { 417 RuleContext tempContext = new RETERuleContext(infGraph, this); 418 for (Iterator i = rules.iterator(); i.hasNext(); ) { 419 Rule r = (Rule)i.next(); 420 if (r.bodyLength() == 0) { 421 for (int j = 0; j < r.headLength(); j++) { 423 Object head = r.getHeadElement(j); 424 if (head instanceof Functor) { 425 Functor f = (Functor)head; 426 Builtin imp = f.getImplementor(); 427 if (imp != null) { 428 tempContext.setRule(r); 429 imp.headAction(f.getArgs(), f.getArgLength(), tempContext); 430 } else { 431 throw new ReasonerException("Invoking undefined Functor " + f.getName() +" in " + r.toShortString()); 432 } 433 } 434 } 435 } 436 } 437 } 438 439 442 447 protected static class ClausePointer { 448 449 450 protected Rule rule; 451 452 453 protected int index; 454 455 456 ClausePointer(Rule rule, int index) { 457 this.rule = rule; 458 this.index = index; 459 } 460 461 462 TriplePattern getClause() { 463 return (TriplePattern)rule.getBodyElement(index); 464 } 465 } 466 467 470 public static class RuleStore { 471 472 473 protected OneToManyMap clauseIndex; 474 475 476 protected HashSet predicatesUsed; 477 478 479 protected boolean wildcardRule; 480 481 482 RuleStore(OneToManyMap clauseIndex, HashSet predicatesUsed, boolean wildcardRule) { 483 this.clauseIndex = clauseIndex; 484 this.predicatesUsed = predicatesUsed; 485 this.wildcardRule = wildcardRule; 486 } 487 } 488 489 } 490 491 492 | Popular Tags |