






import re
import string
from collections import Counter

import sacrebleu
import sacremoses
from packaging import version

import datasets


a						:			Any     	=					"\n@inproceedings{xu-etal-2016-optimizing,\n    title = {Optimizing Statistical Machine Translation for Text Simplification},\n    authors={Xu, Wei and Napoles, Courtney and Pavlick, Ellie and Chen, Quanze and Callison-Burch, Chris},\n    journal = {Transactions of the Association for Computational Linguistics},\n    volume = {4},\n    year={2016},\n    url = {https://www.aclweb.org/anthology/Q16-1029},\n    pages = {401--415\n},\n@inproceedings{post-2018-call,\n    title = \"A Call for Clarity in Reporting {BLEU} Scores\",\n    author = \"Post, Matt\",\n    booktitle = \"Proceedings of the Third Conference on Machine Translation: Research Papers\",\n    month = oct,\n    year = \"2018\",\n    address = \"Belgium, Brussels\",\n    publisher = \"Association for Computational Linguistics\",\n    url = \"https://www.aclweb.org/anthology/W18-6319\",\n    pages = \"186--191\",\n}\n"

a						:			List[Any]     	=					"\\nWIKI_SPLIT is the combination of three metrics SARI, EXACT and SACREBLEU\nIt can be used to evaluate the quality of machine-generated texts.\n"


a						:			Any     	=					"\nCalculates sari score (between 0 and 100) given a list of source and predicted\nsentences, and a list of lists of reference sentences. It also computes the BLEU score as well as the exact match score.\nArgs:\n    sources: list of source sentences where each sentence should be a string.\n    predictions: list of predicted sentences where each sentence should be a string.\n    references: list of lists of reference sentences where each sentence should be a string.\nReturns:\n    sari: sari score\n    sacrebleu: sacrebleu score\n    exact: exact score\n\nExamples:\n    >>> sources=[\"About 95 species are currently accepted .\"]\n    >>> predictions=[\"About 95 you now get in .\"]\n    >>> references=[[\"About 95 species are currently known .\"]]\n    >>> wiki_split = datasets.load_metric(\"wiki_split\")\n    >>> results = wiki_split.compute(sources=sources, predictions=predictions, references=references)\n    >>> print(results)\n    {'sari': 21.805555555555557, 'sacrebleu': 14.535768424205482, 'exact': 0.0}\n"






def 							lowerCamelCase__ (       __lowerCamelCase     :	List[Any]						):

  def remove_articles(__lowerCamelCase     :	List[str]						):
    __UpperCAmelCase				:      List[str]	 =    re.compile(R"""\b(a|an|the)\b"""    ,						re.UNICODE						)
    return re.sub(__lowerCamelCase    ,						""" """    ,						__lowerCamelCase						)

  def white_space_fix(__lowerCamelCase     :	List[str]						):
    return " ".join(text.split()						)

  def remove_punc(__lowerCamelCase     :	Any						):
    __UpperCAmelCase				:      List[Any]	 =    set(string.punctuation						)
    return "".join(ch for ch in text if ch not in exclude						)

  def lower(__lowerCamelCase     :	Tuple						):
    return text.lower()

  return white_space_fix(remove_articles(remove_punc(lower(__lowerCamelCase						)						)						)						)






def 							lowerCamelCase__ (       __lowerCamelCase     :	str    ,						__lowerCamelCase     :	int						):
  return int(normalize_answer(__lowerCamelCase						) == normalize_answer(__lowerCamelCase						)						)






def 							lowerCamelCase__ (       __lowerCamelCase     :	Optional[Any]    ,						__lowerCamelCase     :	Any						):
  __UpperCAmelCase				:      Optional[int]	 =    [any(compute_exact(__lowerCamelCase    ,						__lowerCamelCase						) for ref in refs						) for pred, refs in zip(__lowerCamelCase    ,						__lowerCamelCase						)]
  return (sum(__lowerCamelCase						) / len(__lowerCamelCase						)) * 100






