/// <summary> /// Gets the closest synset that is reachable from the current and another synset along the given relations. For example, /// given two synsets and the Hypernym relation, this will return the lowest synset that is a hypernym of both synsets. If /// the hypernym hierarchy forms a tree, this will be the lowest common ancestor. /// </summary> /// <param name="synset">Other synset</param> /// <param name="relations">Relations to follow</param> /// <returns>Closest mutually reachable synset</returns> public SynSet GetClosestMutuallyReachableSynset(SynSet synset, IEnumerable <WordNetEngine.SynSetRelation> relations) { // avoid cycles List <SynSet> synsetsEncountered = new List <SynSet>(); synsetsEncountered.Add(this); // start search queue Queue <SynSet> searchQueue = new Queue <SynSet>(); searchQueue.Enqueue(this); // run search SynSet closest = null; while (searchQueue.Count > 0 && closest == null) { SynSet currSynSet = searchQueue.Dequeue(); /* check for a path between the given synset and the current one. if such a path exists, the current * synset is the closest mutually reachable synset. */ if (synset.GetShortestPathTo(currSynSet, relations) != null) { closest = currSynSet; } // otherwise, expand the search along the given relations else { foreach (SynSet relatedSynset in currSynSet.GetRelatedSynSets(relations, false)) { if (!synsetsEncountered.Contains(relatedSynset)) { searchQueue.Enqueue(relatedSynset); synsetsEncountered.Add(relatedSynset); } } } } return(closest); }
/// <summary> /// Gets the shortest path from the current synset to another, following the given synset relations. /// </summary> /// <param name="destination">Destination synset</param> /// <param name="relations">Relations to follow, or null for all relations.</param> /// <returns>Synset path, or null if none exists.</returns> public List <SynSet> GetShortestPathTo(SynSet destination, IEnumerable <WordNetEngine.SynSetRelation> relations) { if (relations == null) { relations = Enum.GetValues(typeof(WordNetEngine.SynSetRelation)) as WordNetEngine.SynSetRelation[]; } // make sure the backpointer on the current synset is null - can't predict what other functions might do _searchBackPointer = null; // avoid cycles List <SynSet> synsetsEncountered = new List <SynSet>(); synsetsEncountered.Add(this); // start search queue Queue <SynSet> searchQueue = new Queue <SynSet>(); searchQueue.Enqueue(this); // run search List <SynSet> path = null; while (searchQueue.Count > 0 && path == null) { SynSet currSynSet = searchQueue.Dequeue(); // see if we've finished the search if (currSynSet == destination) { // gather synsets along path path = new List <SynSet>(); while (currSynSet != null) { path.Add(currSynSet); currSynSet = currSynSet.SearchBackPointer; } // reverse for the correct order path.Reverse(); } // expand the search one level else { foreach (SynSet synset in currSynSet.GetRelatedSynSets(relations, false)) { if (!synsetsEncountered.Contains(synset)) { synset.SearchBackPointer = currSynSet; searchQueue.Enqueue(synset); synsetsEncountered.Add(synset); } } } } // null-out all search backpointers foreach (SynSet synset in synsetsEncountered) { synset.SearchBackPointer = null; } return(path); }