1 10 package com.hp.hpl.jena.reasoner.rulesys.impl; 11 12 import com.hp.hpl.jena.graph.*; 13 import com.hp.hpl.jena.reasoner.*; 14 import com.hp.hpl.jena.reasoner.rulesys.*; 15 import com.hp.hpl.jena.util.PrintUtil; 16 17 import java.util.*; 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 20 21 29 public class LPInterpreter { 30 31 34 35 protected LPBRuleEngine engine; 36 37 38 protected LPInterpreterContext iContext; 39 40 41 protected boolean isComplete = false; 42 43 44 protected Node[] tVars = new Node[RuleClauseCode.MAX_TEMPORARY_VARS]; 45 46 47 protected Node[] argVars = new Node[RuleClauseCode.MAX_ARGUMENT_VARS]; 48 49 50 protected Node[] pVars = null; 51 52 53 protected EnvironmentFrame envFrame; 54 55 56 protected FrameObject cpFrame; 57 58 59 protected ArrayList trail = new ArrayList(); 60 61 62 protected RuleContext context; 63 64 65 protected TopLevelTripleMatchFrame topTMFrame; 66 67 68 protected TriplePattern goal; 69 70 static Log logger = LogFactory.getLog(LPInterpreter.class); 71 72 75 80 public LPInterpreter(LPBRuleEngine engine, TriplePattern goal) { 81 this(engine, goal, engine.getRuleStore().codeFor(goal), true); 82 } 83 84 85 92 public LPInterpreter(LPBRuleEngine engine, TriplePattern goal, boolean isTop) { 93 this(engine, goal, engine.getRuleStore().codeFor(goal), isTop); 94 } 95 96 104 public LPInterpreter(LPBRuleEngine engine, TriplePattern goal, List clauses, boolean isTop) { 105 this.engine = engine; 106 this.goal = goal; 108 if (engine.getDerivationLogging()) { 110 envFrame = new EnvironmentFrameWithDerivation(RuleClauseCode.returnCodeBlock); 111 } else { 112 envFrame = new EnvironmentFrame(RuleClauseCode.returnCodeBlock); 113 } 114 envFrame.allocate(RuleClauseCode.MAX_PERMANENT_VARS); 115 HashMap mappedVars = new HashMap(); 116 envFrame.pVars[0] = argVars[0] = standardize(goal.getSubject(), mappedVars); 117 envFrame.pVars[1] = argVars[1] = standardize(goal.getPredicate(), mappedVars); 118 envFrame.pVars[2] = argVars[2] = standardize(goal.getObject(), mappedVars); 119 if (engine.getDerivationLogging()) { 120 ((EnvironmentFrameWithDerivation)envFrame).initDerivationRecord(argVars); 121 } 122 123 if (clauses != null && clauses.size() > 0) { 124 if (isTop && engine.getRuleStore().isTabled(goal)) { 125 setupTabledCall(0, 0); 126 } else { 128 setupClauseCall(0, 0, clauses); 129 } 130 } 131 132 topTMFrame = new TopLevelTripleMatchFrame(this, goal); 134 topTMFrame.linkTo(cpFrame); 135 topTMFrame.setContinuation(0, 0); 136 cpFrame = topTMFrame; 137 } 138 139 143 public void setTopInterpreter(LPInterpreterContext context) { 144 iContext = context; 145 FrameObject topChoice = topTMFrame.getLink(); 146 if (topChoice instanceof ConsumerChoicePointFrame) { 147 ((ConsumerChoicePointFrame)topChoice).context = context; 148 } 149 } 150 151 154 158 public void close() { 159 synchronized (engine) { 160 isComplete = true; 161 engine.detach(this); 162 if (cpFrame != null) cpFrame.close(); 163 } 164 } 165 166 169 public void setState(LPInterpreterState state) { 170 if (state instanceof ConsumerChoicePointFrame) { 171 restoreState((ConsumerChoicePointFrame) state); 172 } else { 173 iContext = (LPInterpreterContext) state; 174 } 175 } 176 183 public Object next() { 184 boolean traceOn = engine.isTraceOn(); 185 186 StateFlag answer = run(); 188 190 if (answer == StateFlag.FAIL || answer == StateFlag.SUSPEND) { 191 return answer; 192 } else if (answer == StateFlag.SATISFIED) { 193 if (traceOn) logger.info("RETURN: " + topTMFrame.lastMatch); 194 return topTMFrame.lastMatch; 195 } else { 196 Triple t = new Triple(deref(pVars[0]), deref(pVars[1]), derefPossFunctor(pVars[2])); 197 if (traceOn) logger.info("RETURN: " + t); 198 return t; 199 } 200 } 201 202 206 209 public LPBRuleEngine getEngine() { 210 return engine; 211 } 212 213 217 public FrameObject getChoiceFrame() { 218 return cpFrame; 219 } 220 221 225 public LPInterpreterContext getContext() { 226 return iContext; 227 } 228 229 232 240 protected StateFlag run() { 241 int pc = 0; int ac = 0; RuleClauseCode clause = null; ChoicePointFrame choice = null; 245 byte[] code; 246 Object [] args; 247 boolean traceOn = engine.isTraceOn(); 248 boolean recordDerivations = engine.getDerivationLogging(); 249 250 main: while (cpFrame != null) { 251 if (cpFrame instanceof ChoicePointFrame) { 253 choice = (ChoicePointFrame)cpFrame; 254 if (!choice.hasNext()) { 255 cpFrame = choice.getLink(); 257 if (traceOn) logger.info("FAIL in clause " + choice.envFrame.clause + " choices exhausted"); 258 continue main; 259 } 260 261 clause = (RuleClauseCode)choice.nextClause(); 262 if (recordDerivations) { 264 envFrame = new EnvironmentFrameWithDerivation(clause); 265 } else { 266 envFrame = new EnvironmentFrame(clause); 267 } 268 envFrame.linkTo(choice.envFrame); 269 envFrame.cpc = choice.cpc; 270 envFrame.cac = choice.cac; 271 272 System.arraycopy(choice.argVars, 0, argVars, 0, RuleClauseCode.MAX_ARGUMENT_VARS); 274 int trailMark = choice.trailIndex; 275 if (trailMark < trail.size()) { 276 unwindTrail(trailMark); 277 } 278 pc = ac = 0; 279 if (recordDerivations) { 280 ((EnvironmentFrameWithDerivation)envFrame).initDerivationRecord(argVars); 281 } 282 283 if (traceOn) logger.info("ENTER " + clause + " : " + getArgTrace()); 284 285 287 } else if (cpFrame instanceof TripleMatchFrame) { 288 TripleMatchFrame tmFrame = (TripleMatchFrame)cpFrame; 289 290 envFrame = tmFrame.envFrame; 292 clause = envFrame.clause; 293 int trailMark = tmFrame.trailIndex; 294 if (trailMark < trail.size()) { 295 unwindTrail(trailMark); 296 } 297 298 if (!tmFrame.nextMatch(this)) { 300 cpFrame = cpFrame.getLink(); 302 if (traceOn) logger.info("TRIPLE match (" + tmFrame.goal +") -> FAIL"); 303 continue main; 304 } 305 if (traceOn) { 306 logger.info("TRIPLE match (" + tmFrame.goal +") -> " + getArgTrace()); 307 logger.info("RENTER " + clause); 308 } 309 310 pc = tmFrame.cpc; 311 ac = tmFrame.cac; 312 313 if (recordDerivations) { 314 if (envFrame instanceof EnvironmentFrameWithDerivation) { 315 ((EnvironmentFrameWithDerivation)envFrame).noteMatch(tmFrame.goal, pc); 316 } 317 } 318 319 321 } else if (cpFrame instanceof TopLevelTripleMatchFrame) { 322 TopLevelTripleMatchFrame tmFrame = (TopLevelTripleMatchFrame)cpFrame; 323 324 if (!tmFrame.nextMatch(this)) { 326 cpFrame = cpFrame.getLink(); 328 if (traceOn) logger.info("TRIPLE match (" + tmFrame.goal +") -> FAIL"); 329 continue main; 330 } else { 331 if (traceOn) logger.info("TRIPLE match (" + tmFrame.goal +") ->"); 333 return StateFlag.SATISFIED; 334 } 335 336 } else if (cpFrame instanceof ConsumerChoicePointFrame) { 337 ConsumerChoicePointFrame ccp = (ConsumerChoicePointFrame)cpFrame; 338 339 envFrame = ccp.envFrame; 341 clause = envFrame.clause; 342 if (traceOn) logger.info("RESTORE " + clause + ", due to tabled goal " + ccp.generator.goal); 343 int trailMark = ccp.trailIndex; 344 if (trailMark < trail.size()) { 345 unwindTrail(trailMark); 346 } 347 348 StateFlag state = ccp.nextMatch(this); 350 if (state == StateFlag.FAIL) { 351 cpFrame = cpFrame.getLink(); 353 if (traceOn) logger.info("FAIL " + clause); 354 continue main; 355 } else if (state == StateFlag.SUSPEND) { 356 preserveState(ccp); 358 iContext.notifyBlockedOn(ccp); 359 cpFrame = cpFrame.getLink(); 360 if (traceOn)logger.info("SUSPEND " + clause); 361 continue main; 362 } 363 364 pc = ccp.cpc; 365 ac = ccp.cac; 366 367 if (recordDerivations) { 368 if (envFrame instanceof EnvironmentFrameWithDerivation) { 369 ((EnvironmentFrameWithDerivation)envFrame).noteMatch(ccp.goal, pc); 370 } 371 } 372 373 375 } else { 376 throw new ReasonerException("Internal error in backward rule system, unrecognized choice point"); 377 } 378 379 engine.incrementProfile(clause); 380 381 interpreter: while (envFrame != null) { 382 383 pVars = envFrame.pVars; 386 int yi, ai, ti; 387 Node arg, constant; 388 List predicateCode; 389 TripleMatchFrame tmFrame; 390 code = clause.getCode(); 391 args = clause.getArgs(); 392 393 codeloop: while (true) { 394 switch (code[pc++]) { 395 case RuleClauseCode.TEST_BOUND: 396 ai = code[pc++]; 397 if (deref(argVars[ai]).isVariable()) { 398 if (traceOn) logger.info("FAIL " + clause); 399 continue main; 400 } 401 break; 402 403 case RuleClauseCode.TEST_UNBOUND: 404 ai = code[pc++]; 405 if (! deref(argVars[ai]).isVariable()) { 406 if (traceOn) logger.info("FAIL " + clause); 407 continue main; 408 } 409 break; 410 411 case RuleClauseCode.ALLOCATE: 412 int envSize = code[pc++]; 413 envFrame.allocate(envSize); 414 pVars = envFrame.pVars; 415 break; 416 417 case RuleClauseCode.GET_VARIABLE : 418 yi = code[pc++]; 419 ai = code[pc++]; 420 pVars[yi] = argVars[ai]; 421 break; 422 423 case RuleClauseCode.GET_TEMP : 424 ti = code[pc++]; 425 ai = code[pc++]; 426 tVars[ti] = argVars[ai]; 427 break; 428 429 case RuleClauseCode.GET_CONSTANT : 430 ai = code[pc++]; 431 arg = argVars[ai]; 432 if (arg instanceof Node_RuleVariable) arg = ((Node_RuleVariable)arg).deref(); 433 constant = (Node) args[ac++]; 434 if (arg instanceof Node_RuleVariable) { 435 bind(arg, constant); 436 } else { 437 if (!arg.sameValueAs(constant)) { 438 if (traceOn) logger.info("FAIL " + clause); 439 continue main; 440 } 441 } 442 break; 443 444 case RuleClauseCode.GET_FUNCTOR: 445 Functor func = (Functor)args[ac++]; 446 boolean match = false; 447 Node o = argVars[2]; 448 if (o instanceof Node_RuleVariable) o = ((Node_RuleVariable)o).deref(); 449 if (Functor.isFunctor(o)) { 450 Functor funcArg = (Functor)o.getLiteral().getValue(); 451 if (funcArg.getName().equals(func.getName())) { 452 if (funcArg.getArgLength() == func.getArgLength()) { 453 Node[] fargs = funcArg.getArgs(); 454 for (int i = 0; i < fargs.length; i++) { 455 argVars[i+3] = fargs[i]; 456 } 457 match = true; 458 } 459 } 460 } else if (o.isVariable()) { 461 Node[] fargs = new Node[func.getArgLength()]; 463 Node[] templateArgs = func.getArgs(); 464 for (int i = 0; i < fargs.length; i++) { 465 Node template = templateArgs[i]; 466 if (template.isVariable()) template = new Node_RuleVariable(null, i+3); 467 fargs[i] = template; 468 argVars[i+3] = template; 469 } 470 Node newFunc = Functor.makeFunctorNode(func.getName(), fargs); 471 bind(((Node_RuleVariable)o).deref(), newFunc); 472 match = true; 473 } 474 if (!match) { 475 if (traceOn) logger.info("FAIL " + clause); 476 continue main; } 478 break; 479 480 case RuleClauseCode.UNIFY_VARIABLE : 481 yi = code[pc++]; 482 ai = code[pc++]; 483 if (!unify(argVars[ai], pVars[yi])) { 484 if (traceOn) logger.info("FAIL " + clause); 485 continue main; 486 } 487 break; 488 489 case RuleClauseCode.UNIFY_TEMP : 490 ti = code[pc++]; 491 ai = code[pc++]; 492 if (!unify(argVars[ai], tVars[ti])) { 493 if (traceOn) logger.info("FAIL " + clause); 494 continue main; 495 } 496 break; 497 498 case RuleClauseCode.PUT_NEW_VARIABLE: 499 yi = code[pc++]; 500 ai = code[pc++]; 501 argVars[ai] = pVars[yi] = new Node_RuleVariable(null, yi); 502 break; 503 504 case RuleClauseCode.PUT_VARIABLE: 505 yi = code[pc++]; 506 ai = code[pc++]; 507 argVars[ai] = pVars[yi]; 508 break; 509 510 case RuleClauseCode.PUT_DEREF_VARIABLE: 511 yi = code[pc++]; 512 ai = code[pc++]; 513 argVars[ai] = deref(pVars[yi]); 514 break; 515 516 case RuleClauseCode.PUT_TEMP: 517 ti = code[pc++]; 518 ai = code[pc++]; 519 argVars[ai] = tVars[ti]; 520 break; 521 522 case RuleClauseCode.PUT_CONSTANT: 523 ai = code[pc++]; 524 argVars[ai] = (Node)args[ac++]; 525 break; 526 527 case RuleClauseCode.CLEAR_ARG: 528 ai = code[pc++]; 529 argVars[ai] = new Node_RuleVariable(null, ai); 530 break; 531 532 case RuleClauseCode.MAKE_FUNCTOR: 533 Functor f = (Functor)args[ac++]; 534 Node[] fargs = new Node[f.getArgLength()]; 535 System.arraycopy(argVars, 3, fargs, 0, fargs.length); 536 argVars[2] = Functor.makeFunctorNode(f.getName(), fargs); 537 break; 538 539 case RuleClauseCode.LAST_CALL_PREDICATE: 540 case RuleClauseCode.CALL_PREDICATE: 542 List clauses = (List)args[ac++]; 543 setupClauseCall(pc, ac, clauses); 544 setupTripleMatchCall(pc, ac); 545 continue main; 546 547 case RuleClauseCode.CALL_PREDICATE_INDEX: 548 clauses = (List)args[ac++]; 551 if (!argVars[2].isVariable()) { 553 clauses = engine.getRuleStore().codeFor( 554 new TriplePattern(argVars[0], argVars[1], argVars[2])); 555 } 556 setupClauseCall(pc, ac, clauses); 557 setupTripleMatchCall(pc, ac); 558 continue main; 559 560 case RuleClauseCode.CALL_TRIPLE_MATCH: 561 setupTripleMatchCall(pc, ac); 562 continue main; 563 564 case RuleClauseCode.CALL_TABLED: 565 setupTabledCall(pc, ac); 566 continue main; 567 568 case RuleClauseCode.CALL_WILD_TABLED: 569 Node predicate = deref(argVars[1]); 570 if (engine.getRuleStore().isTabled(predicate)) { 571 setupTabledCall(pc, ac); 572 } else { 573 clauses = engine.getRuleStore().codeFor( 575 new TriplePattern(argVars[0], predicate, argVars[2])); 576 if (clauses != null) setupClauseCall(pc, ac, clauses); 577 setupTripleMatchCall(pc, ac); 578 } 579 continue main; 580 581 case RuleClauseCode.PROCEED: 582 pc = envFrame.cpc; 583 ac = envFrame.cac; 584 if (traceOn) logger.info("EXIT " + clause); 585 if (recordDerivations && envFrame.getRule() != null) { 586 if (envFrame instanceof EnvironmentFrameWithDerivation) { 587 EnvironmentFrameWithDerivation efd = (EnvironmentFrameWithDerivation) envFrame; 588 Triple result = efd.getResult(); 589 List matches = efd.getMatchList(); 590 BackwardRuleInfGraphI infGraph = engine.getInfGraph(); 591 RuleDerivation d = new RuleDerivation(envFrame.getRule(), result, matches, infGraph); 592 infGraph.logDerivation(result, d); 593 } 594 } 595 envFrame = (EnvironmentFrame) envFrame.link; 596 if (envFrame != null) { 597 clause = envFrame.clause; 598 } 599 continue interpreter; 600 601 case RuleClauseCode.CALL_BUILTIN: 602 Builtin builtin = (Builtin)args[ac++]; 603 if (context == null) { 604 BBRuleContext bbcontext = new BBRuleContext(engine.getInfGraph()); 605 bbcontext.setEnv(new LPBindingEnvironment(this)); 606 context = bbcontext; 607 } 608 context.setRule(clause.getRule()); 609 if (!builtin.bodyCall(argVars, code[pc++], context)) { 610 if (traceOn) logger.info("FAIL " + clause + ", due to " + builtin.getName()); 611 continue main; 612 } 613 break; 614 615 default : 616 throw new ReasonerException("Internal error in backward rule system\nIllegal op code"); 617 } 618 } 619 } 621 return StateFlag.ACTIVE; 623 } 624 return StateFlag.FAIL; 626 } 627 628 631 private String getArgTrace() { 632 StringBuffer temp = new StringBuffer (); 633 temp.append(PrintUtil.print(deref(argVars[0]))); 634 temp.append(" "); 635 temp.append(PrintUtil.print(deref(argVars[1]))); 636 temp.append(" "); 637 temp.append(PrintUtil.print(deref(argVars[2]))); 638 return temp.toString(); 639 } 640 641 644 private void setupTripleMatchCall(int pc, int ac) { 645 TripleMatchFrame tmFrame = new TripleMatchFrame(this); 646 tmFrame.setContinuation(pc, ac); 647 tmFrame.linkTo(cpFrame); 648 cpFrame = tmFrame; 649 } 650 651 654 private void setupClauseCall(int pc, int ac, List clauses) { 655 ChoicePointFrame newChoiceFrame = new ChoicePointFrame(this, clauses); 656 newChoiceFrame.linkTo(cpFrame); 657 newChoiceFrame.setContinuation(pc, ac); 658 cpFrame = newChoiceFrame; 659 } 660 661 664 private void setupTabledCall(int pc, int ac) { 665 ConsumerChoicePointFrame ccp = new ConsumerChoicePointFrame(this); 666 ccp.linkTo(cpFrame); 667 ccp.setContinuation(pc, ac); 668 cpFrame = ccp; 669 } 670 671 675 public void preserveState(ConsumerChoicePointFrame ccp) { 676 ccp.preserveState(trail); 677 } 678 679 682 public void restoreState(ConsumerChoicePointFrame ccp) { 683 cpFrame = ccp; 684 ccp.restoreState(this); 685 iContext = ccp.context; 686 } 687 688 692 public boolean unify(Node n1, Node n2) { 693 Node nv1 = n1; 694 if (nv1 instanceof Node_RuleVariable) { 695 nv1 = ((Node_RuleVariable)n1).deref(); 696 697 } 698 Node nv2 = n2; 699 if (nv2 instanceof Node_RuleVariable) { 700 nv2 = ((Node_RuleVariable)n2).deref(); 701 } 702 if (nv1 instanceof Node_RuleVariable) { 703 bind(nv1, nv2); 704 return true; 705 } else if (nv2 instanceof Node_RuleVariable) { 706 bind(nv2, nv1); 707 return true; 708 } else { 709 return nv1.sameValueAs(nv2); 710 } 711 712 } 713 714 719 public void bind(Node var, Node val) { 720 ((Node_RuleVariable)var).simpleBind(val); 721 trail.add(var); 722 } 723 724 727 public void unwindTrail(int mark) { 728 for (int i = trail.size()-1; i >= mark; i--) { 729 Node_RuleVariable var = (Node_RuleVariable)trail.get(i); 730 var.unbind(); 731 trail.remove(i); 732 } 733 } 734 735 738 public static Node deref(Node node) { 739 if (node instanceof Node_RuleVariable) { 740 return ((Node_RuleVariable)node).deref(); 741 } else { 742 return node; 743 } 744 } 745 746 749 public static Node derefPossFunctor(Node node) { 750 if (node instanceof Node_RuleVariable) { 751 Node dnode = ((Node_RuleVariable)node).deref(); 752 if (dnode.isVariable()) { 753 throw new ReasonerException("Internal error in LP reasoner: variable in triple result"); 755 } 756 if (Functor.isFunctor(dnode)) { 757 Functor f = (Functor) dnode.getLiteral().getValue(); 758 Node[] fargs = f.getArgs(); 759 boolean needCopy = false; 760 for (int i = 0; i < fargs.length; i++) { 761 if (fargs[i].isVariable()) { 762 needCopy = true; 763 break; 764 } 765 } 766 if (needCopy) { 767 Node[] newArgs = new Node[fargs.length]; 768 for (int i = 0; i < fargs.length; i++) { 769 newArgs[i] = deref(fargs[i]); 770 } 771 dnode = Functor.makeFunctorNode(f.getName(), newArgs); 772 } 773 return dnode; 774 } else { 775 return dnode; 776 } 777 } else { 778 return node; 779 } 780 } 781 782 788 private Node standardize(Node node, Map mappedVars) { 789 Node dnode = deref(node); 790 if (node == Node.ANY || node == Node_RuleVariable.WILD) { 791 return new Node_RuleVariable(null, 0); 792 } else if (dnode.isVariable()) { 793 Node mnode = (Node) mappedVars.get(dnode); 794 if (mnode == null) { 795 mnode = new Node_RuleVariable(null, 0); 796 mappedVars.put(dnode, mnode); 797 } 798 return mnode; 799 } else { 800 return dnode; 801 } 802 } 803 804 } 805 806 807 | Popular Tags |