/// <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 Set <SynSet> synsetsEncountered = new Set <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 similarity of two synsets /// </summary> /// <param name="synset1">First synset</param> /// <param name="synset2">Second synset</param> /// <param name="strategy">Strategy to use. All strategies named WuPalmer1994* will produce the same result since only two synsets /// are available.</param> /// <param name="relations">Synset relations to follow when computing similarity (pass null for all relations)</param> /// <returns>Similarity</returns> public float GetSimilarity(SynSet synset1, SynSet synset2, Strategy strategy, params WordNetEngine.SynSetRelation[] relations) { if (relations == null) { relations = Enum.GetValues(typeof(WordNetEngine.SynSetRelation)).Cast <WordNetEngine.SynSetRelation>().ToArray(); } float similarity = 0; if (strategy.ToString().StartsWith("WuPalmer1994")) { // get the LCS along the similarity relations SynSet lcs = synset1.GetClosestMutuallyReachableSynset(synset2, relations); if (lcs == null) { similarity = 0; } else { // get depth of synsets int lcsDepth = lcs.GetDepth(relations) + 1; int synset1Depth = synset1.GetShortestPathTo(lcs, relations).Count - 1 + lcsDepth; int synset2Depth = synset2.GetShortestPathTo(lcs, relations).Count - 1 + lcsDepth; // get similarity similarity = 2 * lcsDepth / (float)(synset1Depth + synset2Depth); } } else { throw new NotImplementedException("Unrecognized strategy"); } if (similarity < 0 || similarity > 1) { throw new Exception("Invalid similarity"); } return(similarity); }
/// <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 Set<SynSet> synsetsEncountered = new Set<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 similarity of two synsets /// </summary> /// <param name="synset1">First synset</param> /// <param name="synset2">Second synset</param> /// <param name="strategy">Strategy to use. All strategies named WuPalmer1994* will produce the same result since only two synsets /// are available.</param> /// <param name="relations">Synset relations to follow when computing similarity (pass null for all relations)</param> /// <returns>Similarity</returns> public float GetSimilarity(SynSet synset1, SynSet synset2, Strategy strategy, params WordNetEngine.SynSetRelation[] relations) { if (relations == null) relations = Enum.GetValues(typeof(WordNetEngine.SynSetRelation)).Cast<WordNetEngine.SynSetRelation>().ToArray(); float similarity = 0; if (strategy.ToString().StartsWith("WuPalmer1994")) { // get the LCS along the similarity relations SynSet lcs = synset1.GetClosestMutuallyReachableSynset(synset2, relations); if (lcs == null) similarity = 0; else { // get depth of synsets int lcsDepth = lcs.GetDepth(relations) + 1; int synset1Depth = synset1.GetShortestPathTo(lcs, relations).Count - 1 + lcsDepth; int synset2Depth = synset2.GetShortestPathTo(lcs, relations).Count - 1 + lcsDepth; // get similarity similarity = 2 * lcsDepth / (float)(synset1Depth + synset2Depth); } } else throw new NotImplementedException("Unrecognized strategy"); if (similarity < 0 || similarity > 1) throw new Exception("Invalid similarity"); return similarity; }