Repository: nltk/nltk

Issue:
Wordnet similarity quirky when only one synsets needs root
Sometimes when only one synset needs root, the similarity between the synsets are not commutative:

```python
from nltk.corpus import wordnet as nltk_wn

ncat = nltk_wn.synset('cat.n.01')
nbuy = nltk_wn.synset('buy.v.01')

print(nltk_wn.path_similarity(nbuy, ncat), nltk_wn.wup_similarity(nbuy, ncat))
print(nltk_wn.path_similarity(ncat, nbuy), nltk_wn.wup_similarity(ncat, nbuy))
```

[out]:

```
0.058823529411764705 0.1111111111111111
None None
```

Details on https://stackoverflow.com/q/20075335/610569 


Discussion:
@alvations, I've seen this "quirk" myself, and as the StackOverflow answer suggests, there are two ways of resolving this:

1. If there is only one word in a pair that contains a root, simulate a root by default, unless specified otherwise.
2. If there is only one word in a pair that contains a root, find the similarities from the one with the simulated root (one that returns a value), and modify the similarity functions to provide that as an output by default.

Is my interpretation of the possible solution correct? Are there any other methods of resolving this?

Resolving patch:
diff --git a/nltk/corpus/reader/wordnet.py b/nltk/corpus/reader/wordnet.py
--- a/nltk/corpus/reader/wordnet.py
+++ b/nltk/corpus/reader/wordnet.py
@@ -845,7 +845,7 @@ def path_similarity(self, other, verbose=False, simulate_root=True):
         """
 
         distance = self.shortest_path_distance(
-            other, simulate_root=simulate_root and self._needs_root()
+            other, simulate_root=simulate_root and (self._needs_root() or other._needs_root()) 
         )
         if distance is None or distance < 0:
             return None
@@ -934,13 +934,15 @@ def wup_similarity(self, other, verbose=False, simulate_root=True):
             the two senses can be found, None is returned.
 
         """
+        need_root = self._needs_root() or other._needs_root()
 
-        need_root = self._needs_root()
         # Note that to preserve behavior from NLTK2 we set use_min_depth=True
         # It is possible that more accurate results could be obtained by
         # removing this setting and it should be tested later on
         subsumers = self.lowest_common_hypernyms(
-            other, simulate_root=simulate_root and need_root, use_min_depth=True
+            other,
+            simulate_root=simulate_root and need_root,
+            use_min_depth=True
         )
 
         # If no LCS was found return None


Test patch:
diff --git a/nltk/test/unit/test_wordnet.py b/nltk/test/unit/test_wordnet.py
--- a/nltk/test/unit/test_wordnet.py
+++ b/nltk/test/unit/test_wordnet.py
@@ -172,12 +172,16 @@ def test_wordnet_similarities(self):
         # Path based similarities.
         self.assertAlmostEqual(S('cat.n.01').path_similarity(S('cat.n.01')), 1.0)
         self.assertAlmostEqual(S('dog.n.01').path_similarity(S('cat.n.01')), 0.2)
+        self.assertAlmostEqual(S('car.n.01').path_similarity(S('automobile.v.01')),
+                               S('automobile.v.01').path_similarity(S('car.n.01')))
         self.assertAlmostEqual(
             S('dog.n.01').lch_similarity(S('cat.n.01')), 2.028, places=3
         )
         self.assertAlmostEqual(
             S('dog.n.01').wup_similarity(S('cat.n.01')), 0.8571, places=3
         )
+        self.assertAlmostEqual(S('car.n.01').wup_similarity(S('automobile.v.01')),
+                               S('automobile.v.01').wup_similarity(S('car.n.01')))
         # Information Content similarities.
         brown_ic = wnic.ic('ic-brown.dat')
         self.assertAlmostEqual(