def 							lowerCamelCase__ (       __lowerCamelCase     :	Union[str, Any]    ,						__lowerCamelCase     :	Any    ,						__lowerCamelCase     :	Optional[int]    ,						__lowerCamelCase     :	str						):
  __UpperCAmelCase				:      Dict	 =    [rgram for rgrams in rgramslist for rgram in rgrams]
  __UpperCAmelCase				:      Optional[int]	 =    Counter(__lowerCamelCase						)

  __UpperCAmelCase				:      List[Any]	 =    Counter(__lowerCamelCase						)
  __UpperCAmelCase				:      str	 =    Counter()
  for sgram, scount in sgramcounter.items():
    __UpperCAmelCase				:      int	 =    scount * numref

  __UpperCAmelCase				:      Union[str, Any]	 =    Counter(__lowerCamelCase						)
  __UpperCAmelCase				:      Tuple	 =    Counter()
  for cgram, ccount in cgramcounter.items():
    __UpperCAmelCase				:      str	 =    ccount * numref

  # KEEP
  __UpperCAmelCase				:      Dict	 =    sgramcounter_rep & cgramcounter_rep
  __UpperCAmelCase				:      str	 =    keepgramcounter_rep & rgramcounter
  __UpperCAmelCase				:      Optional[Any]	 =    sgramcounter_rep & rgramcounter

  __UpperCAmelCase				:      int	 =    0
  __UpperCAmelCase				:      Dict	 =    0
  for keepgram in keepgramcountergood_rep:
    keeptmpscorea += keepgramcountergood_rep[keepgram] / keepgramcounter_rep[keepgram]
    # Fix an alleged bug [2] in the keep score computation.
    # keeptmpscore2 += keepgramcountergood_rep[keepgram] / keepgramcounterall_rep[keepgram]
    keeptmpscorea += keepgramcountergood_rep[keepgram]
  # Define 0/0=1 instead of 0 to give higher scores for predictions that match
  #      a target exactly.
  __UpperCAmelCase				:      int	 =    1
  __UpperCAmelCase				:      Union[str, Any]	 =    1
  if len(__lowerCamelCase						) > 0:
    __UpperCAmelCase				:      Optional[int]	 =    keeptmpscorea / len(__lowerCamelCase						)
  if len(__lowerCamelCase						) > 0:
    # Fix an alleged bug [2] in the keep score computation.
    # keepscore_recall = keeptmpscore2 / len(keepgramcounterall_rep)
    __UpperCAmelCase				:      Optional[int]	 =    keeptmpscorea / sum(keepgramcounterall_rep.values()						)
  __UpperCAmelCase				:      Tuple	 =    0
  if keepscore_precision > 0 or keepscore_recall > 0:
    __UpperCAmelCase				:      Optional[Any]	 =    2 * keepscore_precision * keepscore_recall / (keepscore_precision + keepscore_recall)

  # DELETION
  __UpperCAmelCase				:      List[str]	 =    sgramcounter_rep - cgramcounter_rep
  __UpperCAmelCase				:      Union[str, Any]	 =    delgramcounter_rep - rgramcounter
  __UpperCAmelCase				:      Union[str, Any]	 =    sgramcounter_rep - rgramcounter
  __UpperCAmelCase				:      Any	 =    0
  __UpperCAmelCase				:      Dict	 =    0
  for delgram in delgramcountergood_rep:
    deltmpscorea += delgramcountergood_rep[delgram] / delgramcounter_rep[delgram]
    deltmpscorea += delgramcountergood_rep[delgram] / delgramcounterall_rep[delgram]
  # Define 0/0=1 instead of 0 to give higher scores for predictions that match
  # a target exactly.
  __UpperCAmelCase				:      Union[str, Any]	 =    1
  if len(__lowerCamelCase						) > 0:
    __UpperCAmelCase				:      Any	 =    deltmpscorea / len(__lowerCamelCase						)

  # ADDITION
  __UpperCAmelCase				:      Optional[int]	 =    set(__lowerCamelCase						) - set(__lowerCamelCase						)
  __UpperCAmelCase				:      List[str]	 =    set(__lowerCamelCase						) & set(__lowerCamelCase						)
  __UpperCAmelCase				:      Tuple	 =    set(__lowerCamelCase						) - set(__lowerCamelCase						)

  __UpperCAmelCase				:      Any	 =    0
  for addgram in addgramcountergood:
    addtmpscore += 1

  # Define 0/0=1 instead of 0 to give higher scores for predictions that match
  # a target exactly.
  __UpperCAmelCase				:      Dict	 =    1
  __UpperCAmelCase				:      str	 =    1
  if len(__lowerCamelCase						) > 0:
    __UpperCAmelCase				:      Dict	 =    addtmpscore / len(__lowerCamelCase						)
  if len(__lowerCamelCase						) > 0:
    __UpperCAmelCase				:      str	 =    addtmpscore / len(__lowerCamelCase						)
  __UpperCAmelCase				:      Tuple	 =    0
  if addscore_precision > 0 or addscore_recall > 0:
    __UpperCAmelCase				:      Union[str, Any]	 =    2 * addscore_precision * addscore_recall / (addscore_precision + addscore_recall)

  return (keepscore, delscore_precision, addscore)






