We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Translation metrics in Python 2.7
The [CI Server](https://nltk.ci.cloudbees.com/job/nltk/TOXENV=py27-jenkins,jdk=jdk8latestOnlineInstall/lastCompletedBuild/testReport/) reports test failures for  `nltk.translate.ribes_score.kendall_tau` and `nltk.translate.ribes_score.spearman_rho`.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nltk/translate/ribes_score.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Natural Language Toolkit: RIBES Score
3 #
4 # Copyright (C) 2001-2015 NLTK Project
5 # Contributors: Katsuhito Sudoh, Liling Tan, Kasramvd, J.F.Sebastian, Mark Byers, ekhumoro, P. Ortiz
6 # URL: <http://nltk.org/>
7 # For license information, see LICENSE.TXT
8 """ RIBES score implementation """
9 
10 from itertools import islice
11 import math
12 
13 from nltk.util import ngrams, choose
14 
15 
16 def ribes(references, hypothesis, alpha=0.25, beta=0.10):
17     """
18     The RIBES (Rank-based Intuitive Bilingual Evaluation Score) from 
19     Hideki Isozaki, Tsutomu Hirao, Kevin Duh, Katsuhito Sudoh and 
20     Hajime Tsukada. 2010. "Automatic Evaluation of Translation Quality for 
21     Distant Language Pairs". In Proceedings of EMNLP. 
22     http://www.aclweb.org/anthology/D/D10/D10-1092.pdf 
23     
24     The generic RIBES scores used in shared task, e.g. Workshop for 
25     Asian Translation (WAT) uses the following RIBES calculations:
26     
27         RIBES = kendall_tau * (alpha**p1) * (beta**bp)
28     
29     Please note that this re-implementation differs from the official
30     RIBES implementation and though it emulates the results as describe
31     in the original paper, there are further optimization implemented 
32     in the official RIBES script.
33     
34     Users are encouraged to use the official RIBES script instead of this 
35     implementation when evaluating your machine translation system. Refer
36     to http://www.kecl.ntt.co.jp/icl/lirg/ribes/ for the official script.
37     
38     :param references: a list of reference sentences
39     :type reference: list(list(str))
40     :param hypothesis: a hypothesis sentence
41     :type hypothesis: list(str)
42     :param alpha: hyperparameter used as a prior for the unigram precision.
43     :type alpha: float
44     :param beta: hyperparameter used as a prior for the brevity penalty.
45     :type beta: float
46     :return: The best ribes score from one of the references.
47     :rtype: float
48     """
49     best_ribes = -1.0
50     # Calculates RIBES for each reference and returns the best score.
51     for reference in references:
52         # Collects the *worder* from the ranked correlation alignments.
53         worder = word_rank_alignment(reference, hypothesis)
54         nkt = kendall_tau(worder)
55             
56         # Calculates the brevity penalty
57         bp = min(1.0, math.exp(1.0 - 1.0 * len(reference)/len(hypothesis)))
58         
59         # Calculates the unigram precision, *p1*
60         p1 = 1.0 * len(worder) / len(hypothesis)
61         
62         _ribes = nkt * (p1 ** alpha) *  (bp ** beta)
63         
64         if _ribes > best_ribes: # Keeps the best score.
65             best_ribes = _ribes
66         
67     return best_ribes
68 
69 
70 def position_of_ngram(ngram, sentence):
71     """
72     This function returns the position of the first instance of the ngram 
73     appearing in a sentence.
74     
75     Note that one could also use string as follows but the code is a little
76     convoluted with type casting back and forth:
77         
78         char_pos = ' '.join(sent)[:' '.join(sent).index(' '.join(ngram))]
79         word_pos = char_pos.count(' ')
80         
81     Another way to conceive this is:
82     
83         return next(i for i, ng in enumerate(ngrams(sentence, len(ngram))) 
84                     if ng == ngram)
85                     
86     :param ngram: The ngram that needs to be searched
87     :type ngram: tuple
88     :param sentence: The list of tokens to search from.
89     :type sentence: list(str)
90     """
91     # Iterates through the ngrams in sentence.
92     for i,sublist in enumerate(ngrams(sentence, len(ngram))):
93         # Returns the index of the word when ngram matches.
94         if ngram == sublist:
95             return i
96 
97 
98 def word_rank_alignment(reference, hypothesis, character_based=False):
99     """    
100     This is the word rank alignment algorithm described in the paper to produce
101     the *worder* list, i.e. a list of word indices of the hypothesis word orders 
102     w.r.t. the list of reference words.
103     
104     Below is (H0, R0) example from the Isozaki et al. 2010 paper, 
105     note the examples are indexed from 1 but the results here are indexed from 0:
106     
107         >>> ref = str('he was interested in world history because he '
108         ... 'read the book').split()
109         >>> hyp = str('he read the book because he was interested in world '
110         ... 'history').split()
111         >>> word_rank_alignment(ref, hyp)
112         [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]
113         
114     The (H1, R1) example from the paper, note the 0th index:
115     
116         >>> ref = 'John hit Bob yesterday'.split()
117         >>> hyp = 'Bob hit John yesterday'.split()
118         >>> word_rank_alignment(ref, hyp)
119         [2, 1, 0, 3]
120 
121     Here is the (H2, R2) example from the paper, note the 0th index here too:
122     
123         >>> ref = 'the boy read the book'.split()
124         >>> hyp = 'the book was read by the boy'.split()
125         >>> word_rank_alignment(ref, hyp)
126         [3, 4, 2, 0, 1]
127         
128     :param reference: a reference sentence
129     :type reference: list(str)
130     :param hypothesis: a hypothesis sentence
131     :type hypothesis: list(str)
132     """
133     worder = []
134     hyp_len = len(hypothesis)
135     # Stores a list of possible ngrams from the reference sentence.
136     # This is used for matching context window later in the algorithm.
137     ref_ngrams = []
138     hyp_ngrams = []
139     for n in range(1, len(reference)+1):
140         for ng in ngrams(reference, n):
141             ref_ngrams.append(ng)
142         for ng in ngrams(hypothesis, n):
143             hyp_ngrams.append(ng)
144     for i, h_word in enumerate(hypothesis):
145         # If word is not in the reference, continue.
146         if h_word not in reference:
147             continue
148         # If we can determine one-to-one word correspondence for unigrams that 
149         # only appear once in both the reference and hypothesis.
150         elif hypothesis.count(h_word) == reference.count(h_word) == 1:
151             worder.append(reference.index(h_word))
152         else:
153             max_window_size = max(i, hyp_len-i+1)
154             for window in range(1, max_window_size):
155                 if i+window < hyp_len: # If searching the right context is possible.
156                     # Retrieve the right context window.
157                     right_context_ngram = tuple(islice(hypothesis, i, i+window+1))
158                     num_times_in_ref = ref_ngrams.count(right_context_ngram)
159                     num_times_in_hyp = hyp_ngrams.count(right_context_ngram) 
160                     # If ngram appears only once in both ref and hyp.
161                     if num_times_in_ref == num_times_in_hyp == 1:
162                         # Find the position of ngram that matched the reference.
163                         pos = position_of_ngram(right_context_ngram, reference)
164                         worder.append(pos)  # Add the positions of the ngram.
165                         break
166                 if window <= i: # If searching the left context is possible.
167                     # Retrieve the left context window.
168                     left_context_ngram = tuple(islice(hypothesis, i-window, i+1))
169                     num_times_in_ref = ref_ngrams.count(left_context_ngram)
170                     num_times_in_hyp = hyp_ngrams.count(left_context_ngram)
171                     if num_times_in_ref == num_times_in_hyp == 1:
172                         # Find the position of ngram that matched the reference.
173                         pos = position_of_ngram(left_context_ngram, reference)
174                         # Add the positions of the ngram.
175                         worder.append(pos+ len(left_context_ngram) -1)  
176                         break
177     return worder
178 
179     
180 def find_increasing_sequences(worder):
181     """
182     Given the *worder* list, this function groups monotonic +1 sequences. 
183     
184         >>> worder = [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]
185         >>> list(find_increasing_sequences(worder))
186         [(7, 8, 9, 10), (0, 1, 2, 3, 4, 5)]
187     
188     :param worder: The worder list output from word_rank_alignment
189     :param type: list(int)
190     """
191     items = iter(worder)
192     a, b = None, next(items, None)
193     result = [b]
194     while b is not None:
195         a, b = b, next(items, None)
196         if b is not None and a + 1 == b:
197             result.append(b)
198         else:
199             if len(result) > 1:
200                 yield tuple(result)
201             result = [b]
202 
203 
204 def kendall_tau(worder, normalize=True):
205     """
206     Calculates the Kendall's Tau correlation coefficient given the *worder*
207     list of word alignments from word_rank_alignment(), using the formula:
208     
209         tau = 2 * num_increasing_pairs / num_possible pairs -1
210     
211     Note that the no. of increasing pairs can be discontinuous in the *worder*
212     list and each each increasing sequence can be tabulated as choose(len(seq), 2) 
213     no. of increasing pairs, e.g.
214     
215         >>> worder = [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]
216         >>> number_possible_pairs = choose(len(worder), 2)
217         >>> round(kendall_tau(worder, normalize=False),3)
218         -0.236
219         >>> round(kendall_tau(worder),3)
220         0.382
221     
222     :param worder: The worder list output from word_rank_alignment
223     :type worder: list(int)
224     :param normalize: Flag to indicate normalization
225     :type normalize: boolean
226     :return: The Kendall's Tau correlation coefficient.
227     :rtype: float
228     """
229     worder_len = len(worder)
230     # Extract the groups of increasing/monotonic sequences.
231     increasing_sequences = find_increasing_sequences(worder)
232     # Calculate no. of increasing_pairs in *worder* list.
233     num_increasing_pairs = sum(choose(len(seq),2) for seq in increasing_sequences) 
234     # Calculate no. of possible pairs.
235     num_possible_pairs = choose(worder_len, 2)
236     # Kendall's Tau computation.
237     tau = 2 * num_increasing_pairs / num_possible_pairs -1
238     if normalize: # If normalized, the tau output falls between 0.0 to 1.0
239         return (tau + 1) /2
240     else: # Otherwise, the tau outputs falls between -1.0 to +1.0
241         return tau
242 
243 
244 def spearman_rho(worder, normalize=True):
245     """
246     Calculates the Spearman's Rho correlation coefficient given the *worder* 
247     list of word alignment from word_rank_alignment(), using the formula:
248     
249         rho = 1 - sum(d**2) / choose(len(worder)+1, 3)  
250         
251     Given that d is the sum of difference between the *worder* list of indices
252     and the original word indices from the reference sentence.
253     
254     Using the (H0,R0) and (H5, R5) example from the paper
255     
256         >>> worder =  [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]
257         >>> round(spearman_rho(worder, normalize=False), 3)
258         -0.591
259         >>> round(spearman_rho(worder), 3)
260         0.205
261     
262     :param worder: The worder list output from word_rank_alignment
263     :param type: list(int)
264     """
265     worder_len = len(worder)
266     sum_d_square = sum((wi - i)**2 for wi, i in zip(worder, range(worder_len)))
267     rho = 1 - sum_d_square / choose(worder_len+1, 3)
268     
269     if normalize: # If normalized, the rho output falls between 0.0 to 1.0
270         return (rho + 1) /2
271     else: # Otherwise, the rho outputs falls between -1.0 to +1.0
272         return rho
273
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/nltk/translate/ribes_score.py b/nltk/translate/ribes_score.py
--- a/nltk/translate/ribes_score.py
+++ b/nltk/translate/ribes_score.py
@@ -6,7 +6,7 @@
 # URL: <http://nltk.org/>
 # For license information, see LICENSE.TXT
 """ RIBES score implementation """
-
+from __future__ import division
 from itertools import islice
 import math

{"golden_diff": "diff --git a/nltk/translate/ribes_score.py b/nltk/translate/ribes_score.py\n--- a/nltk/translate/ribes_score.py\n+++ b/nltk/translate/ribes_score.py\n@@ -6,7 +6,7 @@\n # URL: <http://nltk.org/>\n # For license information, see LICENSE.TXT\n \"\"\" RIBES score implementation \"\"\"\n-\n+from __future__ import division\n from itertools import islice\n import math\n", "issue": "Translation metrics in Python 2.7\nThe [CI Server](https://nltk.ci.cloudbees.com/job/nltk/TOXENV=py27-jenkins,jdk=jdk8latestOnlineInstall/lastCompletedBuild/testReport/) reports test failures for  `nltk.translate.ribes_score.kendall_tau` and `nltk.translate.ribes_score.spearman_rho`.\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Natural Language Toolkit: RIBES Score\n#\n# Copyright (C) 2001-2015 NLTK Project\n# Contributors: Katsuhito Sudoh, Liling Tan, Kasramvd, J.F.Sebastian, Mark Byers, ekhumoro, P. Ortiz\n# URL: <http://nltk.org/>\n# For license information, see LICENSE.TXT\n\"\"\" RIBES score implementation \"\"\"\n\nfrom itertools import islice\nimport math\n\nfrom nltk.util import ngrams, choose\n\n\ndef ribes(references, hypothesis, alpha=0.25, beta=0.10):\n    \"\"\"\n    The RIBES (Rank-based Intuitive Bilingual Evaluation Score) from \n    Hideki Isozaki, Tsutomu Hirao, Kevin Duh, Katsuhito Sudoh and \n    Hajime Tsukada. 2010. \"Automatic Evaluation of Translation Quality for \n    Distant Language Pairs\". In Proceedings of EMNLP. \n    http://www.aclweb.org/anthology/D/D10/D10-1092.pdf \n    \n    The generic RIBES scores used in shared task, e.g. Workshop for \n    Asian Translation (WAT) uses the following RIBES calculations:\n    \n        RIBES = kendall_tau * (alpha**p1) * (beta**bp)\n    \n    Please note that this re-implementation differs from the official\n    RIBES implementation and though it emulates the results as describe\n    in the original paper, there are further optimization implemented \n    in the official RIBES script.\n    \n    Users are encouraged to use the official RIBES script instead of this \n    implementation when evaluating your machine translation system. Refer\n    to http://www.kecl.ntt.co.jp/icl/lirg/ribes/ for the official script.\n    \n    :param references: a list of reference sentences\n    :type reference: list(list(str))\n    :param hypothesis: a hypothesis sentence\n    :type hypothesis: list(str)\n    :param alpha: hyperparameter used as a prior for the unigram precision.\n    :type alpha: float\n    :param beta: hyperparameter used as a prior for the brevity penalty.\n    :type beta: float\n    :return: The best ribes score from one of the references.\n    :rtype: float\n    \"\"\"\n    best_ribes = -1.0\n    # Calculates RIBES for each reference and returns the best score.\n    for reference in references:\n        # Collects the *worder* from the ranked correlation alignments.\n        worder = word_rank_alignment(reference, hypothesis)\n        nkt = kendall_tau(worder)\n            \n        # Calculates the brevity penalty\n        bp = min(1.0, math.exp(1.0 - 1.0 * len(reference)/len(hypothesis)))\n        \n        # Calculates the unigram precision, *p1*\n        p1 = 1.0 * len(worder) / len(hypothesis)\n        \n        _ribes = nkt * (p1 ** alpha) *  (bp ** beta)\n        \n        if _ribes > best_ribes: # Keeps the best score.\n            best_ribes = _ribes\n        \n    return best_ribes\n\n\ndef position_of_ngram(ngram, sentence):\n    \"\"\"\n    This function returns the position of the first instance of the ngram \n    appearing in a sentence.\n    \n    Note that one could also use string as follows but the code is a little\n    convoluted with type casting back and forth:\n        \n        char_pos = ' '.join(sent)[:' '.join(sent).index(' '.join(ngram))]\n        word_pos = char_pos.count(' ')\n        \n    Another way to conceive this is:\n    \n        return next(i for i, ng in enumerate(ngrams(sentence, len(ngram))) \n                    if ng == ngram)\n                    \n    :param ngram: The ngram that needs to be searched\n    :type ngram: tuple\n    :param sentence: The list of tokens to search from.\n    :type sentence: list(str)\n    \"\"\"\n    # Iterates through the ngrams in sentence.\n    for i,sublist in enumerate(ngrams(sentence, len(ngram))):\n        # Returns the index of the word when ngram matches.\n        if ngram == sublist:\n            return i\n\n\ndef word_rank_alignment(reference, hypothesis, character_based=False):\n    \"\"\"    \n    This is the word rank alignment algorithm described in the paper to produce\n    the *worder* list, i.e. a list of word indices of the hypothesis word orders \n    w.r.t. the list of reference words.\n    \n    Below is (H0, R0) example from the Isozaki et al. 2010 paper, \n    note the examples are indexed from 1 but the results here are indexed from 0:\n    \n        >>> ref = str('he was interested in world history because he '\n        ... 'read the book').split()\n        >>> hyp = str('he read the book because he was interested in world '\n        ... 'history').split()\n        >>> word_rank_alignment(ref, hyp)\n        [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        \n    The (H1, R1) example from the paper, note the 0th index:\n    \n        >>> ref = 'John hit Bob yesterday'.split()\n        >>> hyp = 'Bob hit John yesterday'.split()\n        >>> word_rank_alignment(ref, hyp)\n        [2, 1, 0, 3]\n\n    Here is the (H2, R2) example from the paper, note the 0th index here too:\n    \n        >>> ref = 'the boy read the book'.split()\n        >>> hyp = 'the book was read by the boy'.split()\n        >>> word_rank_alignment(ref, hyp)\n        [3, 4, 2, 0, 1]\n        \n    :param reference: a reference sentence\n    :type reference: list(str)\n    :param hypothesis: a hypothesis sentence\n    :type hypothesis: list(str)\n    \"\"\"\n    worder = []\n    hyp_len = len(hypothesis)\n    # Stores a list of possible ngrams from the reference sentence.\n    # This is used for matching context window later in the algorithm.\n    ref_ngrams = []\n    hyp_ngrams = []\n    for n in range(1, len(reference)+1):\n        for ng in ngrams(reference, n):\n            ref_ngrams.append(ng)\n        for ng in ngrams(hypothesis, n):\n            hyp_ngrams.append(ng)\n    for i, h_word in enumerate(hypothesis):\n        # If word is not in the reference, continue.\n        if h_word not in reference:\n            continue\n        # If we can determine one-to-one word correspondence for unigrams that \n        # only appear once in both the reference and hypothesis.\n        elif hypothesis.count(h_word) == reference.count(h_word) == 1:\n            worder.append(reference.index(h_word))\n        else:\n            max_window_size = max(i, hyp_len-i+1)\n            for window in range(1, max_window_size):\n                if i+window < hyp_len: # If searching the right context is possible.\n                    # Retrieve the right context window.\n                    right_context_ngram = tuple(islice(hypothesis, i, i+window+1))\n                    num_times_in_ref = ref_ngrams.count(right_context_ngram)\n                    num_times_in_hyp = hyp_ngrams.count(right_context_ngram) \n                    # If ngram appears only once in both ref and hyp.\n                    if num_times_in_ref == num_times_in_hyp == 1:\n                        # Find the position of ngram that matched the reference.\n                        pos = position_of_ngram(right_context_ngram, reference)\n                        worder.append(pos)  # Add the positions of the ngram.\n                        break\n                if window <= i: # If searching the left context is possible.\n                    # Retrieve the left context window.\n                    left_context_ngram = tuple(islice(hypothesis, i-window, i+1))\n                    num_times_in_ref = ref_ngrams.count(left_context_ngram)\n                    num_times_in_hyp = hyp_ngrams.count(left_context_ngram)\n                    if num_times_in_ref == num_times_in_hyp == 1:\n                        # Find the position of ngram that matched the reference.\n                        pos = position_of_ngram(left_context_ngram, reference)\n                        # Add the positions of the ngram.\n                        worder.append(pos+ len(left_context_ngram) -1)  \n                        break\n    return worder\n\n    \ndef find_increasing_sequences(worder):\n    \"\"\"\n    Given the *worder* list, this function groups monotonic +1 sequences. \n    \n        >>> worder = [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        >>> list(find_increasing_sequences(worder))\n        [(7, 8, 9, 10), (0, 1, 2, 3, 4, 5)]\n    \n    :param worder: The worder list output from word_rank_alignment\n    :param type: list(int)\n    \"\"\"\n    items = iter(worder)\n    a, b = None, next(items, None)\n    result = [b]\n    while b is not None:\n        a, b = b, next(items, None)\n        if b is not None and a + 1 == b:\n            result.append(b)\n        else:\n            if len(result) > 1:\n                yield tuple(result)\n            result = [b]\n\n\ndef kendall_tau(worder, normalize=True):\n    \"\"\"\n    Calculates the Kendall's Tau correlation coefficient given the *worder*\n    list of word alignments from word_rank_alignment(), using the formula:\n    \n        tau = 2 * num_increasing_pairs / num_possible pairs -1\n    \n    Note that the no. of increasing pairs can be discontinuous in the *worder*\n    list and each each increasing sequence can be tabulated as choose(len(seq), 2) \n    no. of increasing pairs, e.g.\n    \n        >>> worder = [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        >>> number_possible_pairs = choose(len(worder), 2)\n        >>> round(kendall_tau(worder, normalize=False),3)\n        -0.236\n        >>> round(kendall_tau(worder),3)\n        0.382\n    \n    :param worder: The worder list output from word_rank_alignment\n    :type worder: list(int)\n    :param normalize: Flag to indicate normalization\n    :type normalize: boolean\n    :return: The Kendall's Tau correlation coefficient.\n    :rtype: float\n    \"\"\"\n    worder_len = len(worder)\n    # Extract the groups of increasing/monotonic sequences.\n    increasing_sequences = find_increasing_sequences(worder)\n    # Calculate no. of increasing_pairs in *worder* list.\n    num_increasing_pairs = sum(choose(len(seq),2) for seq in increasing_sequences) \n    # Calculate no. of possible pairs.\n    num_possible_pairs = choose(worder_len, 2)\n    # Kendall's Tau computation.\n    tau = 2 * num_increasing_pairs / num_possible_pairs -1\n    if normalize: # If normalized, the tau output falls between 0.0 to 1.0\n        return (tau + 1) /2\n    else: # Otherwise, the tau outputs falls between -1.0 to +1.0\n        return tau\n\n\ndef spearman_rho(worder, normalize=True):\n    \"\"\"\n    Calculates the Spearman's Rho correlation coefficient given the *worder* \n    list of word alignment from word_rank_alignment(), using the formula:\n    \n        rho = 1 - sum(d**2) / choose(len(worder)+1, 3)  \n        \n    Given that d is the sum of difference between the *worder* list of indices\n    and the original word indices from the reference sentence.\n    \n    Using the (H0,R0) and (H5, R5) example from the paper\n    \n        >>> worder =  [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        >>> round(spearman_rho(worder, normalize=False), 3)\n        -0.591\n        >>> round(spearman_rho(worder), 3)\n        0.205\n    \n    :param worder: The worder list output from word_rank_alignment\n    :param type: list(int)\n    \"\"\"\n    worder_len = len(worder)\n    sum_d_square = sum((wi - i)**2 for wi, i in zip(worder, range(worder_len)))\n    rho = 1 - sum_d_square / choose(worder_len+1, 3)\n    \n    if normalize: # If normalized, the rho output falls between 0.0 to 1.0\n        return (rho + 1) /2\n    else: # Otherwise, the rho outputs falls between -1.0 to +1.0\n        return rho\n", "path": "nltk/translate/ribes_score.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Natural Language Toolkit: RIBES Score\n#\n# Copyright (C) 2001-2015 NLTK Project\n# Contributors: Katsuhito Sudoh, Liling Tan, Kasramvd, J.F.Sebastian, Mark Byers, ekhumoro, P. Ortiz\n# URL: <http://nltk.org/>\n# For license information, see LICENSE.TXT\n\"\"\" RIBES score implementation \"\"\"\nfrom __future__ import division\nfrom itertools import islice\nimport math\n\nfrom nltk.util import ngrams, choose\n\n\ndef ribes(references, hypothesis, alpha=0.25, beta=0.10):\n    \"\"\"\n    The RIBES (Rank-based Intuitive Bilingual Evaluation Score) from \n    Hideki Isozaki, Tsutomu Hirao, Kevin Duh, Katsuhito Sudoh and \n    Hajime Tsukada. 2010. \"Automatic Evaluation of Translation Quality for \n    Distant Language Pairs\". In Proceedings of EMNLP. \n    http://www.aclweb.org/anthology/D/D10/D10-1092.pdf \n    \n    The generic RIBES scores used in shared task, e.g. Workshop for \n    Asian Translation (WAT) uses the following RIBES calculations:\n    \n        RIBES = kendall_tau * (alpha**p1) * (beta**bp)\n    \n    Please note that this re-implementation differs from the official\n    RIBES implementation and though it emulates the results as describe\n    in the original paper, there are further optimization implemented \n    in the official RIBES script.\n    \n    Users are encouraged to use the official RIBES script instead of this \n    implementation when evaluating your machine translation system. Refer\n    to http://www.kecl.ntt.co.jp/icl/lirg/ribes/ for the official script.\n    \n    :param references: a list of reference sentences\n    :type reference: list(list(str))\n    :param hypothesis: a hypothesis sentence\n    :type hypothesis: list(str)\n    :param alpha: hyperparameter used as a prior for the unigram precision.\n    :type alpha: float\n    :param beta: hyperparameter used as a prior for the brevity penalty.\n    :type beta: float\n    :return: The best ribes score from one of the references.\n    :rtype: float\n    \"\"\"\n    best_ribes = -1.0\n    # Calculates RIBES for each reference and returns the best score.\n    for reference in references:\n        # Collects the *worder* from the ranked correlation alignments.\n        worder = word_rank_alignment(reference, hypothesis)\n        nkt = kendall_tau(worder)\n            \n        # Calculates the brevity penalty\n        bp = min(1.0, math.exp(1.0 - 1.0 * len(reference)/len(hypothesis)))\n        \n        # Calculates the unigram precision, *p1*\n        p1 = 1.0 * len(worder) / len(hypothesis)\n        \n        _ribes = nkt * (p1 ** alpha) *  (bp ** beta)\n        \n        if _ribes > best_ribes: # Keeps the best score.\n            best_ribes = _ribes\n        \n    return best_ribes\n\n\ndef position_of_ngram(ngram, sentence):\n    \"\"\"\n    This function returns the position of the first instance of the ngram \n    appearing in a sentence.\n    \n    Note that one could also use string as follows but the code is a little\n    convoluted with type casting back and forth:\n        \n        char_pos = ' '.join(sent)[:' '.join(sent).index(' '.join(ngram))]\n        word_pos = char_pos.count(' ')\n        \n    Another way to conceive this is:\n    \n        return next(i for i, ng in enumerate(ngrams(sentence, len(ngram))) \n                    if ng == ngram)\n                    \n    :param ngram: The ngram that needs to be searched\n    :type ngram: tuple\n    :param sentence: The list of tokens to search from.\n    :type sentence: list(str)\n    \"\"\"\n    # Iterates through the ngrams in sentence.\n    for i,sublist in enumerate(ngrams(sentence, len(ngram))):\n        # Returns the index of the word when ngram matches.\n        if ngram == sublist:\n            return i\n\n\ndef word_rank_alignment(reference, hypothesis, character_based=False):\n    \"\"\"    \n    This is the word rank alignment algorithm described in the paper to produce\n    the *worder* list, i.e. a list of word indices of the hypothesis word orders \n    w.r.t. the list of reference words.\n    \n    Below is (H0, R0) example from the Isozaki et al. 2010 paper, \n    note the examples are indexed from 1 but the results here are indexed from 0:\n    \n        >>> ref = str('he was interested in world history because he '\n        ... 'read the book').split()\n        >>> hyp = str('he read the book because he was interested in world '\n        ... 'history').split()\n        >>> word_rank_alignment(ref, hyp)\n        [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        \n    The (H1, R1) example from the paper, note the 0th index:\n    \n        >>> ref = 'John hit Bob yesterday'.split()\n        >>> hyp = 'Bob hit John yesterday'.split()\n        >>> word_rank_alignment(ref, hyp)\n        [2, 1, 0, 3]\n\n    Here is the (H2, R2) example from the paper, note the 0th index here too:\n    \n        >>> ref = 'the boy read the book'.split()\n        >>> hyp = 'the book was read by the boy'.split()\n        >>> word_rank_alignment(ref, hyp)\n        [3, 4, 2, 0, 1]\n        \n    :param reference: a reference sentence\n    :type reference: list(str)\n    :param hypothesis: a hypothesis sentence\n    :type hypothesis: list(str)\n    \"\"\"\n    worder = []\n    hyp_len = len(hypothesis)\n    # Stores a list of possible ngrams from the reference sentence.\n    # This is used for matching context window later in the algorithm.\n    ref_ngrams = []\n    hyp_ngrams = []\n    for n in range(1, len(reference)+1):\n        for ng in ngrams(reference, n):\n            ref_ngrams.append(ng)\n        for ng in ngrams(hypothesis, n):\n            hyp_ngrams.append(ng)\n    for i, h_word in enumerate(hypothesis):\n        # If word is not in the reference, continue.\n        if h_word not in reference:\n            continue\n        # If we can determine one-to-one word correspondence for unigrams that \n        # only appear once in both the reference and hypothesis.\n        elif hypothesis.count(h_word) == reference.count(h_word) == 1:\n            worder.append(reference.index(h_word))\n        else:\n            max_window_size = max(i, hyp_len-i+1)\n            for window in range(1, max_window_size):\n                if i+window < hyp_len: # If searching the right context is possible.\n                    # Retrieve the right context window.\n                    right_context_ngram = tuple(islice(hypothesis, i, i+window+1))\n                    num_times_in_ref = ref_ngrams.count(right_context_ngram)\n                    num_times_in_hyp = hyp_ngrams.count(right_context_ngram) \n                    # If ngram appears only once in both ref and hyp.\n                    if num_times_in_ref == num_times_in_hyp == 1:\n                        # Find the position of ngram that matched the reference.\n                        pos = position_of_ngram(right_context_ngram, reference)\n                        worder.append(pos)  # Add the positions of the ngram.\n                        break\n                if window <= i: # If searching the left context is possible.\n                    # Retrieve the left context window.\n                    left_context_ngram = tuple(islice(hypothesis, i-window, i+1))\n                    num_times_in_ref = ref_ngrams.count(left_context_ngram)\n                    num_times_in_hyp = hyp_ngrams.count(left_context_ngram)\n                    if num_times_in_ref == num_times_in_hyp == 1:\n                        # Find the position of ngram that matched the reference.\n                        pos = position_of_ngram(left_context_ngram, reference)\n                        # Add the positions of the ngram.\n                        worder.append(pos+ len(left_context_ngram) -1)  \n                        break\n    return worder\n\n    \ndef find_increasing_sequences(worder):\n    \"\"\"\n    Given the *worder* list, this function groups monotonic +1 sequences. \n    \n        >>> worder = [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        >>> list(find_increasing_sequences(worder))\n        [(7, 8, 9, 10), (0, 1, 2, 3, 4, 5)]\n    \n    :param worder: The worder list output from word_rank_alignment\n    :param type: list(int)\n    \"\"\"\n    items = iter(worder)\n    a, b = None, next(items, None)\n    result = [b]\n    while b is not None:\n        a, b = b, next(items, None)\n        if b is not None and a + 1 == b:\n            result.append(b)\n        else:\n            if len(result) > 1:\n                yield tuple(result)\n            result = [b]\n\n\ndef kendall_tau(worder, normalize=True):\n    \"\"\"\n    Calculates the Kendall's Tau correlation coefficient given the *worder*\n    list of word alignments from word_rank_alignment(), using the formula:\n    \n        tau = 2 * num_increasing_pairs / num_possible pairs -1\n    \n    Note that the no. of increasing pairs can be discontinuous in the *worder*\n    list and each each increasing sequence can be tabulated as choose(len(seq), 2) \n    no. of increasing pairs, e.g.\n    \n        >>> worder = [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        >>> number_possible_pairs = choose(len(worder), 2)\n        >>> round(kendall_tau(worder, normalize=False),3)\n        -0.236\n        >>> round(kendall_tau(worder),3)\n        0.382\n    \n    :param worder: The worder list output from word_rank_alignment\n    :type worder: list(int)\n    :param normalize: Flag to indicate normalization\n    :type normalize: boolean\n    :return: The Kendall's Tau correlation coefficient.\n    :rtype: float\n    \"\"\"\n    worder_len = len(worder)\n    # Extract the groups of increasing/monotonic sequences.\n    increasing_sequences = find_increasing_sequences(worder)\n    # Calculate no. of increasing_pairs in *worder* list.\n    num_increasing_pairs = sum(choose(len(seq),2) for seq in increasing_sequences) \n    # Calculate no. of possible pairs.\n    num_possible_pairs = choose(worder_len, 2)\n    # Kendall's Tau computation.\n    tau = 2 * num_increasing_pairs / num_possible_pairs -1\n    if normalize: # If normalized, the tau output falls between 0.0 to 1.0\n        return (tau + 1) /2\n    else: # Otherwise, the tau outputs falls between -1.0 to +1.0\n        return tau\n\n\ndef spearman_rho(worder, normalize=True):\n    \"\"\"\n    Calculates the Spearman's Rho correlation coefficient given the *worder* \n    list of word alignment from word_rank_alignment(), using the formula:\n    \n        rho = 1 - sum(d**2) / choose(len(worder)+1, 3)  \n        \n    Given that d is the sum of difference between the *worder* list of indices\n    and the original word indices from the reference sentence.\n    \n    Using the (H0,R0) and (H5, R5) example from the paper\n    \n        >>> worder =  [7, 8, 9, 10, 6, 0, 1, 2, 3, 4, 5]\n        >>> round(spearman_rho(worder, normalize=False), 3)\n        -0.591\n        >>> round(spearman_rho(worder), 3)\n        0.205\n    \n    :param worder: The worder list output from word_rank_alignment\n    :param type: list(int)\n    \"\"\"\n    worder_len = len(worder)\n    sum_d_square = sum((wi - i)**2 for wi, i in zip(worder, range(worder_len)))\n    rho = 1 - sum_d_square / choose(worder_len+1, 3)\n    \n    if normalize: # If normalized, the rho output falls between 0.0 to 1.0\n        return (rho + 1) /2\n    else: # Otherwise, the rho outputs falls between -1.0 to +1.0\n        return rho\n", "path": "nltk/translate/ribes_score.py"}]}