We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
BLEU score returns 1 (perfect match) instead of zero
Hi, taken from bleu implementation:

``` python
    @staticmethod
     def compute(candidate, references, weights):
        candidate = [c.lower() for c in candidate]
        references = [[r.lower() for r in reference] for reference in references]

        p_ns = (BLEU.modified_precision(candidate, references, i) for i, _ in enumerate(weights, start=1))
        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns) if p_n)

        bp = BLEU.brevity_penalty(candidate, references)
        return bp * math.exp(s)
```

This function incorrectly returns BLEU score 1 when the candidate has no alignment to any of the references. In this case, `p_ns` will be all zeros because there is no overlap for any n-grams, which will make `s` zero, which will return `1` at the end.

There should be a special case check for the case when there is zero alignment and return zero correctly. 


--- 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/align/bleu.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Natural Language Toolkit: BLEU
3 #
4 # Copyright (C) 2001-2013 NLTK Project
5 # Authors: Chin Yee Lee, Hengfeng Li, Ruxin Hou, Calvin Tanujaya Lim
6 # URL: <http://nltk.org/>
7 # For license information, see LICENSE.TXT
8 
9 from __future__ import division
10 
11 import math
12 
13 from nltk import word_tokenize
14 from nltk.compat import Counter
15 from nltk.util import ngrams
16 
17 
18 class BLEU(object):
19     """
20     This class implements the BLEU method, which is used to evaluate
21     the quality of machine translation. [1]
22 
23     Consider an example:
24 
25     >>> weights = [0.25, 0.25, 0.25, 0.25]
26     >>> candidate1 = ['It', 'is', 'a', 'guide', 'to', 'action', 'which',
27     ...               'ensures', 'that', 'the', 'military', 'always',
28     ...               'obeys', 'the', 'commands', 'of', 'the', 'party']
29 
30     >>> candidate2 = ['It', 'is', 'to', 'insure', 'the', 'troops',
31     ...               'forever', 'hearing', 'the', 'activity', 'guidebook',
32     ...               'that', 'party', 'direct']
33 
34     >>> reference1 = ['It', 'is', 'a', 'guide', 'to', 'action', 'that',
35     ...               'ensures', 'that', 'the', 'military', 'will', 'forever',
36     ...               'heed', 'Party', 'commands']
37 
38     >>> reference2 = ['It', 'is', 'the', 'guiding', 'principle', 'which',
39     ...               'guarantees', 'the', 'military', 'forces', 'always',
40     ...               'being', 'under', 'the', 'command', 'of', 'the',
41     ...               'Party']
42 
43     >>> reference3 = ['It', 'is', 'the', 'practical', 'guide', 'for', 'the',
44     ...               'army', 'always', 'to', 'heed', 'the', 'directions',
45     ...               'of', 'the', 'party']
46 
47     The BLEU method mainly consists of two parts:
48 
49     Part 1 - modified n-gram precision
50 
51     The normal precision method may lead to some wrong translations with
52     high-precision, e.g., the translation, in which a word of reference
53     repeats several times, has very high precision. So in the modified
54     n-gram precision, a reference word will be considered exhausted after
55     a matching candidate word is identified.
56 
57     Unigrams:
58 
59     >>> BLEU.modified_precision(
60     ...    candidate1,
61     ...    [reference1, reference2, reference3],
62     ...    n=1,
63     ... )
64     0.94...
65 
66     >>> BLEU.modified_precision(
67     ...    candidate2,
68     ...    [reference1, reference2, reference3],
69     ...    n=1,
70     ... )
71     0.57...
72 
73     Bigrmas:
74 
75     >>> BLEU.modified_precision(
76     ...    candidate1,
77     ...    [reference1, reference2, reference3],
78     ...    n=2,
79     ... )
80     0.58...
81 
82     >>> BLEU.modified_precision(
83     ...    candidate2,
84     ...    [reference1, reference2, reference3],
85     ...    n=2,
86     ... )
87     0.07...
88 
89 
90     Part 2 - brevity penalty
91 
92     As the modified n-gram precision still has the problem from the short
93     length sentence, brevity penalty is used to modify the overall BLEU
94     score according to length.
95 
96     >>> BLEU.compute(candidate1, [reference1, reference2, reference3], weights)
97     0.504...
98 
99     >>> BLEU.compute(candidate2, [reference1, reference2, reference3], weights)
100     0.457...
101 
102     2. Test with two corpus that one is a reference and another is
103     an output from translation system:
104 
105     >>> weights = [0.25, 0.25, 0.25, 0.25]
106     >>> ref_file = open('newstest2012-ref.en')  # doctest: +SKIP
107     >>> candidate_file = open('newstest2012.fr-en.cmu-avenue')  # doctest: +SKIP
108 
109     >>> total = 0.0
110     >>> count = 0
111 
112     >>> for candi_raw in candidate_file:  # doctest: +SKIP
113     ...		ref_raw = ref_file.readline()
114     ...		ref_tokens = word_tokenize(ref_raw)
115     ...		candi_tokens = word_tokenize(candi_raw)
116     ...		total = BLEU.compute(candi_tokens, [ref_tokens], weights)
117     ...		count += 1
118 
119     >>> total / count  # doctest: +SKIP
120     2.787504437460048e-05
121 
122     [1] Papineni, Kishore, et al. "BLEU: a method for automatic evaluation of
123     machine translation." Proceedings of the 40th annual meeting on
124     association for computational linguistics. Association for Computational
125     Linguistics, 2002.
126 
127     """
128 
129     @staticmethod
130     def compute(candidate, references, weights):
131         candidate = [c.lower() for c in candidate]
132         references = [[r.lower() for r in reference] for reference in references]
133 
134         p_ns = (BLEU.modified_precision(candidate, references, i) for i, _ in enumerate(weights, start=1))
135         s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns) if p_n)
136 
137         bp = BLEU.brevity_penalty(candidate, references)
138         return bp * math.exp(s)
139 
140     @staticmethod
141     def modified_precision(candidate, references, n):
142         """ Calculate modified ngram precision.
143 
144         >>> BLEU.modified_precision(
145         ...    'the the the the the the the'.split(),
146         ...    ['the cat is on the mat'.split(), 'there is a cat on the mat'.split()],
147         ...    n=1,
148         ... )
149         0.28...
150 
151         >>> BLEU.modified_precision(
152         ...    'the the the the the the the'.split(),
153         ...    ['the cat is on the mat'.split(), 'there is a cat on the mat'.split()],
154         ...    n=2,
155         ... )
156         0.0
157 
158         >>> BLEU.modified_precision(
159         ...    'of the'.split(),
160         ...    [
161         ...        'It is a guide to action that ensures that the military will forever heed Party commands.'.split(),
162         ...        'It is the guiding principle which guarantees the military forces always being under the command of the Party.'.split(),
163         ...        'It is the practical guide for the army always to heed the directions of the party'.split(),
164         ...    ],
165         ...    n=1,
166         ... )
167         1.0
168 
169         >>> BLEU.modified_precision(
170         ...    'of the'.split(),
171         ...    [
172         ...        'It is a guide to action that ensures that the military will forever heed Party commands.'.split(),
173         ...        'It is the guiding principle which guarantees the military forces always being under the command of the Party.'.split(),
174         ...        'It is the practical guide for the army always to heed the directions of the party'.split(),
175         ...    ],
176         ...    n=2,
177         ... )
178         1.0
179 
180         """
181         counts = Counter(ngrams(candidate, n))
182 
183         if not counts:
184             return 0
185 
186         max_counts = {}
187         for reference in references:
188             reference_counts = Counter(ngrams(reference, n))
189             for ngram in counts:
190                 max_counts[ngram] = max(max_counts.get(ngram, 0), reference_counts[ngram])
191 
192         clipped_counts = dict((ngram, min(count, max_counts[ngram])) for ngram, count in counts.items())
193 
194         return sum(clipped_counts.values()) / sum(counts.values())
195 
196     @staticmethod
197     def brevity_penalty(candidate, references):
198         c = len(candidate)
199         r = min(abs(len(r) - c) for r in references)
200 
201         if c > r:
202             return 1
203         else:
204             return math.exp(1 - r / c)
205 
206 # run doctests
207 if __name__ == "__main__":
208     import doctest
209     doctest.testmod()
210
```
--- 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/align/bleu.py b/nltk/align/bleu.py
--- a/nltk/align/bleu.py
+++ b/nltk/align/bleu.py
@@ -132,7 +132,13 @@
         references = [[r.lower() for r in reference] for reference in references]
 
         p_ns = (BLEU.modified_precision(candidate, references, i) for i, _ in enumerate(weights, start=1))
-        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns) if p_n)
+        p_ns_nonzero = list(filter(None, p_ns))
+
+        if not p_ns_nonzero:
+            # There is zero aliment, so the score is 0
+            return 0
+
+        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns_nonzero))
 
         bp = BLEU.brevity_penalty(candidate, references)
         return bp * math.exp(s)

{"golden_diff": "diff --git a/nltk/align/bleu.py b/nltk/align/bleu.py\n--- a/nltk/align/bleu.py\n+++ b/nltk/align/bleu.py\n@@ -132,7 +132,13 @@\n         references = [[r.lower() for r in reference] for reference in references]\n \n         p_ns = (BLEU.modified_precision(candidate, references, i) for i, _ in enumerate(weights, start=1))\n-        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns) if p_n)\n+        p_ns_nonzero = list(filter(None, p_ns))\n+\n+        if not p_ns_nonzero:\n+            # There is zero aliment, so the score is 0\n+            return 0\n+\n+        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns_nonzero))\n \n         bp = BLEU.brevity_penalty(candidate, references)\n         return bp * math.exp(s)\n", "issue": "BLEU score returns 1 (perfect match) instead of zero\nHi, taken from bleu implementation:\n\n``` python\n    @staticmethod\n     def compute(candidate, references, weights):\n        candidate = [c.lower() for c in candidate]\n        references = [[r.lower() for r in reference] for reference in references]\n\n        p_ns = (BLEU.modified_precision(candidate, references, i) for i, _ in enumerate(weights, start=1))\n        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns) if p_n)\n\n        bp = BLEU.brevity_penalty(candidate, references)\n        return bp * math.exp(s)\n```\n\nThis function incorrectly returns BLEU score 1 when the candidate has no alignment to any of the references. In this case, `p_ns` will be all zeros because there is no overlap for any n-grams, which will make `s` zero, which will return `1` at the end.\n\nThere should be a special case check for the case when there is zero alignment and return zero correctly. \n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Natural Language Toolkit: BLEU\n#\n# Copyright (C) 2001-2013 NLTK Project\n# Authors: Chin Yee Lee, Hengfeng Li, Ruxin Hou, Calvin Tanujaya Lim\n# URL: <http://nltk.org/>\n# For license information, see LICENSE.TXT\n\nfrom __future__ import division\n\nimport math\n\nfrom nltk import word_tokenize\nfrom nltk.compat import Counter\nfrom nltk.util import ngrams\n\n\nclass BLEU(object):\n    \"\"\"\n    This class implements the BLEU method, which is used to evaluate\n    the quality of machine translation. [1]\n\n    Consider an example:\n\n    >>> weights = [0.25, 0.25, 0.25, 0.25]\n    >>> candidate1 = ['It', 'is', 'a', 'guide', 'to', 'action', 'which',\n    ...               'ensures', 'that', 'the', 'military', 'always',\n    ...               'obeys', 'the', 'commands', 'of', 'the', 'party']\n\n    >>> candidate2 = ['It', 'is', 'to', 'insure', 'the', 'troops',\n    ...               'forever', 'hearing', 'the', 'activity', 'guidebook',\n    ...               'that', 'party', 'direct']\n\n    >>> reference1 = ['It', 'is', 'a', 'guide', 'to', 'action', 'that',\n    ...               'ensures', 'that', 'the', 'military', 'will', 'forever',\n    ...               'heed', 'Party', 'commands']\n\n    >>> reference2 = ['It', 'is', 'the', 'guiding', 'principle', 'which',\n    ...               'guarantees', 'the', 'military', 'forces', 'always',\n    ...               'being', 'under', 'the', 'command', 'of', 'the',\n    ...               'Party']\n\n    >>> reference3 = ['It', 'is', 'the', 'practical', 'guide', 'for', 'the',\n    ...               'army', 'always', 'to', 'heed', 'the', 'directions',\n    ...               'of', 'the', 'party']\n\n    The BLEU method mainly consists of two parts:\n\n    Part 1 - modified n-gram precision\n\n    The normal precision method may lead to some wrong translations with\n    high-precision, e.g., the translation, in which a word of reference\n    repeats several times, has very high precision. So in the modified\n    n-gram precision, a reference word will be considered exhausted after\n    a matching candidate word is identified.\n\n    Unigrams:\n\n    >>> BLEU.modified_precision(\n    ...    candidate1,\n    ...    [reference1, reference2, reference3],\n    ...    n=1,\n    ... )\n    0.94...\n\n    >>> BLEU.modified_precision(\n    ...    candidate2,\n    ...    [reference1, reference2, reference3],\n    ...    n=1,\n    ... )\n    0.57...\n\n    Bigrmas:\n\n    >>> BLEU.modified_precision(\n    ...    candidate1,\n    ...    [reference1, reference2, reference3],\n    ...    n=2,\n    ... )\n    0.58...\n\n    >>> BLEU.modified_precision(\n    ...    candidate2,\n    ...    [reference1, reference2, reference3],\n    ...    n=2,\n    ... )\n    0.07...\n\n\n    Part 2 - brevity penalty\n\n    As the modified n-gram precision still has the problem from the short\n    length sentence, brevity penalty is used to modify the overall BLEU\n    score according to length.\n\n    >>> BLEU.compute(candidate1, [reference1, reference2, reference3], weights)\n    0.504...\n\n    >>> BLEU.compute(candidate2, [reference1, reference2, reference3], weights)\n    0.457...\n\n    2. Test with two corpus that one is a reference and another is\n    an output from translation system:\n\n    >>> weights = [0.25, 0.25, 0.25, 0.25]\n    >>> ref_file = open('newstest2012-ref.en')  # doctest: +SKIP\n    >>> candidate_file = open('newstest2012.fr-en.cmu-avenue')  # doctest: +SKIP\n\n    >>> total = 0.0\n    >>> count = 0\n\n    >>> for candi_raw in candidate_file:  # doctest: +SKIP\n    ...\t\tref_raw = ref_file.readline()\n    ...\t\tref_tokens = word_tokenize(ref_raw)\n    ...\t\tcandi_tokens = word_tokenize(candi_raw)\n    ...\t\ttotal = BLEU.compute(candi_tokens, [ref_tokens], weights)\n    ...\t\tcount += 1\n\n    >>> total / count  # doctest: +SKIP\n    2.787504437460048e-05\n\n    [1] Papineni, Kishore, et al. \"BLEU: a method for automatic evaluation of\n    machine translation.\" Proceedings of the 40th annual meeting on\n    association for computational linguistics. Association for Computational\n    Linguistics, 2002.\n\n    \"\"\"\n\n    @staticmethod\n    def compute(candidate, references, weights):\n        candidate = [c.lower() for c in candidate]\n        references = [[r.lower() for r in reference] for reference in references]\n\n        p_ns = (BLEU.modified_precision(candidate, references, i) for i, _ in enumerate(weights, start=1))\n        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns) if p_n)\n\n        bp = BLEU.brevity_penalty(candidate, references)\n        return bp * math.exp(s)\n\n    @staticmethod\n    def modified_precision(candidate, references, n):\n        \"\"\" Calculate modified ngram precision.\n\n        >>> BLEU.modified_precision(\n        ...    'the the the the the the the'.split(),\n        ...    ['the cat is on the mat'.split(), 'there is a cat on the mat'.split()],\n        ...    n=1,\n        ... )\n        0.28...\n\n        >>> BLEU.modified_precision(\n        ...    'the the the the the the the'.split(),\n        ...    ['the cat is on the mat'.split(), 'there is a cat on the mat'.split()],\n        ...    n=2,\n        ... )\n        0.0\n\n        >>> BLEU.modified_precision(\n        ...    'of the'.split(),\n        ...    [\n        ...        'It is a guide to action that ensures that the military will forever heed Party commands.'.split(),\n        ...        'It is the guiding principle which guarantees the military forces always being under the command of the Party.'.split(),\n        ...        'It is the practical guide for the army always to heed the directions of the party'.split(),\n        ...    ],\n        ...    n=1,\n        ... )\n        1.0\n\n        >>> BLEU.modified_precision(\n        ...    'of the'.split(),\n        ...    [\n        ...        'It is a guide to action that ensures that the military will forever heed Party commands.'.split(),\n        ...        'It is the guiding principle which guarantees the military forces always being under the command of the Party.'.split(),\n        ...        'It is the practical guide for the army always to heed the directions of the party'.split(),\n        ...    ],\n        ...    n=2,\n        ... )\n        1.0\n\n        \"\"\"\n        counts = Counter(ngrams(candidate, n))\n\n        if not counts:\n            return 0\n\n        max_counts = {}\n        for reference in references:\n            reference_counts = Counter(ngrams(reference, n))\n            for ngram in counts:\n                max_counts[ngram] = max(max_counts.get(ngram, 0), reference_counts[ngram])\n\n        clipped_counts = dict((ngram, min(count, max_counts[ngram])) for ngram, count in counts.items())\n\n        return sum(clipped_counts.values()) / sum(counts.values())\n\n    @staticmethod\n    def brevity_penalty(candidate, references):\n        c = len(candidate)\n        r = min(abs(len(r) - c) for r in references)\n\n        if c > r:\n            return 1\n        else:\n            return math.exp(1 - r / c)\n\n# run doctests\nif __name__ == \"__main__\":\n    import doctest\n    doctest.testmod()\n", "path": "nltk/align/bleu.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Natural Language Toolkit: BLEU\n#\n# Copyright (C) 2001-2013 NLTK Project\n# Authors: Chin Yee Lee, Hengfeng Li, Ruxin Hou, Calvin Tanujaya Lim\n# URL: <http://nltk.org/>\n# For license information, see LICENSE.TXT\n\nfrom __future__ import division\n\nimport math\n\nfrom nltk import word_tokenize\nfrom nltk.compat import Counter\nfrom nltk.util import ngrams\n\n\nclass BLEU(object):\n    \"\"\"\n    This class implements the BLEU method, which is used to evaluate\n    the quality of machine translation. [1]\n\n    Consider an example:\n\n    >>> weights = [0.25, 0.25, 0.25, 0.25]\n    >>> candidate1 = ['It', 'is', 'a', 'guide', 'to', 'action', 'which',\n    ...               'ensures', 'that', 'the', 'military', 'always',\n    ...               'obeys', 'the', 'commands', 'of', 'the', 'party']\n\n    >>> candidate2 = ['It', 'is', 'to', 'insure', 'the', 'troops',\n    ...               'forever', 'hearing', 'the', 'activity', 'guidebook',\n    ...               'that', 'party', 'direct']\n\n    >>> reference1 = ['It', 'is', 'a', 'guide', 'to', 'action', 'that',\n    ...               'ensures', 'that', 'the', 'military', 'will', 'forever',\n    ...               'heed', 'Party', 'commands']\n\n    >>> reference2 = ['It', 'is', 'the', 'guiding', 'principle', 'which',\n    ...               'guarantees', 'the', 'military', 'forces', 'always',\n    ...               'being', 'under', 'the', 'command', 'of', 'the',\n    ...               'Party']\n\n    >>> reference3 = ['It', 'is', 'the', 'practical', 'guide', 'for', 'the',\n    ...               'army', 'always', 'to', 'heed', 'the', 'directions',\n    ...               'of', 'the', 'party']\n\n    The BLEU method mainly consists of two parts:\n\n    Part 1 - modified n-gram precision\n\n    The normal precision method may lead to some wrong translations with\n    high-precision, e.g., the translation, in which a word of reference\n    repeats several times, has very high precision. So in the modified\n    n-gram precision, a reference word will be considered exhausted after\n    a matching candidate word is identified.\n\n    Unigrams:\n\n    >>> BLEU.modified_precision(\n    ...    candidate1,\n    ...    [reference1, reference2, reference3],\n    ...    n=1,\n    ... )\n    0.94...\n\n    >>> BLEU.modified_precision(\n    ...    candidate2,\n    ...    [reference1, reference2, reference3],\n    ...    n=1,\n    ... )\n    0.57...\n\n    Bigrmas:\n\n    >>> BLEU.modified_precision(\n    ...    candidate1,\n    ...    [reference1, reference2, reference3],\n    ...    n=2,\n    ... )\n    0.58...\n\n    >>> BLEU.modified_precision(\n    ...    candidate2,\n    ...    [reference1, reference2, reference3],\n    ...    n=2,\n    ... )\n    0.07...\n\n\n    Part 2 - brevity penalty\n\n    As the modified n-gram precision still has the problem from the short\n    length sentence, brevity penalty is used to modify the overall BLEU\n    score according to length.\n\n    >>> BLEU.compute(candidate1, [reference1, reference2, reference3], weights)\n    0.504...\n\n    >>> BLEU.compute(candidate2, [reference1, reference2, reference3], weights)\n    0.457...\n\n    2. Test with two corpus that one is a reference and another is\n    an output from translation system:\n\n    >>> weights = [0.25, 0.25, 0.25, 0.25]\n    >>> ref_file = open('newstest2012-ref.en')  # doctest: +SKIP\n    >>> candidate_file = open('newstest2012.fr-en.cmu-avenue')  # doctest: +SKIP\n\n    >>> total = 0.0\n    >>> count = 0\n\n    >>> for candi_raw in candidate_file:  # doctest: +SKIP\n    ...\t\tref_raw = ref_file.readline()\n    ...\t\tref_tokens = word_tokenize(ref_raw)\n    ...\t\tcandi_tokens = word_tokenize(candi_raw)\n    ...\t\ttotal = BLEU.compute(candi_tokens, [ref_tokens], weights)\n    ...\t\tcount += 1\n\n    >>> total / count  # doctest: +SKIP\n    2.787504437460048e-05\n\n    [1] Papineni, Kishore, et al. \"BLEU: a method for automatic evaluation of\n    machine translation.\" Proceedings of the 40th annual meeting on\n    association for computational linguistics. Association for Computational\n    Linguistics, 2002.\n\n    \"\"\"\n\n    @staticmethod\n    def compute(candidate, references, weights):\n        candidate = [c.lower() for c in candidate]\n        references = [[r.lower() for r in reference] for reference in references]\n\n        p_ns = (BLEU.modified_precision(candidate, references, i) for i, _ in enumerate(weights, start=1))\n        p_ns_nonzero = list(filter(None, p_ns))\n\n        if not p_ns_nonzero:\n            # There is zero aliment, so the score is 0\n            return 0\n\n        s = math.fsum(w * math.log(p_n) for w, p_n in zip(weights, p_ns_nonzero))\n\n        bp = BLEU.brevity_penalty(candidate, references)\n        return bp * math.exp(s)\n\n    @staticmethod\n    def modified_precision(candidate, references, n):\n        \"\"\" Calculate modified ngram precision.\n\n        >>> BLEU.modified_precision(\n        ...    'the the the the the the the'.split(),\n        ...    ['the cat is on the mat'.split(), 'there is a cat on the mat'.split()],\n        ...    n=1,\n        ... )\n        0.28...\n\n        >>> BLEU.modified_precision(\n        ...    'the the the the the the the'.split(),\n        ...    ['the cat is on the mat'.split(), 'there is a cat on the mat'.split()],\n        ...    n=2,\n        ... )\n        0.0\n\n        >>> BLEU.modified_precision(\n        ...    'of the'.split(),\n        ...    [\n        ...        'It is a guide to action that ensures that the military will forever heed Party commands.'.split(),\n        ...        'It is the guiding principle which guarantees the military forces always being under the command of the Party.'.split(),\n        ...        'It is the practical guide for the army always to heed the directions of the party'.split(),\n        ...    ],\n        ...    n=1,\n        ... )\n        1.0\n\n        >>> BLEU.modified_precision(\n        ...    'of the'.split(),\n        ...    [\n        ...        'It is a guide to action that ensures that the military will forever heed Party commands.'.split(),\n        ...        'It is the guiding principle which guarantees the military forces always being under the command of the Party.'.split(),\n        ...        'It is the practical guide for the army always to heed the directions of the party'.split(),\n        ...    ],\n        ...    n=2,\n        ... )\n        1.0\n\n        \"\"\"\n        counts = Counter(ngrams(candidate, n))\n\n        if not counts:\n            return 0\n\n        max_counts = {}\n        for reference in references:\n            reference_counts = Counter(ngrams(reference, n))\n            for ngram in counts:\n                max_counts[ngram] = max(max_counts.get(ngram, 0), reference_counts[ngram])\n\n        clipped_counts = dict((ngram, min(count, max_counts[ngram])) for ngram, count in counts.items())\n\n        return sum(clipped_counts.values()) / sum(counts.values())\n\n    @staticmethod\n    def brevity_penalty(candidate, references):\n        c = len(candidate)\n        r = min(abs(len(r) - c) for r in references)\n\n        if c > r:\n            return 1\n        else:\n            return math.exp(1 - r / c)\n\n# run doctests\nif __name__ == \"__main__\":\n    import doctest\n    doctest.testmod()\n", "path": "nltk/align/bleu.py"}]}