def 							lowerCamelCase__ (       __lowerCamelCase     :	Optional[Any]    ,						__lowerCamelCase     :	Union[str, Any]    ,						__lowerCamelCase     :	List[Any]						):
  __UpperCAmelCase				:      Optional[int]	 =    len(__lowerCamelCase						)

  __UpperCAmelCase				:      Any	 =    ssent.split(""" """						)
  __UpperCAmelCase				:      List[str]	 =    csent.split(""" """						)
  __UpperCAmelCase				:      List[str]	 =    []
  __UpperCAmelCase				:      Optional[int]	 =    []
  __UpperCAmelCase				:      Optional[int]	 =    []
  __UpperCAmelCase				:      List[Any]	 =    []
  __UpperCAmelCase				:      Optional[int]	 =    []
  __UpperCAmelCase				:      Dict	 =    []

  __UpperCAmelCase				:      Tuple	 =    []
  __UpperCAmelCase				:      Union[str, Any]	 =    []
  __UpperCAmelCase				:      Optional[Any]	 =    []
  __UpperCAmelCase				:      Optional[int]	 =    []
  for rsent in rsents:
    __UpperCAmelCase				:      List[str]	 =    rsent.split(""" """						)
    __UpperCAmelCase				:      List[str]	 =    []
    __UpperCAmelCase				:      int	 =    []
    __UpperCAmelCase				:      str	 =    []
    ragramslist.append(__lowerCamelCase						)
    for i in range(0    ,						len(__lowerCamelCase						) - 1						):
      if i < len(__lowerCamelCase						) - 1:
        __UpperCAmelCase				:      Optional[Any]	 =    ragrams[i] + """ """ + ragrams[i + 1]
        ragrams.append(__lowerCamelCase						)
      if i < len(__lowerCamelCase						) - 2:
        __UpperCAmelCase				:      Union[str, Any]	 =    ragrams[i] + """ """ + ragrams[i + 1] + """ """ + ragrams[i + 2]
        ragrams.append(__lowerCamelCase						)
      if i < len(__lowerCamelCase						) - 3:
        __UpperCAmelCase				:      Union[str, Any]	 =    ragrams[i] + """ """ + ragrams[i + 1] + """ """ + ragrams[i + 2] + """ """ + ragrams[i + 3]
        ragrams.append(__lowerCamelCase						)
    ragramslist.append(__lowerCamelCase						)
    ragramslist.append(__lowerCamelCase						)
    ragramslist.append(__lowerCamelCase						)

  for i in range(0    ,						len(__lowerCamelCase						) - 1						):
    if i < len(__lowerCamelCase						) - 1:
      __UpperCAmelCase				:      Tuple	 =    sagrams[i] + """ """ + sagrams[i + 1]
      sagrams.append(__lowerCamelCase						)
    if i < len(__lowerCamelCase						) - 2:
      __UpperCAmelCase				:      Any	 =    sagrams[i] + """ """ + sagrams[i + 1] + """ """ + sagrams[i + 2]
      sagrams.append(__lowerCamelCase						)
    if i < len(__lowerCamelCase						) - 3:
      __UpperCAmelCase				:      Union[str, Any]	 =    sagrams[i] + """ """ + sagrams[i + 1] + """ """ + sagrams[i + 2] + """ """ + sagrams[i + 3]
      sagrams.append(__lowerCamelCase						)

  for i in range(0    ,						len(__lowerCamelCase						) - 1						):
    if i < len(__lowerCamelCase						) - 1:
      __UpperCAmelCase				:      Optional[int]	 =    cagrams[i] + """ """ + cagrams[i + 1]
      cagrams.append(__lowerCamelCase						)
    if i < len(__lowerCamelCase						) - 2:
      __UpperCAmelCase				:      Dict	 =    cagrams[i] + """ """ + cagrams[i + 1] + """ """ + cagrams[i + 2]
      cagrams.append(__lowerCamelCase						)
    if i < len(__lowerCamelCase						) - 3:
      __UpperCAmelCase				:      Tuple	 =    cagrams[i] + """ """ + cagrams[i + 1] + """ """ + cagrams[i + 2] + """ """ + cagrams[i + 3]
      cagrams.append(__lowerCamelCase						)

  ((__UpperCAmelCase) ,					(__UpperCAmelCase) ,					(__UpperCAmelCase))				:      Optional[int]	 =    SARIngram(__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase						)
  ((__UpperCAmelCase) ,					(__UpperCAmelCase) ,					(__UpperCAmelCase))				:      Optional[Any]	 =    SARIngram(__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase						)
  ((__UpperCAmelCase) ,					(__UpperCAmelCase) ,					(__UpperCAmelCase))				:      Union[str, Any]	 =    SARIngram(__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase						)
  ((__UpperCAmelCase) ,					(__UpperCAmelCase) ,					(__UpperCAmelCase))				:      int	 =    SARIngram(__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase						)
  __UpperCAmelCase				:      Optional[int]	 =    sum([keepascore, keepascore, keepascore, keepascore]						) / 4
  __UpperCAmelCase				:      Optional[int]	 =    sum([delascore, delascore, delascore, delascore]						) / 4
  __UpperCAmelCase				:      List[Any]	 =    sum([addascore, addascore, addascore, addascore]						) / 4
  __UpperCAmelCase				:      int	 =    (avgkeepscore + avgdelscore + avgaddscore) / 3
  return finalscore






