private static bool FindSubst(Name n1, Name n2, bool allowPartialTerms, SubstitutionSet bindings) { n1 = n1.MakeGround(bindings); n2 = n2.MakeGround(bindings); var t = GetTerms(n1, n2, allowPartialTerms); if (t == null) { return(false); } foreach (var p in t) { Substitution candidate = null; bool isVar1 = p.Item1.IsVariable; bool isVar2 = p.Item2.IsVariable; // Case 1: x = t, where t is not a variable and x is a variable, and create substitution x/t if (isVar1 != isVar2) { Name variable = (isVar1 ? p.Item1 : p.Item2); Name value = isVar1 ? p.Item2 : p.Item1; if (value.ContainsVariable(variable)) //Occurs check to prevent cyclical evaluations { return(false); } candidate = new Substitution(variable, new ComplexValue(value)); } else if (isVar1) //isVar1 == isVar2 == true { //Case 2: x = x, where x is a variable, ignore it. otherwise add the substitution if (!(p.Item1 == p.Item2)) { candidate = new Substitution(p.Item1, new ComplexValue(p.Item2)); } } else //isVar1 == isVar2 == false { // Case 3: t1 = t2, where t1,t2 are not variables. // If they don't contain variables, compare them to see if they are equal. If they are not equal the unification fails. if (p.Item1.IsGrounded && p.Item2.IsGrounded) { if (p.Item1 == p.Item2) { continue; } if (p.Item1 == Name.UNIVERSAL_SYMBOL || p.Item2 == Name.UNIVERSAL_SYMBOL) { continue; } return(false); } //If one or both contain variables, unify the terms if (!FindSubst(p.Item1, p.Item2, allowPartialTerms, bindings)) { return(false); } } if (candidate != null) { // Step 4: check to see if the newly created substitution conflicts with any of the already created substitution. // If it does, the unification fails. if (!bindings.AddSubstitution(candidate)) { return(false); } } } return(true); }
public override Name MakeGround(SubstitutionSet bindings) { return(this); }
/// <summary> /// Given a SubstitutionSet, tries to ground this Name by substituting every variable with the corresponding value. /// </summary> /// <param name="bindings">The SubstitutionSet to be used to ground this Name.</param> /// <returns>A new instance, which is a clone of this Name, but grounded as much as possible.</returns> /// <remarks> /// - If this instance is already grounded before calling this method, it will just return the same Name. /// - This method does not warrant that this Name will be fully grounded, as the given SubstitutionSet /// may not contain the substitution variables needed to perform the task. /// </remarks> public abstract Name MakeGround(SubstitutionSet bindings);