/** * <code> * function UNIFY(x, y, theta) returns a substitution to make x and y identical * inputs: x, a variable, constant, list, or compound * y, a variable, constant, list, or compound * theta, the substitution built up so far (optional, defaults to empty) * </code> * * @return a Dictionary<Variable, Term> representing the substitution (i.e. a set * of variable/term pairs) or null which is used to indicate a * failure to unify. */ public Dictionary<Variable, Term> unify(FOLNode x, FOLNode y, Dictionary<Variable, Term> theta) { // if theta = failure then return failure if (theta == null) { return null; } else if (x.Equals(y)) { // else if x = y then return theta return theta; } else if (x is Variable) { // else if VARIABLE?(x) then return UNIVY-VAR(x, y, theta) return unifyVar((Variable)x, y, theta); } else if (y is Variable) { // else if VARIABLE?(y) then return UNIFY-VAR(y, x, theta) return unifyVar((Variable)y, x, theta); } else if (isCompound(x) && isCompound(y)) { // else if COMPOUND?(x) and COMPOUND?(y) then // return UNIFY(x.ARGS, y.ARGS, UNIFY(x.OP, y.OP, theta)) return unify(args(x), args(y), unifyOps(op(x), op(y), theta)); } else { // else return failure return null; } }
// PROTECTED METHODS // Note: You can subclass and override this method in order // to re-implement the OCCUR-CHECK?() to always // return false if you want that to be the default // behavior, as is the case with Prolog. protected bool occurCheck(Dictionary <Variable, Term> theta, Variable var, FOLNode x) { if (x is Function) { List <Variable> varsToCheck = _variableCollector .collectAllVariables((Function)x); if (varsToCheck.Contains(var)) { return(true); } // Now need to check if cascading will cause occurs to happen // e.g. // Loves(SF1(v2),v2) // Loves(v3,SF0(v3)) // or // P(v1,SF0(v1),SF0(v1)) // P(v2,SF0(v2),v2 ) // or // P(v1, F(v2),F(v2),F(v2),v1, F(F(v1)),F(F(F(v1))),v2) // P(F(v3),v4, v5, v6, F(F(v5)),v4, F(v3), F(F(v5))) return(cascadeOccurCheck(theta, var, varsToCheck, new List <Variable>(varsToCheck))); } return(false); }
/** * <code> * function UNIFY-VAR(var, x, theta) returns a substitution * inputs: var, a variable * x, any expression * theta, the substitution built up so far * </code> */ private IMap <Variable, Term> unifyVar(Variable var, FOLNode x, IMap <Variable, Term> theta) { if (!(x is Term)) { return(null); } else if (theta.ContainsKey(var)) { // if {var/val} E theta then return UNIFY(val, x, theta) return(unify(theta.Get(var), x, theta)); } else if (x is Variable && theta.ContainsKey(x as Variable)) { // else if {x/val} E theta then return UNIFY(var, val, theta) return(unify(var, theta.Get(x as Variable), theta)); } else if (occurCheck(theta, var, x)) { // else if OCCUR-CHECK?(var, x) then return failure return(null); } else { // else return add {var/x} to theta cascadeSubstitution(theta, var, (Term)x); return(theta); } }
// // PROTECTED METHODS // // Note: You can subclass and override this method in order // to re-implement the OCCUR-CHECK?() to always // return false if you want that to be the default // behavior, as is the case with Prolog. // Note: Implementation is based on unify-bug.pdf document by Peter Norvig: // http://norvig.com/unify-bug.pdf protected bool occurCheck(IMap <Variable, Term> theta, Variable var, FOLNode x) { // ((equal var x) t) if (var.Equals(x)) { return(true); // ((bound? x subst) } else if (x is Variable && theta.ContainsKey(x as Variable)) { // (occurs-in? var (lookup x subst) subst)) return(occurCheck(theta, var, theta.Get(x as Variable))); // ((consp x) (or (occurs-in? var (first x) subst) (occurs-in? var // (rest x) subst))) } else if (x is Function && x is Function) { // (or (occurs-in? var (first x) subst) (occurs-in? var (rest x) // subst))) Function fx = (Function)x; foreach (Term fxt in fx.getArgs()) { if (occurCheck(theta, var, fxt)) { return(true); } } } return(false); }
// PRIVATE METHODS /** * <code> * function UNIFY-VAR(var, x, theta) returns a substitution * inputs: var, a variable * x, any expression * theta, the substitution built up so far * </code> */ private Dictionary <Variable, Term> unifyVar(Variable var, FOLNode x, Dictionary <Variable, Term> theta) { if (!(x is Term)) { return(null); } else if (theta.ContainsKey(var)) { // if {var/val} E theta then return UNIFY(val, x, theta) return(unify(theta[var], x, theta)); } else if (theta.Keys.Contains(x)) { // else if {x/val} E theta then return UNIFY(var, val, theta) return(unify(var, (FOLNode)theta[(Variable)x], theta)); } else if (occurCheck(theta, var, x)) { // else if OCCUR-CHECK?(var, x) then return failure return(null); } else { // else return add {var/x} to theta cascadeSubstitution(theta, var, (Term)x); return(theta); } }
/** * Returns a Dictionary<Variable, Term> representing the substitution (i.e. a set * of variable/term pairs) or null which is used to indicate a failure to * unify. * * @param x * a variable, constant, list, or compound * @param y * a variable, constant, list, or compound * @param theta * the substitution built up so far * * @return a Dictionary<Variable, Term> representing the substitution (i.e. a set * of variable/term pairs) or null which is used to indicate a * failure to unify. */ public Dictionary <Variable, Term> unify(FOLNode x, FOLNode y, Dictionary <Variable, Term> theta) { // if theta = failure then return failure if (theta == null) { return(null); } else if (x.Equals(y)) { // else if x = y then return theta return(theta); } else if (x is Variable) { // else if VARIABLE?(x) then return UNIVY-VAR(x, y, theta) return(unifyVar((Variable)x, y, theta)); } else if (y is Variable) { // else if VARIABLE?(y) then return UNIFY-VAR(y, x, theta) return(unifyVar((Variable)y, x, theta)); } else if (isCompound(x) && isCompound(y)) { // else if COMPOUND?(x) and COMPOUND?(y) then // return UNIFY(x.ARGS, y.ARGS, UNIFY(x.OP, y.OP, theta)) return(unify(args(x), args(y), unifyOps(op(x), op(y), theta))); } else { // else return failure return(null); } }
public Dictionary<Variable, Term> unify(FOLNode x, FOLNode y) { return unify(x, y, new Dictionary<Variable, Term>()); }
private bool isCompound(FOLNode x) { return x.isCompound(); }
/** * Returns a Dictionary<Variable, Term> representing the substitution (i.e. a set * of variable/term pairs) or null which is used to indicate a failure to * unify. * * @param x * a variable, constant, list, or compound * @param y * a variable, constant, list, or compound * * @return a Dictionary<Variable, Term> representing the substitution (i.e. a set * of variable/term pairs) or null which is used to indicate a * failure to unify. */ public Dictionary <Variable, Term> unify(FOLNode x, FOLNode y) { return(unify(x, y, new Dictionary <Variable, Term>())); }
private String op(FOLNode x) { return(x.getSymbolicName()); }
// // PROTECTED METHODS // // Note: You can subclass and override this method in order // to re-implement the OCCUR-CHECK?() to always // return false if you want that to be the default // behavior, as is the case with Prolog. protected bool occurCheck(Dictionary<Variable, Term> theta, Variable var, FOLNode x) { if (x is Function) { List<Variable> varsToCheck = _variableCollector .collectAllVariables((Function)x); if (varsToCheck.Contains(var)) { return true; } // Now need to check if cascading will cause occurs to happen // e.g. // Loves(SF1(v2),v2) // Loves(v3,SF0(v3)) // or // P(v1,SF0(v1),SF0(v1)) // P(v2,SF0(v2),v2 ) // or // P(v1, F(v2),F(v2),F(v2),v1, F(F(v1)),F(F(F(v1))),v2) // P(F(v3),v4, v5, v6, F(F(v5)),v4, F(v3), F(F(v5))) return cascadeOccurCheck(theta, var, varsToCheck, new List<Variable>(varsToCheck)); } return false; }
public IMap <Variable, Term> unify(FOLNode x, FOLNode y) { return(unifier.unify(x, y)); }
public Dictionary<Variable, Term> unify(FOLNode x, FOLNode y) { return unifier.unify(x, y); }
/** * Returns a Map<Variable, Term> representing the substitution (i.e. a set * of variable/term pairs) or null which is used to indicate a failure to * unify. * * @param x * a variable, constant, list, or compound * @param y * a variable, constant, list, or compound * * @return a Map<Variable, Term> representing the substitution (i.e. a set * of variable/term pairs) or null which is used to indicate a * failure to unify. */ public IMap <Variable, Term> unify(FOLNode x, FOLNode y) { return(unify(x, y, CollectionFactory.CreateInsertionOrderedMap <Variable, Term>())); }
private ICollection <FOLNode> args(FOLNode x) { return(x.getArgs()); }
private List <FOLNode> args(FOLNode x) { return(x.getArgs()); }
// // PRIVATE METHODS // /** * <code> * function UNIFY-VAR(var, x, theta) returns a substitution * inputs: var, a variable * x, any expression * theta, the substitution built up so far * </code> */ private Dictionary<Variable, Term> unifyVar(Variable var, FOLNode x, Dictionary<Variable, Term> theta) { if (!(x is Term)) { return null; } else if (theta.ContainsKey(var)) { // if {var/val} E theta then return UNIFY(val, x, theta) return unify(theta[var], x, theta); } else if (theta.Keys.Contains(x)) { // else if {x/val} E theta then return UNIFY(var, val, theta) return unify(var, (FOLNode)theta[(Variable)x], theta); } else if (occurCheck(theta, var, x)) { // else if OCCUR-CHECK?(var, x) then return failure return null; } else { // else return add {var/x} to theta cascadeSubstitution(theta, var, (Term)x); return theta; } }
private bool isCompound(FOLNode x) { return(x.isCompound()); }
private List<FOLNode> args(FOLNode x) { return x.getArgs(); }
private String op(FOLNode x) { return x.getSymbolicName(); }
public Dictionary <Variable, Term> unify(FOLNode x, FOLNode y) { return(unifier.unify(x, y)); }