def 							lowerCamelCase__ (       __lowerCamelCase     :	Any    ,						__lowerCamelCase     :	bool = True    ,						__lowerCamelCase     :	str = "13a"    ,						__lowerCamelCase     :	bool = True						):
  # Normalization is requried for the ASSET dataset (one of the primary
  # datasets in sentence simplification) to allow using space
  # to split the sentence. Even though Wiki-Auto and TURK datasets,
  # do not require normalization, we do it for consistency.
  # Code adapted from the EASSE library [1] written by the authors of the ASSET dataset.
  # [1] https://github.com/feralvam/easse/blob/580bba7e1378fc8289c663f864e0487188fe8067/easse/utils/preprocessing.py#L7

  if lowercase:
    __UpperCAmelCase				:      Union[str, Any]	 =    sentence.lower()

  if tokenizer in ["13a", "intl"]:
    if version.parse(sacrebleu.__version__						).major >= 2:
      __UpperCAmelCase				:      List[str]	 =    sacrebleu.metrics.bleu._get_tokenizer(__lowerCamelCase						)()(__lowerCamelCase						)
    else:
      __UpperCAmelCase				:      Optional[int]	 =    sacrebleu.TOKENIZERS[tokenizer]()(__lowerCamelCase						)
  elif tokenizer == "moses":
    __UpperCAmelCase				:      Optional[int]	 =    sacremoses.MosesTokenizer().tokenize(__lowerCamelCase    ,						return_str=__lowerCamelCase    ,						escape=__lowerCamelCase						)
  elif tokenizer == "penn":
    __UpperCAmelCase				:      Optional[int]	 =    sacremoses.MosesTokenizer().penn_tokenize(__lowerCamelCase    ,						return_str=__lowerCamelCase						)
  else:
    __UpperCAmelCase				:      str	 =    sentence

  if not return_str:
    __UpperCAmelCase				:      Optional[int]	 =    normalized_sent.split()

  return normalized_sent






