natural language toolkit bleu score c 20012023 nltk project s chin yee lee hengfeng li ruxin hou calvin tanujaya lim contributors bjrn mattsson dmitrijs milajevs liling tan url https www nltk org for license information see license txt bleu score implementation import math import sys import warnings from collections import counter from fractions import fraction from nltk util import ngrams def sentencebleu references hypothesis weights0 25 0 25 0 25 0 25 smoothingfunctionnone autoreweighfalse return corpusbleu references hypothesis weights smoothingfunction autoreweigh def corpusbleu listofreferences hypotheses weights0 25 0 25 0 25 0 25 smoothingfunctionnone autoreweighfalse before proceeding to compute bleu perform sanity checks pnumerators counter key ngram order and value no of ngram matches pdenominators counter key ngram order and value no of ngram in ref hyplengths reflengths 0 0 assert lenlistofreferences lenhypotheses the number of hypotheses and their references should be the same try weights00 except weights weights maxweightlength maxlenweight for weight in weights iterate through each hypothesis and their corresponding references for references hypothesis in ziplistofreferences hypotheses for each order of ngram calculate the numerator and denominator for the corpuslevel modified precision for i in range1 maxweightlength 1 pi modifiedprecisionreferences hypothesis i pnumeratorsi pi numerator pdenominatorsi pi denominator calculate the hypothesis length and the closest reference length adds them to the corpuslevel hypothesis and reference counts hyplen lenhypothesis hyplengths hyplen reflengths closestreflengthreferences hyplen calculate corpuslevel brevity penalty bp brevitypenaltyreflengths hyplengths collects the various precision values for the different ngram orders pn fractionpnumeratorsi pdenominatorsi normalizefalse for i in range1 maxweightlength 1 returns 0 if there s no matching ngrams we only need to check for pnumerators1 0 since if there s no unigrams there won t be any higher order ngrams if pnumerators1 0 return 0 if lenweights 1 else 0 lenweights if there s no smoothing set use method0 from smoothinfunction class if not smoothingfunction smoothingfunction smoothingfunction method0 smoothen the modified precision note smoothingfunction may convert values into floats it tries to retain the fraction object as much as the smoothing method allows pn smoothingfunction pn referencesreferences hypothesishypothesis hyplenhyplengths bleuscores for weight in weights uniformly reweighting based on maximum hypothesis lengths if largest order of ngrams 4 and weights is set at default if autoreweigh if hyplengths 4 and weight 0 25 0 25 0 25 0 25 weight 1 hyplengths hyplengths s wi math logpi for wi pi in zipweight pn if pi 0 s bp math expmath fsums bleuscores appends return bleuscores0 if lenweights 1 else bleuscores def modifiedprecisionreferences hypothesis n extracts all ngrams in hypothesis set an empty counter if hypothesis is empty counts counterngramshypothesis n if lenhypothesis n else counter extract a union of references counts maxcounts reduceor counterngramsref n for ref in references maxcounts for reference in references referencecounts counterngramsreference n if lenreference n else counter for ngram in counts maxcountsngram maxmaxcounts getngram 0 referencecountsngram assigns the intersection between hypothesis and references counts clippedcounts ngram mincount maxcountsngram for ngram count in counts items numerator sumclippedcounts values ensures that denominator is minimum 1 to avoid zerodivisionerror usually this happens when the ngram order is lenreference denominator max1 sumcounts values return fractionnumerator denominator normalizefalse def closestreflengthreferences hyplen reflens lenreference for reference in references closestreflen min reflens keylambda reflen absreflen hyplen reflen return closestreflen def brevitypenaltyclosestreflen hyplen if hyplen closestreflen return 1 if hypothesis is empty brevity penalty 0 should result in bleu 0 0 elif hyplen 0 return 0 else return math exp1 closestreflen hyplen class smoothingfunction def initself epsilon0 1 alpha5 k5 self epsilon epsilon self alpha alpha self k k def method0self pn args kwargs pnnew for i pi in enumeratepn if pi numerator 0 pnnew appendpi else msg str nthe hypothesis contains 0 counts of gram overlaps n therefore the bleu score evaluates to 0 independently ofn how many ngram overlaps of lower order it contains n consider using lower ngram order or use smoothingfunction formati 1 warnings warnmsg when numerator0 where denonminator0 or 0 the result for the precision score should be equal to 0 or undefined due to bleu geometric mean computation in logarithm space we we need to take the return sys floatinfo min such that math logsys floatinfo min returns a 0 precision score pnnew appendsys floatinfo min return pnnew def method1self pn args kwargs return pi numerator self epsilon pi denominator if pi numerator 0 else pi for pi in pn def method2self pn args kwargs return fractionpni numerator 1 pni denominator 1 normalizefalse if i 0 else pn0 for i in rangelenpn def method3self pn args kwargs incvnt 1 from the mtevalv13a pl it s referred to as k for i pi in enumeratepn if pi numerator 0 pni 1 2incvnt pi denominator incvnt 1 return pn def method4self pn references hypothesis hyplennone args kwargs incvnt 1 hyplen hyplen if hyplen else lenhypothesis for i pi in enumeratepn if pi numerator 0 and hyplen 1 incvnt i 1 self k math log hyplen note that this k is different from the k from nist pni incvnt pi denominator numerator 1 2incvnt self k math loghyplen pni numerator pi denominator incvnt 1 return pn def method5self pn references hypothesis hyplennone args kwargs hyplen hyplen if hyplen else lenhypothesis m requires an precision value for an addition ngram order pnplus1 pn modifiedprecisionreferences hypothesis 5 m1 pn0 1 for i pi in enumeratepn pni mi 1 pi pnplus1i 1 3 mi pni return pn def method6self pn references hypothesis hyplennone args kwargs hyplen hyplen if hyplen else lenhypothesis this smoothing only works when p1 and p2 is nonzero raise an error with an appropriate message when the input is too short to use this smoothing technique assert pn2 this smoothing method requires nonzero precision for bigrams for i pi in enumeratepn if i in 0 1 skips the first 2 orders of ngrams continue else pi0 0 if pni 2 0 else pni 1 2 pni 2 no of ngrams in translation that matches the reference m pi numerator no of ngrams in translation l sum1 for in ngramshypothesis i 1 calculates the interpolated precision pni m self alpha pi0 l self alpha return pn def method7self pn references hypothesis hyplennone args kwargs hyplen hyplen if hyplen else lenhypothesis pn self method4pn references hypothesis hyplen pn self method5pn references hypothesis hyplen return pn natural language toolkit bleu score c 2001 2023 nltk project s chin yee lee hengfeng li ruxin hou calvin tanujaya lim contributors björn mattsson dmitrijs milajevs liling tan url https www nltk org for license information see license txt bleu score implementation calculate bleu score bilingual evaluation understudy from papineni kishore salim roukos todd ward and wei jing zhu 2002 bleu a method for automatic evaluation of machine translation in proceedings of acl https www aclweb org anthology p02 1040 pdf hypothesis1 it is a guide to action which ensures that the military always obeys the commands of the party hypothesis2 it is to insure the troops forever hearing the activity guidebook that party direct reference1 it is a guide to action that ensures that the military will forever heed party commands reference2 it is the guiding principle which guarantees the military forces always being under the command of the party reference3 it is the practical guide for the army always to heed the directions of the party sentence_bleu reference1 reference2 reference3 hypothesis1 doctest ellipsis 0 5045 if there is no ngrams overlap for any order of n grams bleu returns the value 0 this is because the precision for the order of n grams without overlap is 0 and the geometric mean in the final bleu score computation multiplies the 0 with the precision of other n grams this results in 0 independently of the precision of the other n gram orders the following example has zero 3 gram and 4 gram overlaps round sentence_bleu reference1 reference2 reference3 hypothesis2 4 doctest ellipsis 0 0 to avoid this harsh behaviour when no ngram overlaps are found a smoothing function can be used chencherry smoothingfunction sentence_bleu reference1 reference2 reference3 hypothesis2 smoothing_function chencherry method1 doctest ellipsis 0 0370 the default bleu calculates a score for up to 4 grams using uniform weights this is called bleu 4 to evaluate your translations with higher lower order ngrams use customized weights e g when accounting for up to 5 grams with uniform weights this is called bleu 5 use weights 1 5 1 5 1 5 1 5 1 5 sentence_bleu reference1 reference2 reference3 hypothesis1 weights doctest ellipsis 0 3920 multiple bleu scores can be computed at once by supplying a list of weights e g for computing bleu 2 bleu 3 and bleu 4 in one computation use weights 1 2 1 2 1 3 1 3 1 3 1 4 1 4 1 4 1 4 sentence_bleu reference1 reference2 reference3 hypothesis1 weights doctest ellipsis 0 7453 0 6240 0 5045 param references reference sentences type references list list str param hypothesis a hypothesis sentence type hypothesis list str param weights weights for unigrams bigrams trigrams and so on one or a list of weights type weights tuple float list tuple float param smoothing_function type smoothing_function smoothingfunction param auto_reweigh option to re normalize the weights uniformly type auto_reweigh bool return the sentence level bleu score returns a list if multiple weights were supplied rtype float list float calculate a single corpus level bleu score aka system level bleu for all the hypotheses and their respective references instead of averaging the sentence level bleu scores i e macro average precision the original bleu metric papineni et al 2002 accounts for the micro average precision i e summing the numerators and denominators for each hypothesis reference s pairs before the division hyp1 it is a guide to action which ensures that the military always obeys the commands of the party ref1a it is a guide to action that ensures that the military will forever heed party commands ref1b it is the guiding principle which guarantees the military forces always being under the command of the party ref1c it is the practical guide for the army always to heed the directions of the party hyp2 he read the book because he was interested in world history ref2a he was interested in world history because he read the book list_of_references ref1a ref1b ref1c ref2a hypotheses hyp1 hyp2 corpus_bleu list_of_references hypotheses doctest ellipsis 0 5920 the example below show that corpus_bleu is different from averaging sentence_bleu for hypotheses score1 sentence_bleu ref1a ref1b ref1c hyp1 score2 sentence_bleu ref2a hyp2 score1 score2 2 doctest ellipsis 0 6223 custom weights may be supplied to fine tune the bleu score further a tuple of float weights for unigrams bigrams trigrams and so on can be given weights 0 1 0 3 0 5 0 1 corpus_bleu list_of_references hypotheses weights weights doctest ellipsis 0 5818 this particular weight gave extra value to trigrams furthermore multiple weights can be given resulting in multiple bleu scores weights 0 5 0 5 0 333 0 333 0 334 0 25 0 25 0 25 0 25 0 2 0 2 0 2 0 2 0 2 corpus_bleu list_of_references hypotheses weights weights doctest ellipsis 0 8242 0 7067 0 5920 0 4719 param list_of_references a corpus of lists of reference sentences w r t hypotheses type list_of_references list list list str param hypotheses a list of hypothesis sentences type hypotheses list list str param weights weights for unigrams bigrams trigrams and so on one or a list of weights type weights tuple float list tuple float param smoothing_function type smoothing_function smoothingfunction param auto_reweigh option to re normalize the weights uniformly type auto_reweigh bool return the corpus level bleu score rtype float before proceeding to compute bleu perform sanity checks key ngram order and value no of ngram matches key ngram order and value no of ngram in ref iterate through each hypothesis and their corresponding references for each order of ngram calculate the numerator and denominator for the corpus level modified precision calculate the hypothesis length and the closest reference length adds them to the corpus level hypothesis and reference counts calculate corpus level brevity penalty collects the various precision values for the different ngram orders returns 0 if there s no matching n grams we only need to check for p_numerators 1 0 since if there s no unigrams there won t be any higher order ngrams if there s no smoothing set use method0 from smoothinfunction class smoothen the modified precision note smoothing_function may convert values into floats it tries to retain the fraction object as much as the smoothing method allows uniformly re weighting based on maximum hypothesis lengths if largest order of n grams 4 and weights is set at default calculate modified ngram precision the normal precision method may lead to some wrong translations with high precision e g the translation in which a word of reference repeats several times has very high precision this function only returns the fraction object that contains the numerator and denominator necessary to calculate the corpus level precision to calculate the modified precision for a single pair of hypothesis and references cast the fraction object into a float the famous the the the example shows that you can get bleu precision by duplicating high frequency words reference1 the cat is on the mat split reference2 there is a cat on the mat split hypothesis1 the the the the the the the split references reference1 reference2 float modified_precision references hypothesis1 n 1 doctest ellipsis 0 2857 in the modified n gram precision a reference word will be considered exhausted after a matching hypothesis word is identified e g reference1 it is a guide to action that ensures that the military will forever heed party commands reference2 it is the guiding principle which guarantees the military forces always being under the command of the party reference3 it is the practical guide for the army always to heed the directions of the party hypothesis of the split references reference1 reference2 reference3 float modified_precision references hypothesis n 1 1 0 float modified_precision references hypothesis n 2 1 0 an example of a normal machine translation hypothesis hypothesis1 it is a guide to action which ensures that the military always obeys the commands of the party hypothesis2 it is to insure the troops forever hearing the activity guidebook that party direct reference1 it is a guide to action that ensures that the military will forever heed party commands reference2 it is the guiding principle which guarantees the military forces always being under the command of the party reference3 it is the practical guide for the army always to heed the directions of the party references reference1 reference2 reference3 float modified_precision references hypothesis1 n 1 doctest ellipsis 0 9444 float modified_precision references hypothesis2 n 1 doctest ellipsis 0 5714 float modified_precision references hypothesis1 n 2 doctest ellipsis 0 5882352941176471 float modified_precision references hypothesis2 n 2 doctest ellipsis 0 07692 param references a list of reference translations type references list list str param hypothesis a hypothesis translation type hypothesis list str param n the ngram order type n int return bleu s modified precision for the nth order ngram rtype fraction extracts all ngrams in hypothesis set an empty counter if hypothesis is empty extract a union of references counts max_counts reduce or_ counter ngrams ref n for ref in references assigns the intersection between hypothesis and references counts ensures that denominator is minimum 1 to avoid zerodivisionerror usually this happens when the ngram order is len reference this function finds the reference that is the closest length to the hypothesis the closest reference length is referred to as r variable from the brevity penalty formula in papineni et al 2002 param references a list of reference translations type references list list str param hyp_len the length of the hypothesis type hyp_len int return the length of the reference that s closest to the hypothesis rtype int calculate brevity penalty as the modified n gram precision still has the problem from the short length sentence brevity penalty is used to modify the overall bleu score according to length an example from the paper there are three references with length 12 15 and 17 and a concise hypothesis of the length 12 the brevity penalty is 1 reference1 list aaaaaaaaaaaa i e a 12 reference2 list aaaaaaaaaaaaaaa i e a 15 reference3 list aaaaaaaaaaaaaaaaa i e a 17 hypothesis list aaaaaaaaaaaa i e a 12 references reference1 reference2 reference3 hyp_len len hypothesis closest_ref_len closest_ref_length references hyp_len brevity_penalty closest_ref_len hyp_len 1 0 in case a hypothesis translation is shorter than the references penalty is applied references a 28 a 28 hypothesis a 12 hyp_len len hypothesis closest_ref_len closest_ref_length references hyp_len brevity_penalty closest_ref_len hyp_len 0 2635971381157267 the length of the closest reference is used to compute the penalty if the length of a hypothesis is 12 and the reference lengths are 13 and 2 the penalty is applied because the hypothesis length 12 is less then the closest reference length 13 references a 13 a 2 hypothesis a 12 hyp_len len hypothesis closest_ref_len closest_ref_length references hyp_len brevity_penalty closest_ref_len hyp_len doctest ellipsis 0 9200 the brevity penalty doesn t depend on reference order more importantly when two reference sentences are at the same distance the shortest reference sentence length is used references a 13 a 11 hypothesis a 12 hyp_len len hypothesis closest_ref_len closest_ref_length references hyp_len bp1 brevity_penalty closest_ref_len hyp_len hyp_len len hypothesis closest_ref_len closest_ref_length reversed references hyp_len bp2 brevity_penalty closest_ref_len hyp_len bp1 bp2 1 true a test example from mteval v13a pl starting from the line 705 references a 11 a 8 hypothesis a 7 hyp_len len hypothesis closest_ref_len closest_ref_length references hyp_len brevity_penalty closest_ref_len hyp_len doctest ellipsis 0 8668 references a 11 a 8 a 6 a 7 hypothesis a 7 hyp_len len hypothesis closest_ref_len closest_ref_length references hyp_len brevity_penalty closest_ref_len hyp_len 1 0 param hyp_len the length of the hypothesis for a single sentence or the sum of all the hypotheses lengths for a corpus type hyp_len int param closest_ref_len the length of the closest reference for a single hypothesis or the sum of all the closest references for every hypotheses type closest_ref_len int return bleu s brevity penalty rtype float if hypothesis is empty brevity penalty 0 should result in bleu 0 0 this is an implementation of the smoothing techniques for segment level bleu scores that was presented in boxing chen and collin cherry 2014 a systematic comparison of smoothing techniques for sentence level bleu in wmt14 http acl2014 org acl2014 w14 33 pdf w14 3346 pdf this will initialize the parameters required for the various smoothing techniques the default values are set to the numbers used in the experiments from chen and cherry 2014 hypothesis1 it is a guide to action which ensures that the military always obeys the commands of the party reference1 it is a guide to action that ensures that the military will forever heed party commands chencherry smoothingfunction print sentence_bleu reference1 hypothesis1 doctest ellipsis 0 4118 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method0 doctest ellipsis 0 4118 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method1 doctest ellipsis 0 4118 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method2 doctest ellipsis 0 4452 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method3 doctest ellipsis 0 4118 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method4 doctest ellipsis 0 4118 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method5 doctest ellipsis 0 4905 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method6 doctest ellipsis 0 4135 print sentence_bleu reference1 hypothesis1 smoothing_function chencherry method7 doctest ellipsis 0 4905 param epsilon the epsilon value use in method 1 type epsilon float param alpha the alpha value use in method 6 type alpha int param k the k value use in method 4 type k int no smoothing when numerator 0 where denonminator 0 or 0 the result for the precision score should be equal to 0 or undefined due to bleu geometric mean computation in logarithm space we we need to take the return sys float_info min such that math log sys float_info min returns a 0 precision score smoothing method 1 add epsilon counts to precision with 0 counts smoothing method 2 add 1 to both numerator and denominator from chin yew lin and franz josef och 2004 orange a method for evaluating automatic evaluation metrics for machine translation in coling 2004 smoothing method 3 nist geometric sequence smoothing the smoothing is computed by taking 1 2 k instead of 0 for each precision score whose matching n gram count is null k is 1 for the first n value for which the n gram match count is null for example if the text contains one 2 gram match and consequently two 1 gram matches the n gram count for each individual precision score would be n 1 prec_count 2 two unigrams n 2 prec_count 1 one bigram n 3 prec_count 1 2 no trigram taking smoothed value of 1 2 k with k 1 n 4 prec_count 1 4 no fourgram taking smoothed value of 1 2 k with k 2 from the mteval v13a pl it s referred to as k smoothing method 4 shorter translations may have inflated precision values due to having smaller denominators therefore we give them proportionally smaller smoothed counts instead of scaling to 1 2 k chen and cherry suggests dividing by 1 ln len t where t is the length of the translation incvnt i 1 self k math log hyp_len note that this k is different from the k from nist p_n i incvnt p_i denominator smoothing method 5 the matched counts for similar values of n should be similar to a calculate the n gram matched count it averages the n 1 n and n 1 gram matched counts requires an precision value for an addition ngram order smoothing method 6 interpolates the maximum likelihood estimate of the precision p_n with a prior estimate pi0 the prior is estimated by assuming that the ratio between pn and pn 1 will be the same as that between pn 1 and pn 2 from gao and he 2013 training mrf based phrase translation models using gradient ascent in naacl this smoothing only works when p_1 and p_2 is non zero raise an error with an appropriate message when the input is too short to use this smoothing technique skips the first 2 orders of ngrams no of ngrams in translation that matches the reference no of ngrams in translation calculates the interpolated precision smoothing method 7 interpolates methods 4 and 5
import math
import sys
import warnings
from collections import Counter
from fractions import Fraction

