public SimpleName(string description) { this.literals = new List <Literal>(); this.isGrounded = true; description = description.RemoveWhiteSpace(); var n = Name.BuildName(description); //Substituir if (n.IsComposed) { char[] literalLimiterChars = { ' ', ',', '(', ')' }; string[] stringLiterals = description.Split(literalLimiterChars, StringSplitOptions.RemoveEmptyEntries); var lPos = 0; var depth = 0; for (int i = 0; i < description.Length; i++) { //add literal Literal lit = null; switch (description[i]) { case '(': this.literals.Add(new Literal(stringLiterals[lPos], LiteralType.Root, depth)); lPos++; depth++; break; case ',': if (description[i - 1] != ')') { this.literals.Add(new Literal(stringLiterals[lPos], LiteralType.Param, depth)); lPos++; } break; case ')': if (description[i - 1] != ')') { this.literals.Add(new Literal(stringLiterals[lPos], LiteralType.Param, depth)); lPos++; } depth--; break; } } } else //if n is non composed { this.literals.Add(new Literal(description, LiteralType.Param, 0)); } //check if grounded foreach (var l in this.literals) { if (SimpleWFN.IsVariable(l)) { this.isGrounded = false; } } }
public SimpleName(IEnumerable <Literal> literalList) { this.literals = new List <Literal>(); this.isGrounded = true; // used to reset the depth of the first literal to 0 var delta = literalList.FirstOrDefault().depth; foreach (var l in literalList) { this.literals.Add(new Literal(l.description, l.type, l.depth - delta)); if (SimpleWFN.IsVariable(l)) { this.isGrounded = false; } } }
//return the idx jump on the valName or -1 if it can't add the substitution private static int FindSubsAux(Literal var, Literal val, SimpleName valName, IDictionary <string, Substitution> bindings) { //first, analyse if the value is a composed name or a single parameter string valDescription; int valLiteralCount; if (val.type == LiteralType.Root) { SimpleName auxName = null; auxName = SimpleWFN.BuildNameFromContainedLiteral(valName, val); valDescription = auxName.ToString(); valLiteralCount = auxName.literals.Count; } else { valDescription = val.description; valLiteralCount = 1; } //check if a binding for the same variable already exists Substitution existingSub = null; bindings.TryGetValue(var.description, out existingSub); if (existingSub != null) { if (existingSub.SubValue.ToString().RemoveWhiteSpace().EqualsIgnoreCase(valDescription)) { return(valLiteralCount); } else { return(-1); } } //if there was no existing binding to the variable try { bindings[var.description] = new Substitution(var.description, valDescription); return(valLiteralCount); } catch (BadSubstitutionException) { return(-1); } }
/// <summary> /// Unifying Method, receives two WellFormedNames and tries /// to find a list of Substitutions that will make /// both names syntatically equal. The algorithm performs Occur Check, /// as such the unification of [X] and Luke([X]) will allways fail. /// /// The method goes on each symbol (for both names) at a time, and tries to find /// a substitution between them. Take into account that the Unification between /// [X](John,Paul) and Friend(John,[X]) fails because the algorithm considers [X] /// to be the same variable /// </summary> /// <see cref="FAtiMA.Core.WellFormedNames.Substitution"/> /// <see cref="FAtiMA.Core.WellFormedNames.Name"/> /// <param name="name1">The first Name</param> /// <param name="name2">The second Name</param> /// <param name="bindings">The out paramenter for the founded substitutions</param> /// <returns>True if the names are unifiable, in this case the bindings list will contain the found Substitutions, otherwise it will be empty</returns> public static bool Unify(SimpleName name1, SimpleName name2, out IEnumerable <Substitution> bindings) { bindings = null; if (name1 == null || name2 == null) { return(false); } if (SimpleWFN.IsGrounded(name1) && SimpleWFN.IsGrounded(name2)) { if (SimpleWFN.Match(name1, name2)) { bindings = Enumerable.Empty <Substitution>(); return(true); } else { return(false); } } bindings = FindSubst(name1, name2); return(bindings != null); }
private static IEnumerable <Substitution> FindSubst(SimpleName n1, SimpleName n2) { // SubstitutionSet bindings = new SubstitutionSet(); Dictionary <string, Substitution> bindings = new Dictionary <string, Substitution>(); var idx1 = 0; var idx2 = 0; do { var l1 = n1.literals[idx1]; var l2 = n2.literals[idx2]; //neither literal is a variable if (!SimpleWFN.IsVariable(l1) && !SimpleWFN.IsVariable(l2)) { if (l1.description.EqualsIgnoreCase(l2.description)) { idx1++; idx2++; continue; } else { return(null); } } //both literals are a variable if (SimpleWFN.IsVariable(l1) && SimpleWFN.IsVariable(l2)) { if (!l1.description.EqualsIgnoreCase(l2.description)) { if (bindings.ContainsKey(l1.description)) { return(null); } bindings[l1.description] = new Substitution(l1.description, l2.description); } idx1++; idx2++; continue; } //only l1 is a variable if (SimpleWFN.IsVariable(l1) && !SimpleWFN.IsVariable(l2)) { var res = FindSubsAux(l1, l2, n2, bindings); if (res == -1) { return(null); } else { idx1++; idx2 += res; continue; } } //only l2 is a variable if (!SimpleWFN.IsVariable(l1) && SimpleWFN.IsVariable(l2)) { var res = FindSubsAux(l2, l1, n1, bindings); if (res == -1) { return(null); } else { idx1 += res; idx2++; continue; } } throw new Exception("Unexpected Situation"); } while (idx1 < n1.literals.Count && idx2 < n2.literals.Count); if (idx1 == n1.literals.Count && idx2 == n2.literals.Count) { return(bindings.Values); // full match } else { return(null); // only partial match }; }
public static bool Match(SimpleName n1, SimpleName n2) { if (SimpleWFN.GetNumberOfTerms(n1) != SimpleWFN.GetNumberOfTerms(n2)) { return(false); } var idx1 = 0; var idx2 = 0; do { var l1 = n1.literals[idx1]; var l2 = n2.literals[idx2]; //auxiliary variables bool typesMatch = l1.type == l2.type; bool l1IsUniv = l1.description == Name.UNIVERSAL_STRING; bool l2IsUniv = l2.description == Name.UNIVERSAL_STRING; bool existsUniversal = l1IsUniv || l2IsUniv; //The easy matching scenario is when both types match if (typesMatch) { if (existsUniversal || l1.description.EqualsIgnoreCase(l2.description)) { idx1++; idx2++; continue; } return(false); //no universals and different descritions } //eg. matching S with S(A) if (!typesMatch && !existsUniversal) { return(false); } //l1 is a universal and l2 has a different type if (!typesMatch && l1IsUniv) { //l1 is a universal parameter and n2 is a root if (l1.type == LiteralType.Param) { // the index on n2 must jump until it reaches the depth of l1 again idx2 += FindJumpUntilDepthN(n2.literals, idx2, l1.depth); idx1++; continue; } //a root universal never matches any parameter except a universal if (l1.type == LiteralType.Root && !l2IsUniv) { return(false); } } //the last case is when l2 is the universal if (!typesMatch && l2IsUniv) { if (l2.type == LiteralType.Param) { // the index on n2 must jump until it reaches the depth of n1 again idx1 += FindJumpUntilDepthN(n1.literals, idx1, l2.depth); idx2++; continue; } //a root universal never matches any parameter except a universal if (l2.type == LiteralType.Root && !l1IsUniv) { return(false); } } } while (idx1 < n1.literals.Count && idx2 < n2.literals.Count); if (idx1 == n1.literals.Count && idx2 == n2.literals.Count) { return(true); // full match } else { return(false); // only partial match } }