def 							lowerCamelCase__ (       __lowerCamelCase     :	Any    ,						__lowerCamelCase     :	Any    ,						__lowerCamelCase     :	int						):
  if not (len(__lowerCamelCase						) == len(__lowerCamelCase						) == len(__lowerCamelCase						)):
    raise ValueError("""Sources length must match predictions and references lengths."""						)
  __UpperCAmelCase				:      Union[str, Any]	 =    0
  for src, pred, refs in zip(__lowerCamelCase    ,						__lowerCamelCase    ,						__lowerCamelCase						):
    sari_score += SARIsent(normalize(__lowerCamelCase						)    ,						normalize(__lowerCamelCase						)    ,						[normalize(__lowerCamelCase						) for sent in refs]						)
  __UpperCAmelCase				:      List[str]	 =    sari_score / len(__lowerCamelCase						)
  return 100 * sari_score






def 							lowerCamelCase__ (       __lowerCamelCase     :	Any    ,						__lowerCamelCase     :	List[str]    ,						__lowerCamelCase     :	Optional[Any]="exp"    ,						__lowerCamelCase     :	Optional[int]=None    ,						__lowerCamelCase     :	Tuple=False    ,						__lowerCamelCase     :	Optional[Any]=False    ,						__lowerCamelCase     :	str=False    ,						):
  __UpperCAmelCase				:      Optional[int]	 =    len(references[0]						)
  if any(len(__lowerCamelCase						) != references_per_prediction for refs in references						):
    raise ValueError("""Sacrebleu requires the same number of references for each prediction"""						)
  __UpperCAmelCase				:      Optional[Any]	 =    [[refs[i] for refs in references] for i in range(__lowerCamelCase						)]
  __UpperCAmelCase				:      Union[str, Any]	 =    sacrebleu.corpus_bleu(
      __lowerCamelCase    ,						__lowerCamelCase    ,						smooth_method=__lowerCamelCase    ,						smooth_value=__lowerCamelCase    ,						force=__lowerCamelCase    ,						lowercase=__lowerCamelCase    ,						use_effective_order=__lowerCamelCase    ,						)
  return output.score







@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION				,			_KWARGS_DESCRIPTION  )
class        a       (					datasets.Metric  ):



      """simple docstring"""


      def       UpperCAmelCase ( self   :     Union[str, Any]   )				-> Dict:
        return datasets.MetricInfo(
            description=_DESCRIPTION						, citation=_CITATION						, inputs_description=_KWARGS_DESCRIPTION						, features=datasets.Features(
                {
                    """predictions""": datasets.Value("""string"""						, id="""sequence"""   ),
                    """references""": datasets.Sequence(datasets.Value("""string"""						, id="""sequence"""   )						, id="""references"""   ),
                }   )						, codebase_urls=[
                """https://github.com/huggingface/transformers/blob/master/src/transformers/data/metrics/squad_metrics.py""",
                """https://github.com/cocoxu/simplification/blob/master/SARI.py""",
                """https://github.com/tensorflow/tensor2tensor/blob/master/tensor2tensor/utils/sari_hook.py""",
                """https://github.com/mjpost/sacreBLEU""",
            ]						, reference_urls=[
                """https://www.aclweb.org/anthology/Q16-1029.pdf""",
                """https://github.com/mjpost/sacreBLEU""",
                """https://en.wikipedia.org/wiki/BLEU""",
                """https://towardsdatascience.com/evaluating-text-output-in-nlp-bleu-at-your-own-risk-e8609665a213""",
            ]						, )




      def       UpperCAmelCase ( self   :     int						, __lowercase   :     str						, __lowercase   :     Optional[int]						, __lowercase   :     int   )				-> Union[str, Any]:
        __UpperCAmelCase				:      str	 =    {}
        result.update({"""sari""": compute_sari(sources=__lowercase						, predictions=__lowercase						, references=__lowercase   )}   )
        result.update({"""sacrebleu""": compute_sacrebleu(predictions=__lowercase						, references=__lowercase   )}   )
        result.update({"""exact""": compute_em(predictions=__lowercase						, references=__lowercase   )}   )
        return result