from nltk.util import ngrams


def sentence_bleu(
    references,
    hypothesis,
    weights=(0.25, 0.25, 0.25, 0.25),
    smoothing_function=None,
    auto_reweigh=False,
):
    
    return corpus_bleu(
        [references], [hypothesis], weights, smoothing_function, auto_reweigh
    )


def corpus_bleu(
    list_of_references,
    hypotheses,
    weights=(0.25, 0.25, 0.25, 0.25),
    smoothing_function=None,
    auto_reweigh=False,
):
    
    

    p_numerators = Counter()  
    p_denominators = Counter()  
    hyp_lengths, ref_lengths = 0, 0

    assert len(list_of_references) == len(hypotheses), (
        "The number of hypotheses and their reference(s) should be the " "same "
    )

    try:
        weights[0][0]
    except:
        weights = [weights]
    max_weight_length = max(len(weight) for weight in weights)

    
    for references, hypothesis in zip(list_of_references, hypotheses):
        
        
        for i in range(1, max_weight_length + 1):
            p_i = modified_precision(references, hypothesis, i)
            p_numerators[i] += p_i.numerator
            p_denominators[i] += p_i.denominator

        
        
        hyp_len = len(hypothesis)
        hyp_lengths += hyp_len
        ref_lengths += closest_ref_length(references, hyp_len)

    
    bp = brevity_penalty(ref_lengths, hyp_lengths)

    
    p_n = [
        Fraction(p_numerators[i], p_denominators[i], _normalize=False)
        for i in range(1, max_weight_length + 1)
    ]

    
    
    
    if p_numerators[1] == 0:
        return 0 if len(weights) == 1 else [0] * len(weights)

    
    if not smoothing_function:
        smoothing_function = SmoothingFunction().method0
    
    
    
    
    p_n = smoothing_function(
        p_n, references=references, hypothesis=hypothesis, hyp_len=hyp_lengths
    )

    bleu_scores = []
    for weight in weights:
        
        
        if auto_reweigh:
            if hyp_lengths < 4 and weight == (0.25, 0.25, 0.25, 0.25):
                weight = (1 / hyp_lengths,) * hyp_lengths

        s = (w_i * math.log(p_i) for w_i, p_i in zip(weight, p_n) if p_i > 0)
        s = bp * math.exp(math.fsum(s))
        bleu_scores.append(s)
    return bleu_scores[0] if len(weights) == 1 else bleu_scores


