// OO jDREW - An Object Oriented extension of the Java Deductive Reasoning Engine for the Web // Copyright (C) 2005 Marcel Ball // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA package org.ruleml.oojdrew.TopDown; /** * <p>Title: OO jDREW</p> * * <p>Description: Reasoning Engine for the Semantic Web - Supporting OO RuleML * 0.88</p> * * <p>Copyright: Copyright (c) 2005</p> * * @author Marcel A. Ball * @version 0.89 */ import java.util.Hashtable; import java.util.Vector; import org.apache.log4j.Logger; import org.ruleml.oojdrew.parsing.RuleMLFormat; import org.ruleml.oojdrew.util.EngineException; import org.ruleml.oojdrew.util.SymbolTable; import org.ruleml.oojdrew.util.Term; import org.ruleml.oojdrew.util.Types; /** * A <code>Unifier</code> is an object that performs two separate functions: it * tells whether two clauses literals that occur in Goals/GoalLists clauses can * unify, and it builds the resulting Goals/GoalLists after the required * substitution, required for the unification, have been applied. * * In this case a DCTree.Goal and DCTree.GoalList are always used * * @author Marcel A. Ball */ public class Unifier { /** * This is use as a index for the goalLists, atoms, vars. */ static final int GOAL = 0; /** * This is use as a index for the goalLists, atoms, vars. */ static final int SUBGOALLIST = 1; /** * This variable stores references to the two goalLists that are * being considered; */ BackwardReasoner.GoalList[] goalLists; /** * An it for the mode. */ static final int DCTREE_MODE = 0; static final int POSL = 1; static final int RuleML = 2; /** * Switch this variable between 1 and 2, * 1 = POSL Bindings * 2 = RuleML Bindings */ int varBindTypes = POSL; /** * This variable stores a copy of the atoms of the two clauses. */ Term[][] atoms = null; /** *This variable is used to temporarly store variable bindings. */ Term[][] vars = null; /** * This array contains the variable names. */ String[] varNames; /** * Keeps track of the amount of Variables */ int variableSize; /** * Keeps track of the amount of variables. */ int variableCount; /** * Hastable for the variable bindings. */ Hashtable[] bindings; /** * The subGoalList that will be used by the Unifier, value of the current subGoals */ BackwardReasoner.GoalList subGoalList; /** * The goal that will be used by the Unifier, value of the current goal. */ BackwardReasoner.Goal goal; /** * This value is set to true if unification of the Goal and the first Goal * in the subGoalList is successful, false otherwise. * It should always be checked to see if it is set to true before calling * the applyToGoal() or applyToGoalList() methods, as they will throw a * RuntimeException if unification was not successful. */ public boolean unified = false; /** * This value is should be set to true if the unification is taking place when * travelling down the tree, and false when returning back up. This indication * is necessary to have proper type unification. */ public boolean down = false; /** * An int for the mode */ int mode; /** * This method will make a deep copy duplicate of the term. * * @param terms Term[] the term to be duplicated. * @param side int used by the unification process to check what clause a * term belongs to when doing unification. * @return Term[] the duplicated term. */ private static Term[] cloneTermArray(Term[] terms, int side) { Term[] nterms = new Term[terms.length]; for (int i = 0; i < nterms.length; i++) { nterms[i] = (Term) terms[i].deepCopy(side); } return nterms; } /** * Constructs a new Unifier for the OO-jDREW top-down module. * * @param goal <code>jDREW.oo.td.DCTree.Goal value</code> - a DCTree.Goal * value of the current goal * * @param subGoalList <code>jDREW.oo.td.DCTree.GoalList value</code> - a * DCTree.GoalList value of the current subGoals * * @param mode <code>int value</code> - an int for the mode - this should be * Unifier.DCTREE_MODE * * @param down <code>boolean value</code> - Tells the unifier if this is going * up or down the tree, use for applying type bindings correctly. */ public Unifier(BackwardReasoner.Goal goal, BackwardReasoner.GoalList subGoalList, int mode, boolean down) { this.mode = mode; this.down = down; if (mode == DCTREE_MODE) { this.goal = goal; goal.setSymbolIndex(); this.subGoalList = subGoalList; atoms = new Term[2][]; atoms[GOAL] = cloneTermArray(goal.goalList.atoms, GOAL); atoms[SUBGOALLIST] = cloneTermArray(subGoalList.atoms, SUBGOALLIST); goalLists = new BackwardReasoner.GoalList[2]; goalLists[GOAL] = goal.goalList; goalLists[SUBGOALLIST] = subGoalList; vars = new Term[2][]; vars[GOAL] = new Term[goal.goalList.varCount]; vars[SUBGOALLIST] = new Term[subGoalList.varCount]; this.variableSize = goal.goalList.varCount + subGoalList.varCount; this.variableCount = 0; this.varNames = new String[variableSize]; this.bindings = new Hashtable[2]; this.bindings[GOAL] = new Hashtable(); this.bindings[SUBGOALLIST] = new Hashtable(); unified = unify(atoms[GOAL][goal.symbolIndex], atoms[SUBGOALLIST][0], varBindTypes); } } /** * Constructs a new Unifier for the OO-jDREW top-down module. This is the same * as calling the Unifier(DCTree.Goal goal, DCTree.GoalList subGoalList, * int mode, boolean down) constructor with down set to false. * * @param goal <code>jDREW.oo.td.DCTree.Goal value</code> - a DCTree.Goal * value of the current goal * * @param subGoalList <code>jDREW.oo.td.DCTree.GoalList value</code> - a * DCTree.GoalList value of the current subGoals * * @param mode <code>int value</code> - an int for the mode - this should be * Unifier.DCTREE_MODE */ public Unifier(BackwardReasoner.Goal goal, BackwardReasoner.GoalList subGoalList, int mode) { this.mode = mode; if (mode == DCTREE_MODE) { this.goal = goal; goal.setSymbolIndex(); this.subGoalList = subGoalList; atoms = new Term[2][]; atoms[GOAL] = cloneTermArray(goal.goalList.atoms, GOAL); atoms[SUBGOALLIST] = cloneTermArray(subGoalList.atoms, SUBGOALLIST); goalLists = new BackwardReasoner.GoalList[2]; goalLists[GOAL] = goal.goalList; goalLists[SUBGOALLIST] = subGoalList; vars = new Term[2][]; vars[GOAL] = new Term[goal.goalList.varCount]; vars[SUBGOALLIST] = new Term[subGoalList.varCount]; this.variableSize = goal.goalList.varCount + subGoalList.varCount; this.variableCount = 0; this.varNames = new String[variableSize]; this.bindings = new Hashtable[2]; this.bindings[GOAL] = new Hashtable(); this.bindings[SUBGOALLIST] = new Hashtable(); unified = unify(atoms[GOAL][goal.symbolIndex], atoms[SUBGOALLIST][0],varBindTypes ); } } /** * This method is used to check if two terms unify with each other; and to * perform any variable bindings that are necessary to make the terms unfiy. * * For more details see the inline comments in the source of this method * and/or look at the description of the unify(Term, Term) method of the * jdrew.oo.bu.Unifier class. * * @param term1 Term One of the terms to attempt to unify. * * @param term2 Term The second term to attempt to unify. * * @param varBindTypes 1 = POSL 2 = RuleML * * @return boolean Returns true if the two terms unify; false otherwise. */ private boolean unify(Term term1, Term term2, int varBindType) { Term t1 = deref(term1); Term t2 = deref(term2); Logger logger = Logger.getLogger("jdrew.oo.td.Unifier"); //logger.debug(t1.toPOSLString(false)); //logger.debug(t2.toPOSLString(false)); if (t1.isExpr() && t2.isExpr()) { if (t1.getSymbol() == t2.getSymbol() && Types.isSuperClass(t2.getType(), t1.getType())) { Vector t1restterms = new Vector(); Vector t2restterms = new Vector(); Vector t1prestterms = new Vector(); Vector t2prestterms = new Vector(); boolean t1rest = (t1.rest >= 0); boolean t2rest = (t2.rest >= 0); boolean t1prest = (t1.prest >= 0); boolean t2prest = (t2.prest >= 0); int i = 0; int j = 0; while (i < t1.subTerms.length && j < t2.subTerms.length) { if (t1.subTerms[i].role == SymbolTable.IREST || t1.subTerms[i].role == SymbolTable.IPREST) { // This is a rest term in t1 - skip for now - this is handeled at the end of unification i++; continue; } if (t2.subTerms[j].role == SymbolTable.IREST || t2.subTerms[j].role == SymbolTable.IPREST) { // This is a rest term in t2 - skip for now - this is handeled at the end of unification j++; continue; } if (t1.subTerms[i].role < t2.subTerms[j].role) { // role(t1[i]) is before role(t2[j]) - go to next i or fail if (t1.subTerms[i].role == SymbolTable.INOROLE && t2prest) { // add to positional rest term list for t2 t2prestterms.add(t1.subTerms[i]); i++; } else if (t1.subTerms[i].role > SymbolTable.INOROLE && t2rest) { // add to slotted rest term list for t2 t2restterms.add(t1.subTerms[i]); i++; } else { return false; // no appropriate rest term in t2 - unification fails } } else if (t1.subTerms[i].role == t2.subTerms[j].role) { // role(t1[i]) is same as role(t2[j]) - unify t1[i] and t2[j] if (!unify(t1.subTerms[i], t2.subTerms[j], varBindTypes )) { return false; } i++; j++; } else if (t1.subTerms[i].role > t2.subTerms[j].role) { // role(t1[i]) is after role(t2[j]) - go to next j if (t2.subTerms[j].role == SymbolTable.INOROLE && t1prest) { // add to positional rest term list for t1 t1prestterms.add(t2.subTerms[j]); j++; } else if (t2.subTerms[j].role > SymbolTable.INOROLE && t1rest) { // add to slotted rest term list for t1 t1restterms.add(t2.subTerms[j]); j++; } else { return false; // no appropriate rest term in t1 - unification fails } } } while (i < t1.subTerms.length) { if (t1.subTerms[i].role == SymbolTable.IREST || t1.subTerms[i].role == SymbolTable.IPREST) { // This is a rest term in t1 - skip for now - this is handeled at the end of unification i++; } else if (t1.subTerms[i].role == SymbolTable.INOROLE && t2prest) { t2prestterms.add(t1.subTerms[i]); i++; } else if (t1.subTerms[i].role > SymbolTable.INOROLE && t2rest) { t2restterms.add(t1.subTerms[i]); i++; } else { return false; // no appropriate rest term in t2 - unification fails } } while (j < t2.subTerms.length) { if (t2.subTerms[j].role == SymbolTable.IREST || t2.subTerms[j].role == SymbolTable.IPREST) { // This is a rest term in t1 - skip for now - this is handeled at the end of unification j++; } else if (t2.subTerms[j].role == SymbolTable.INOROLE && t1prest) { t1prestterms.add(t2.subTerms[j]); j++; } else if (t2.subTerms[j].role > SymbolTable.INOROLE && t1rest) { t1restterms.add(t2.subTerms[j]); j++; } else { return false; // no appropriate rest term in t2 - unification fails } } // Now do unification of rest term with rest term list that was created Term t1prestterm = new Term(SymbolTable.IPLEX, SymbolTable.IPREST, Types.IOBJECT, t1prestterms); t1prestterm.setSide(t2.getSide()); Term t1restterm = new Term(SymbolTable.IPLEX, SymbolTable.IREST, Types.IOBJECT, t1restterms); t1restterm.setSide(t2.getSide()); Term t2prestterm = new Term(SymbolTable.IPLEX, SymbolTable.IPREST, Types.IOBJECT, t2prestterms); t2prestterm.setSide(t1.getSide()); Term t2restterm = new Term(SymbolTable.IPLEX, SymbolTable.IREST, Types.IOBJECT, t2restterms); t2restterm.setSide(t1.getSide()); if (t1prest) { if (!unify(t1.subTerms[t1.prest], t1prestterm, varBindTypes)) { return false; } } else { if (t1prestterms.size() > 0) { return false; // t1 has no positional rest term, but one is required for successful unification } } if (t1rest) { if (!unify(t1.subTerms[t1.rest], t1restterm,varBindTypes)) { return false; } } else { if (t1restterms.size() > 0) { return false; // t1 has no slotted rest term, but one is required for successful unification } } if (t2prest) { if (!unify(t2.subTerms[t2.prest], t2prestterm, varBindTypes)) { return false; } } else { if (t2prestterms.size() > 0) { return false; // t2 has no positional rest term, but one is required for successful unification } } if (t2rest) { if (!unify(t2.subTerms[t2.rest], t2restterm, varBindTypes )) { return false; } } else { if (t2restterms.size() > 0) { return false; // t2 has no slotted rest term, but one is required for successful unification } } return true; // All subterms unified correctly, symbols and types are compatible, therefore t1 and t2 unify } else { return false; // Symbols were different or types were not compatible (! (type(t2) >= type(t1))) } } else if (t1.isExpr() && !t2.isExpr()) { if (t2.getSymbol() < 0 && Types.isSuperClass(t2.getType(), t1.getType())) { // t2 is a variable, t1 is a complex term (Cterm, Plex, Atom) int side = t2.getSide(); int sym = -(t2.getSymbol() + 1); this.vars[side][sym] = t1; if (side == GOAL) { String t2str = "?" + this.goal.goalList.variableNames[sym]; if (t2.type != Types.IOBJECT) { t2str += " : " + Types.typeName(t2.type); } if (!t2str.startsWith("?$ANON")) { if (t1.getSide() == GOAL) { // System.out.println("1"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(t2str, t1.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(t2str, t1.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("2"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(t2str, t1.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(t2str, t1.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } else { String t2str = "?" + this.subGoalList.variableNames[sym]; if (t2.type != Types.IOBJECT) { t2str += " : " + Types.typeName(t2.type); } if (!t2str.startsWith("?$ANON")) { if (t1.getSide() == GOAL) { //System.out.println("3"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t2str, t1.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t2str, t1.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { // System.out.println("4"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t2str, t1.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t2str, t1.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } return true; } else { // t2 is an individual constant (Ind) and t2 is a complex term (Cterm, Plex, Atom) return false; } } else if (!t1.isExpr() && t2.isExpr()) { if (t1.getSymbol() < 0 && Types.isSuperClass(t1.getType(), t2.getType())) { // t1 is a variable, t2 is a complex term (Cterm, Plex, Atom) int side = t1.getSide(); int sym = -(t1.getSymbol() + 1); this.vars[side][sym] = t2; if (side == GOAL) { String t1str = "?" + this.goal.goalList.variableNames[sym]; if (t1.type != Types.IOBJECT) { t1str += " : " + Types.typeName(t1.type); } if (!t1str.startsWith("?$ANON")) { if (t2.getSide() == GOAL) { //System.out.println("5"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(t1str, t2.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(t1str, t2.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("6"); if(varBindType == POSL){ String posl = t2.toPOSLString(this.subGoalList.variableNames, true); if(posl.contains("->")){ posl = posl.substring(posl.indexOf("->") + 2); } this.goal.goalList.varBindings.put(t1str, posl); } if(varBindType == RuleML){ String ruleML = t2.toRuleMLString(this.subGoalList.variableNames, RuleMLFormat.RuleML91); int firstIndex = ruleML.indexOf("</Ind>"); int secondIndex = ruleML.indexOf("</slot>"); if(firstIndex != -1 && secondIndex != -1) ruleML = ruleML.substring(firstIndex+6, secondIndex); //System.out.println(ruleML); this.goal.goalList.varBindings.put(t1str, ruleML); } } } } else { String t1str = "?" + this.subGoalList.variableNames[sym]; if (t1.type != Types.IOBJECT) { t1str += " : " + Types.typeName(t1.type); } if (!t1str.startsWith("?$ANON")) { if (t2.getSide() == GOAL) { //System.out.println("7"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t1str, t2.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t1str, t2.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("8"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t1str, t2.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t1str, t2.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } return true; } else { // t1 is an individual constant (Ind) and t2 is a complex term (Cterm, Plex, Atom) return false; } } else if (!t1.isExpr() && !t2.isExpr()) { if (t1.getSymbol() >= 0 && t2.getSymbol() >= 0) { // Both t1 and t2 are individual constants (Ind) if (t1.getSymbol() == t2.getSymbol() && Types.isSuperClass(t1.getType(),t2.getType()) && (t1.getData() == t2.getData())) { //System.out.println("T1: "+ t1.getType()); //System.out.println("T2: " + t2.getType()); //System.out.println("Ind Ind unification"); //Both symbols are the same, and the types are compatible (type(t2) >= type(t1)) return true; } else { return false; } } else if (t1.getSymbol() < 0 && t2.getSymbol() >= 0) { // t1 is a variable (Var) and t2 is an individual constant (Ind) if (Types.isSuperClass(t1.getType(), t2.getType())) { int sym = -(t1.getSymbol() + 1); int side = t1.getSide(); this.vars[side][sym] = t2; if (side == GOAL) { String t1str = "?" + this.goal.goalList.variableNames[sym]; if (t1.type != Types.IOBJECT) { t1str += " : " + Types.typeName(t1.type); } if (!t1str.startsWith("?$ANON")) { if (t2.getSide() == GOAL) { //System.out.println("9"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(t1str, t2.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(t1str, t2.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("10"); if(varBindType == POSL){ String posl = t2.toPOSLString(this.subGoalList.variableNames, true); if(posl.contains("->")){ posl = posl.substring(posl.indexOf("->") + 2); } this.goal.goalList.varBindings.put(t1str, posl); } if(varBindType == RuleML){ String ruleML = t2.toRuleMLString(this.subGoalList.variableNames, RuleMLFormat.RuleML91); int firstIndex = ruleML.indexOf("</Ind>"); int secondIndex = ruleML.indexOf("</slot>"); if(firstIndex != -1 && secondIndex != -1) ruleML = ruleML.substring(firstIndex+6, secondIndex); this.goal.goalList.varBindings.put(t1str, ruleML); } } } } else { String t1str = "?" + this.subGoalList.variableNames[sym]; if (t1.type != Types.IOBJECT) { t1str += " : " + Types.typeName(t1.type); } if (!t1str.startsWith("?$ANON")) { if (t2.getSide() == GOAL) { //System.out.println("11"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t1str, t2.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t1str, t2.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("12"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t1str, t2.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t1str, t2.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } return true; } else { return false; // Types are not compatible (! (type(t1) >= type(t2)) ) } } else if (t1.getSymbol() >= 0 && t2.getSymbol() < 0) { // t1 is an individual constant (Ind) and t2 is a variable (Var) if (Types.isSuperClass(t2.getType(), t1.getType())) { int sym = -(t2.getSymbol() + 1); int side = t2.getSide(); this.vars[side][sym] = t1; if (side == GOAL) { String t2str = "?" + this.goal.goalList.variableNames[sym]; if (t2.type != Types.IOBJECT) { t2str += " : " + Types.typeName(t2.type); } if (!t2str.startsWith("?$ANON")) { if (t1.getSide() == GOAL) { // System.out.println("13"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(t2str, t1.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(t2str, t1.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("14"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(t2str, t1.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(t2str, t1.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } else { String t2str = "?" + this.subGoalList.variableNames[sym]; if (t2.type != Types.IOBJECT) { t2str += " : " + Types.typeName(t2.type); } if (!t2str.startsWith("?$ANON")) { if (t1.getSide() == GOAL) { //System.out.println("15"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t2str, t1.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t2str, t1.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("16"); if(varBindType == POSL){ this.subGoalList.varBindings.put(t2str, t1.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(t2str, t1.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } return true; } else { return false; // Types are not compatible (! (type(t2) >= type(t2)) ) } } else if (t1.getSymbol() < 0 && t2.getSymbol() < 0) { if (t1.getSide() == t2.getSide() && t1.getSymbol() == t2.getSymbol()) { return true; // same variable - done nothing - prevents infinite dereference loop } // Both t1 and t2 are variables (Var) int type = Types.greatestLowerBound(t1.getType(), t2.getType()); if(type == Types.INOTHING){ //Logger logger = Logger.getLogger("jdrew.oo.td.Unifier"); logger.debug("Unification failed as there is no type that satisfies the restrictions of both variable types: " + Types.typeName(t1.getType()) + " and " + Types.typeName(t2.getType())); return false; } //System.out.println("hi"); //System.out.println("======Unifier 95========="); Term x; Term y; if (down) { x = t1; y = t2; } else { x = t2; y = t1; } int side = y.getSide(); int sym = -(y.getSymbol() + 1); Term xdc = x.deepCopy(); xdc.setType(type); this.vars[side][sym] = xdc; if (side == GOAL) { String ystr = "?" + this.goal.goalList.variableNames[sym]; if (y.type != Types.IOBJECT) { ystr += " : " + Types.typeName(y.type); } if (!ystr.startsWith("?$ANON")) { if (x.getSide() == GOAL) { // System.out.println("17"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(ystr, x.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(ystr, x.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { // System.out.println("18"); if(varBindType == POSL){ this.goal.goalList.varBindings.put(ystr, x.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.goal.goalList.varBindings.put(ystr, x.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } else { String ystr = "?" + this.subGoalList.variableNames[sym]; if (y.type != Types.IOBJECT) { ystr += " : " + Types.typeName(y.type); } if (!ystr.startsWith("?$ANON")) { if (x.getSide() == GOAL) { //System.out.println("19"); if(varBindType == POSL){ this.subGoalList.varBindings.put(ystr, x.toPOSLString(this.goal.goalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(ystr, x.toRuleMLString(this.goal.goalList. variableNames, RuleMLFormat.RuleML91)); } } else { //System.out.println("20"); if(varBindType == POSL){ this.subGoalList.varBindings.put(ystr, x.toPOSLString(this.subGoalList. variableNames, true)); } if(varBindType == RuleML){ this.subGoalList.varBindings.put(ystr, x.toRuleMLString(this.subGoalList. variableNames, RuleMLFormat.RuleML91)); } } } } return true; } else { throw new EngineException("Terms are not valid."); } // This should never happen - one of the previous cases will always occur } else { throw new EngineException("Terms are not valid."); } // This should never happen - one of the previous cases will always occur } /** * This method is used to dereference a variable; i.e. to find any variable * bindings that have already been made. * * @param term Term The term to dereference. * * @return Term The dereferenced term; if the initial term is not a variable * then this is that initial term; if the inital term is a variable, then * this will either be the original variable; or the term that that * variable was bound to if it has been bound. */ private Term deref(Term term) { if (term.getSymbol() > 0) { return term; } else { int side = term.getSide(); int sym = -(term.getSymbol() + 1); Term termd = null; if (sym < 0 || side < 0) { return term; } termd = vars[side][sym]; if (termd == null) { return term; } else { return deref(termd); } } } /** * */ private Hashtable varNameFound; /** * Used to apply the variable bindings to the current goal. Should only be * called if unified is set to true. */ public void applyToGoal() { if (!unified) { throw new RuntimeException( "Attempt to use substitution without unification."); } variableCount = 0; varNameFound = new Hashtable(); varNames = new String[this.variableSize]; if (mode == DCTREE_MODE) { goal.goalList.atoms = new Term[atoms[GOAL].length]; for (int i = 0; i < goal.goalList.atoms.length; i++) { goal.goalList.atoms[i] = apply(atoms[GOAL][i]); } goal.goalList.variableNames = this.varNames; goal.goalList.varCount = this.variableCount; goal.setSymbolIndex(); } } /** * Used to apply variable bindings to the sub goal list. Should only be called * if unified is set to true. */ public void applyToGoalList() { if (!unified) { throw new RuntimeException( "Attempt to use substitution without unification."); } variableCount = 0; varNameFound = new Hashtable(); varNames = new String[this.variableSize]; if (mode == DCTREE_MODE) { subGoalList.atoms = new Term[atoms[SUBGOALLIST].length]; for (int i = 0; i < subGoalList.atoms.length; i++) { subGoalList.atoms[i] = apply(atoms[SUBGOALLIST][i]); } subGoalList.varCount = this.variableCount; subGoalList.variableNames = this.varNames; } } /** * This method applies the varibale bindings to a term. * * @param t Term the term to apply variable bindings too. * * @return Term the term with variable bindings applied to it. */ private Term apply(Term ct) { int role = ct.getRole(); int classID = ct.getType(); if (!ct.isExpr()) { Term dCt = deref(ct); Term n = (Term) dCt.deepCopy(); n.setRole(role); //n.setType(classID); //n.classID = classID; if (dCt == ct) { if (n.getSymbol() < 0) { String t = n.getSide() + ":" + n.getSymbol(); int idx; if (varNameFound.containsKey(t)) { idx = ((Integer) varNameFound.get(t)).intValue(); } else { idx = variableCount; Integer idx2 = idx; varNameFound.put(t, idx2); varNames[idx] = goalLists[dCt.getSide()].variableNames[ - dCt.getSymbol() - 1]; variableCount++; } n.setSymbol( -(idx + 1)); //n.classID = classID; } return n; } else { Term n2 = apply(n); //if(n2.symbol < 0) // n2.setType(classID); return n2; } } else if (ct.isExpr()) { Term ct2 = ct; Term[] ct2terms = ct2.getSubTerms(); Vector terms2 = new Vector(); //Term[] terms2 = new Term[ct2terms.length]; for (int i = 0; i < ct2terms.length; i++) { Term test2 = deref(ct2terms[i]); if ((ct2terms[i].getRole() == SymbolTable.IPREST || ct2terms[i].getRole() == SymbolTable.IREST) && test2.isExpr() && test2.getSymbol() == SymbolTable.IPLEX) { Term[] restSubTerms = test2.getSubTerms(); for (int j = 0; j < restSubTerms.length; j++) { terms2.add(apply(restSubTerms[j])); } if (this.down) { String t = ct2terms[i].getSide() + ":" + ct2terms[i].getSymbol(); int idx; if (varNameFound.containsKey(t)) { idx = ((Integer) varNameFound.get(t)).intValue(); } else { idx = variableCount; Integer idx2 = idx; varNameFound.put(t, idx2); varNames[idx] = goalLists[ct2terms[i].getSide()]. variableNames[ -(ct2terms[i]. getSymbol() + 1)]; variableCount++; } int symn = -(idx + 1); terms2.add(new Term(symn, ct2terms[i].getRole(), Types.IOBJECT)); } } else { terms2.add(apply(ct2terms[i])); } } Term nct = new Term(ct2.getSymbol(), ct2.getRole(), ct2.getType(), terms2); nct.setSide(ct2.getSide()); nct.setAtom(ct.isAtom()); return nct; } else { throw new RuntimeException("Error creating resolvent."); } } }