
import jax
import jax.numpy as jnp
from bigbird_flax import FlaxBigBirdForNaturalQuestions
from datasets import load_from_disk

from transformers import BigBirdTokenizerFast


lowerCAmelCase						:   Tuple										=    {0: '''null''', 1: '''short''', 2: '''long''', 3: '''yes''', 4: '''no'''}
lowerCAmelCase						:   Optional[int]										=    set(''''''.join(['''‘''', '''’''', '''´''', '''`''', '''.''', ''',''', '''-''', '''\"''']))





def 			_lowercase    (      __UpperCamelCase     :		List[str]   ,       __UpperCamelCase     :		List[str]=0   ,       __UpperCamelCase     :		Union[str, Any]=None ):
      return [" ".join(x.split(""" """ )[begin:end] ) for x in answers if len(x.split(""" """ ) ) > 1]





def 			_lowercase    (      __UpperCamelCase     :		int   ,       __UpperCamelCase     :		Dict=False ):
      if make_sub_answers:
            # if answers are longer than one word, make sure a predictions is correct if it coresponds to the complete 1: or :-1 sub word
            # *e.g.* if the correct answer contains a prefix such as "the", or "a"
            snake_case__					=   (
                given_answers + get_sub_answers(lowercase__   ,       begin=1 ) + get_sub_answers(lowercase__   ,       end=-1 )
            )
      snake_case__					=   []
      for answer in given_answers:
            snake_case__					=   answer.replace("""_"""   ,       """ """ ).lower()
            snake_case__					=   "".join(c if c not in PUNCTUATION_SET_TO_EXCLUDE else """ """ for c in alias )
            answers.append(""" """.join(alias.split() ).strip() )
      return set(lowercase__ )