__a							     =					'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'







def lowerCamelCase__  (     _lowercase ):

     '''simple docstring'''


     if not isinstance(_lowercase					,		_lowercase ):
          UpperCAmelCase_     :				Union[str, Any]  =     f'''a bytes-like object is required, not \'{data.__class__.__name__}\''''
          raise TypeError(_lowercase )

     UpperCAmelCase_     :				Any  =     ''''''.join(bin(_lowercase )[2:].zfill(8 ) for byte in data )

     UpperCAmelCase_     :				Any  =     len(_lowercase ) % 6 != 0

     if padding_needed:
          # The padding that will be added later
          UpperCAmelCase_     :				Union[str, Any]  =     B'''=''' * ((6 - len(_lowercase ) % 6) // 2)

          # Append binary_stream with arbitrary binary digits (0's by default) to make its
          # length a multiple of 6.
          binary_stream += "0" * (6 - len(_lowercase ) % 6)
     else:
          UpperCAmelCase_     :				int  =     B''''''

     # Encode every 6 binary digits to their corresponding Base64 character
     return (
         "".join(
             B64_CHARSET[int(binary_stream[index : index + 6]					,		2 )]
             for index in range(0					,		len(_lowercase )					,		6 ) ).encode()
         + padding
     )







def lowerCamelCase__  (     _lowercase ):

     '''simple docstring'''


     if not isinstance(_lowercase					,		_lowercase ) and not isinstance(_lowercase					,		_lowercase ):
          UpperCAmelCase_     :				Tuple  =     (
              '''argument should be a bytes-like object or ASCII string, '''
              f'''not \'{encoded_data.__class__.__name__}\''''
          )
          raise TypeError(_lowercase )

     # In case encoded_data is a bytes-like object, make sure it contains only
     # ASCII characters so we convert it to a string object
     if isinstance(_lowercase					,		_lowercase ):
          try:
               UpperCAmelCase_     :				Any  =     encoded_data.decode('''utf-8''' )
          except UnicodeDecodeError:
               raise ValueError('''base64 encoded data should only contain ASCII characters''' )

     UpperCAmelCase_     :				str  =     encoded_data.count('''=''' )

     # Check if the encoded string contains non base64 characters
     if padding:
          assert all(
              char in B64_CHARSET for char in encoded_data[:-padding] ), "Invalid base64 character(s) found."
     else:
          assert all(
              char in B64_CHARSET for char in encoded_data ), "Invalid base64 character(s) found."

     # Check the padding
     assert len(_lowercase ) % 4 == 0 and padding < 3, "Incorrect padding"

     if padding:
          # Remove padding if there is one
          UpperCAmelCase_     :				List[Any]  =     encoded_data[:-padding]

          UpperCAmelCase_     :				List[Any]  =     ''''''.join(
              bin(B64_CHARSET.index(_lowercase ) )[2:].zfill(6 ) for char in encoded_data )[: -padding * 2]
     else:
          UpperCAmelCase_     :				Tuple  =     ''''''.join(
              bin(B64_CHARSET.index(_lowercase ) )[2:].zfill(6 ) for char in encoded_data )

     UpperCAmelCase_     :				str  =     [
         int(binary_stream[index : index + 8]					,		2 )
         for index in range(0					,		len(_lowercase )					,		8 )
     ]

     return bytes(_lowercase )


if __name__ == "__main__":
     import doctest

     doctest.testmod()