/// <summary> /// Gets the VerbClass path from this class to another class /// </summary> /// <param name="verbClass">Destination class</param> /// <returns>Sequence of verb classes representing the path</returns> public List <VerbClass> GetPathTo(VerbClass verbClass) { // get the lca VerbClass lca = GetLowestCommonAncestor(verbClass); // add classes from the current to the lca List <VerbClass> path = new List <VerbClass>(); VerbClass current = this; while (current != lca) { path.Add(current); current = current.Parent; } // add lca path.Add(lca); // insert classes from the destination to the lca (make sure ordering it correct) int currInsert = path.Count; current = verbClass; while (current != lca) { path.Insert(currInsert, current); current = current.Parent; } return(path); }
/// <summary> /// Adds a child class to this class /// </summary> /// <param name="child">Child class to add</param> public void AddChild(VerbClass child) { if (child.Parent != null) { throw new Exception("Child class already has a parent"); } child._parent = this; _children.Add(child); }
/// <summary> /// Gets examples from this class /// </summary> /// <param name="includeInherited">Whether or not to include inherited examples</param> /// <returns>Examples</returns> public Set <string> GetExamples(bool includeInherited) { // start with roles in this class Set <string> examples = _examples.Copy(); // optionally add inherited if (includeInherited) { examples.ThrowExceptionOnDuplicateAdd = false; VerbClass current = this; while ((current = current.Parent) != null) { examples.AddRange(current.GetExamples(false)); } } return(examples); }
/// <summary> /// Gets thematic roles in this class /// </summary> /// <param name="includeInherited">Whether or not to include inherited roles</param> /// <returns>Thematic roles</returns> public Set <VerbNetEngine.ThematicRole> GetThematicRoles(bool includeInherited) { // start with roles in this class Set <VerbNetEngine.ThematicRole> roles = _thematicRoles.Copy(); // optionally add inherited if (includeInherited) { roles.ThrowExceptionOnDuplicateAdd = false; VerbClass current = this; while ((current = current.Parent) != null) { roles.AddRange(current.GetThematicRoles(false)); } } return(roles); }
/// <summary> /// Gets the lowest common ancestor between this class and another /// </summary> /// <param name="verbClass">Other class</param> /// <returns>Lowest common ancestor</returns> public VerbClass GetLowestCommonAncestor(VerbClass verbClass) { // append period to both IDs to remove any ambiguity about classes...then get common substring string lcaID = GetCommonInitialSubstring((_id + "."), (verbClass.ID + ".")); ; int lastPeriod = lcaID.LastIndexOf('.'); lcaID = lcaID.Substring(0, lastPeriod); // find lca VerbClass lca = this; while (lca.ID != lcaID) { lca = lca.Parent; } return(lca); }
/// <summary> /// Checks whether this class has a thematic role /// </summary> /// <param name="role">Role to check for</param> /// <param name="includeInherited">Whether or not to include inherited roles</param> /// <returns>True if role is present and false otherwise</returns> public bool ContainsThematicRole(VerbNetEngine.ThematicRole role, bool includeInherited) { VerbClass currClass = this; while (currClass != null) { // check current class if (currClass._thematicRoles.Contains(role)) { return(true); } // check parent class if allowed else if (includeInherited) { currClass = currClass.Parent; } else { return(false); } } return(false); }
/// <summary> /// Constructor /// </summary> /// <param name="verbNetDirectory">Path to the VerbNet directory</param> public VerbNetEngine(string verbNetDirectory) { // check directory if (!Directory.Exists(verbNetDirectory)) { throw new Exception("Invalid VerbNet directory"); } // extract all verb classes _idVerbClass = new Dictionary <string, VerbClass>(); foreach (string classPath in Directory.GetFiles(verbNetDirectory, "*.xml")) { ExtractClass(File.ReadAllText(classPath), false); } // add root class _rootVerbClass = new VerbClass("0"); _idVerbClass.Add(_rootVerbClass.ID, _rootVerbClass); // assemble hierarchy while (true) { // create empty "connector" classes for verbnet classes whose direct parent is not defined in verbnet Dictionary <string, VerbClass> newIdVerbClass = new Dictionary <string, VerbClass>(); // check all non-root classes that don't have a parent foreach (string id in _idVerbClass.Keys) { if (id != _rootVerbClass.ID && _idVerbClass[id].Parent == null) { VerbClass currentClass = _idVerbClass[id]; // get id of parent by removing the final location string parentID = id.Substring(0, id.LastIndexOf('.')); // try to get parent class VerbClass parentClass; if (!_idVerbClass.TryGetValue(parentID, out parentClass)) { // create new connector class, reusing existing connector class if we have one VerbClass connectorClass; if (!newIdVerbClass.TryGetValue(parentID, out connectorClass)) { connectorClass = new VerbClass(parentID); newIdVerbClass.Add(connectorClass.ID, connectorClass); } parentClass = connectorClass; } // add current class as sub-class of parent parentClass.AddChild(currentClass); } } // add all newly created connector classes foreach (string id in newIdVerbClass.Keys) { _idVerbClass.Add(id, newIdVerbClass[id]); } // if we didn't add any connector classes, each class (except the root) has a parent defined in _idVerbClass - hierarchy is complete if (newIdVerbClass.Count == 0) { break; } } // map each verb to its classes _verbVerbClasses = new Dictionary <string, Set <VerbClass> >(); foreach (VerbClass verbClass in _rootVerbClass.GetChildren(true)) { foreach (string verb in verbClass.GetVerbs(false)) { _verbVerbClasses.EnsureContainsKey(verb, typeof(Set <VerbClass>)); _verbVerbClasses[verb].Add(verbClass); } } // make sure all verb classes except for the root has a parent (i.e., make sure we have a rooted tree) foreach (VerbClass vnClass in _idVerbClass.Values) { if (vnClass.ID != "0" && vnClass.Parent == null) { throw new Exception("Invalid VerbNet tree structure!"); } } }
/// <summary> /// Gets a class from the VerbNet hierarchy /// </summary> /// <param name="id">ID of class in 0.1.2.3 format</param> /// <param name="verbClass">Verb class if one was found</param> /// <returns>Verb class</returns> public bool TryGetClass(string id, out VerbClass verbClass) { return(_idVerbClass.TryGetValue(id, out verbClass)); }
/// <summary> /// Extracts a VerbNet class from its XML definition /// </summary> /// <param name="classXML">XML for class</param> /// <param name="isSubClassXML">Whether or not the XML describes a sub-class</param> /// <returns>VerbClass</returns> private VerbClass ExtractClass(string classXML, bool isSubClassXML) { // extract class from given XML VerbClass vnClass = null; XmlParser classP = new XmlParser(classXML); string classTag = isSubClassXML ? "VNSUBCLASS" : "VNCLASS"; string vnClassXML; while ((vnClassXML = classP.OuterXML(classTag)) != null) { XmlParser vnClassP = new XmlParser(vnClassXML); // get id, using only the dotted number portion and using 0 as the root of all classes string id = vnClassP.AttributeValue(classTag, "ID").Trim().Replace('-', '.'); id = "0." + id.Substring(id.IndexOf('.') + 1); // create class vnClass = new VerbClass(id); // extract verbs XmlParser membersP = new XmlParser(vnClassP.OuterXML("MEMBERS")); string verb; while ((verb = membersP.AttributeValue("MEMBER", "name")) != null) { vnClass.AddVerb(verb); membersP.MoveToElementNode(false); } // extract thematic roles XmlParser rolesP = new XmlParser(vnClassP.OuterXML("THEMROLES")); string role; while ((role = rolesP.AttributeValue("THEMROLE", "type")) != null) { vnClass.AddThematicRole((ThematicRole)Enum.Parse(typeof(ThematicRole), role)); rolesP.MoveToElementNode(false); } // extract examples XmlParser examplesP = new XmlParser(vnClassP.OuterXML("FRAMES")); string example; while ((example = examplesP.ElementText("EXAMPLE")) != null) { vnClass.AddExample(example); } // extract subclasses XmlParser subClassesP = new XmlParser(vnClassP.OuterXML("SUBCLASSES")); string subClassXML; while ((subClassXML = subClassesP.OuterXML("VNSUBCLASS")) != null) { vnClass.AddChild(ExtractClass(subClassXML, true)); } // map id to verb class _idVerbClass.Add(vnClass.ID, vnClass); } if (vnClass == null) { throw new Exception("Invalid class XML"); } return(vnClass); }
/// <summary> /// Gets a simple measure of similarity between the current class and another class. The formula: 2 * depth(lca) / (depth(current) + depth(other)). /// This is similar to the Wu and Palmer (1994) metric for WordNet synset similarity. /// </summary> /// <param name="verbClass"></param> /// <returns></returns> public float GetHierarchicalSimilarityWith(VerbClass verbClass) { return((2 * GetLowestCommonAncestor(verbClass).Depth) / (float)(Depth + verbClass.Depth)); }