def modified_precision(references, hypothesis, n):
    
    
    
    counts = Counter(ngrams(hypothesis, n)) if len(hypothesis) >= n else Counter()
    
    
    max_counts = {}
    for reference in references:
        reference_counts = (
            Counter(ngrams(reference, n)) if len(reference) >= n else Counter()
        )
        for ngram in counts:
            max_counts[ngram] = max(max_counts.get(ngram, 0), reference_counts[ngram])

    
    clipped_counts = {
        ngram: min(count, max_counts[ngram]) for ngram, count in counts.items()
    }

    numerator = sum(clipped_counts.values())
    
    
    denominator = max(1, sum(counts.values()))

    return Fraction(numerator, denominator, _normalize=False)


def closest_ref_length(references, hyp_len):
    
    ref_lens = (len(reference) for reference in references)
    closest_ref_len = min(
        ref_lens, key=lambda ref_len: (abs(ref_len - hyp_len), ref_len)
    )
    return closest_ref_len


def brevity_penalty(closest_ref_len, hyp_len):
    
    if hyp_len > closest_ref_len:
        return 1
    
    elif hyp_len == 0:
        return 0
    else:
        return math.exp(1 - closest_ref_len / hyp_len)


class SmoothingFunction:
    

    def __init__(self, epsilon=0.1, alpha=5, k=5):
        
        self.epsilon = epsilon
        self.alpha = alpha
        self.k = k

    def method0(self, p_n, *args, **kwargs):
        
        p_n_new = []
        for i, p_i in enumerate(p_n):
            if p_i.numerator != 0:
                p_n_new.append(p_i)
            else:
                _msg = str(
                    "\nThe hypothesis contains 0 counts of {}-gram overlaps.\n"
                    "Therefore the BLEU score evaluates to 0, independently of\n"
                    "how many N-gram overlaps of lower order it contains.\n"
                    "Consider using lower n-gram order or use "
                    "SmoothingFunction()"
                ).format(i + 1)
                warnings.warn(_msg)
                
                
                
                
                
                p_n_new.append(sys.float_info.min)
        return p_n_new

    def method1(self, p_n, *args, **kwargs):
        
        return [
            (p_i.numerator + self.epsilon) / p_i.denominator
            if p_i.numerator == 0
            else p_i
            for p_i in p_n
        ]

    def method2(self, p_n, *args, **kwargs):
        
        return [
            Fraction(p_n[i].numerator + 1, p_n[i].denominator + 1, _normalize=False)
            if i != 0
            else p_n[0]
            for i in range(len(p_n))
        ]

    def method3(self, p_n, *args, **kwargs):
        
        incvnt = 1  
        for i, p_i in enumerate(p_n):
            if p_i.numerator == 0:
                p_n[i] = 1 / (2**incvnt * p_i.denominator)
                incvnt += 1
        return p_n

    def method4(self, p_n, references, hypothesis, hyp_len=None, *args, **kwargs):
        
        incvnt = 1
        hyp_len = hyp_len if hyp_len else len(hypothesis)
        for i, p_i in enumerate(p_n):
            if p_i.numerator == 0 and hyp_len > 1:
                
                
                
                
                numerator = 1 / (2**incvnt * self.k / math.log(hyp_len))
                p_n[i] = numerator / p_i.denominator
                incvnt += 1
        return p_n

    def method5(self, p_n, references, hypothesis, hyp_len=None, *args, **kwargs):
        
        hyp_len = hyp_len if hyp_len else len(hypothesis)
        m = {}
        
        p_n_plus1 = p_n + [modified_precision(references, hypothesis, 5)]
        m[-1] = p_n[0] + 1
        for i, p_i in enumerate(p_n):
            p_n[i] = (m[i - 1] + p_i + p_n_plus1[i + 1]) / 3
            m[i] = p_n[i]
        return p_n

    def method6(self, p_n, references, hypothesis, hyp_len=None, *args, **kwargs):
        
        hyp_len = hyp_len if hyp_len else len(hypothesis)
        
        
        
        assert p_n[2], "This smoothing method requires non-zero precision for bigrams."
        for i, p_i in enumerate(p_n):
            if i in [0, 1]:  
                continue
            else:
                pi0 = 0 if p_n[i - 2] == 0 else p_n[i - 1] ** 2 / p_n[i - 2]
                
                m = p_i.numerator
                
                l = sum(1 for _ in ngrams(hypothesis, i + 1))
                
                p_n[i] = (m + self.alpha * pi0) / (l + self.alpha)
        return p_n

    def method7(self, p_n, references, hypothesis, hyp_len=None, *args, **kwargs):
        
        hyp_len = hyp_len if hyp_len else len(hypothesis)
        p_n = self.method4(p_n, references, hypothesis, hyp_len)
        p_n = self.method5(p_n, references, hypothesis, hyp_len)
        return p_n