def 			_lowercase    (      __UpperCamelCase     :		List[Any]   ,       __UpperCamelCase     :		Tuple   ,       __UpperCamelCase     :		List[Any]=1   ,       __UpperCamelCase     :		Any=100 ):
      snake_case__					=   jax.lax.top_k(lowercase__   ,       lowercase__ )
      snake_case__					=   jax.lax.top_k(lowercase__   ,       lowercase__ )

      snake_case__					=   best_end_idx[:, None] - best_start_idx[None, :]
      snake_case__					=   jnp.logical_or(widths < 0   ,       widths > max_size )
      snake_case__					=   (best_end_scores[:, None] + best_start_scores[None, :]) - (1E8 * mask)
      snake_case__					=   jnp.argmax(lowercase__ ).item()

      return best_start_idx[best_score % top_k], best_end_idx[best_score // top_k]





def 			_lowercase    (      __UpperCamelCase     :		str ):
      snake_case__					=   sample["question"]["text"]
      snake_case__					=   sample["document"]["tokens"]["token"]
      snake_case__					=   sample["document"]["tokens"]["is_html"]
      snake_case__					=   sample["annotations"]["long_answer"]
      snake_case__					=   sample["annotations"]["short_answers"]

      snake_case__					=   " ".join([context[i] for i in range(len(lowercase__ ) ) if not is_html[i]] )

      # 0 - No ; 1 - Yes
      for answer in sample["annotations"]["yes_no_answer"]:
            if answer == 0 or answer == 1:
                  return {
                      "question": question,
                      "context": context_string,
                      "short": [],
                      "long": [],
                      "category": "no" if answer == 0 else "yes",
                  }

      snake_case__					=   []
      for s in short_answers:
            short_targets.extend(s["""text"""] )
      snake_case__					=   list(set(lowercase__ ) )

      snake_case__					=   []
      for s in long_answers:
            if s["start_token"] == -1:
                  continue
            snake_case__					=   context[s["start_token"] : s["end_token"]]
            snake_case__					=   is_html[s["start_token"] : s["end_token"]]
            snake_case__					=   " ".join([answer[i] for i in range(len(lowercase__ ) ) if not html[i]] )
            if new_answer not in long_targets:
                  long_targets.append(lowercase__ )

      snake_case__					=   "long_short" if len(short_targets + long_targets ) > 0 else "null"

      return {
          "question": question,
          "context": context_string,
          "short": short_targets,
          "long": long_targets,
          "category": category,
      }





def 			_lowercase    (      ):
      snake_case__					=   load_from_disk("""natural-questions-validation""" )
      snake_case__					=   dataset.map(lowercase__ ).remove_columns(["""annotations""", """document""", """id"""] )
      print(lowercase__ )

      snake_case__					=   dataset.filter(lambda __UpperCamelCase : (len(x["""question"""] ) + len(x["""context"""] )) < 4 * 4096 )
      snake_case__					=   short_validation_dataset.filter(lambda __UpperCamelCase : x["category"] != "null" )
      short_validation_dataset

      snake_case__					=   "vasudevgupta/flax-bigbird-natural-questions"
      snake_case__					=   FlaxBigBirdForNaturalQuestions.from_pretrained(lowercase__ )
      snake_case__					=   BigBirdTokenizerFast.from_pretrained(lowercase__ )

      @jax.jit
      def forward(*__UpperCamelCase     :		Union[str, Any]   ,       **__UpperCamelCase     :		int ):
            snake_case__					=   model(*lowercase__   ,       **lowercase__ )
            return start_logits, end_logits, jnp.argmax(lowercase__   ,       axis=-1 )

      def evaluate(__UpperCamelCase     :		int ):
            # encode question and context so that they are separated by a tokenizer.sep_token and cut at max_length
            snake_case__					=   tokenizer(
                example["""question"""]   ,       example["""context"""]   ,       return_tensors="""np"""   ,       max_length=4096   ,       padding="""max_length"""   ,       truncation=lowercase__   ,       )

            snake_case__					=   forward(**lowercase__ )

            snake_case__					=   CATEGORY_MAPPING[category.item()]

            snake_case__					=   example["long"] + example["short"]
            if example["category"] in ["yes", "no", "null"]:
                  snake_case__					=   [example["category"]]
            snake_case__					=   example["category"] != "null"
            # Now target can be: "yes", "no", "null", "list of long & short answers"

            if predicted_category in ["yes", "no", "null"]:
                  snake_case__					=   [predicted_category]
                  snake_case__					=   example["output"] == example["targets"]
                  snake_case__					=   predicted_category != "null"
                  return example

            snake_case__					=   38 if predicted_category == "short" else 1024
            snake_case__					=   get_best_valid_start_end_idx(
                start_scores[0]   ,       end_scores[0]   ,       top_k=8   ,       max_size=lowercase__ )

            snake_case__					=   inputs["input_ids"][0].tolist()
            snake_case__					=   [tokenizer.decode(input_ids[start_score : end_score + 1] )]

            snake_case__					=   expand_to_aliases(example["""targets"""]   ,       make_sub_answers=lowercase__ )
            snake_case__					=   expand_to_aliases(example["""output"""] )

            # some preprocessing to both prediction and answer
            snake_case__					=   {"".join(a.split() ) for a in answers}
            snake_case__					=   {"".join(p.split() ) for p in predictions}
            snake_case__					=   {s for s in predictions if s not in ["``", "''", "`", "'"]}

            # if there is a common element, it's a exact match
            snake_case__					=   len(list(answers & predictions ) ) > 0
            snake_case__					=   predicted_category != "null" and len(lowercase__ ) > 0

            return example

      snake_case__					=   short_validation_dataset.map(lowercase__ )

      snake_case__					=   len(lowercase__ )
      snake_case__					=   len(short_validation_dataset.filter(lambda __UpperCamelCase : x["match"] == 1 ) )
      print("""EM score:"""   ,       (matched / total) * 100   ,       """%""" )


if __name__ == "__main__":
       main()









from doctest import testmod
from math import sqrt





def 			_lowercase    (      __UpperCamelCase     :		int ):
      snake_case__					=   []
      if num < 1:
            return facs
      facs.append(1 )
      if num == 1:
            return facs
      facs.append(__UpperCamelCase )
      for i in range(2   ,       int(sqrt(__UpperCamelCase ) ) + 1 ):
            if num % i == 0:  # If i is a factor of num
                  facs.append(__UpperCamelCase )
                  snake_case__					=   num // i  # num//i is the other factor of num
                  if d != i:  # If d and i are distinct
                        facs.append(__UpperCamelCase )  # we have found another factor
      facs.sort()
      return facs


if __name__ == "__main__":
       testmod(name='''factors_of_a_number''', verbose=True)






