'''simple docstring'''


import datasets

from .evaluate import (
    apply_no_ans_threshold,
    find_all_best_thresh,
    get_raw_scores,
    make_eval_dict,
    make_qid_to_has_ans,
    merge_eval,
)


snake_case__	:     int      =    '''\
@inproceedings{Rajpurkar2016SQuAD10,
  title={SQuAD: 100, 000+ Questions for Machine Comprehension of Text},
  author={Pranav Rajpurkar and Jian Zhang and Konstantin Lopyrev and Percy Liang},
  booktitle={EMNLP},
  year={2016}
}
'''

snake_case__	:     List[str]      =    '''
This metric wrap the official scoring script for version 2 of the Stanford Question
Answering Dataset (SQuAD).

Stanford Question Answering Dataset (SQuAD) is a reading comprehension dataset, consisting of questions posed by
crowdworkers on a set of Wikipedia articles, where the answer to every question is a segment of text, or span,
from the corresponding reading passage, or the question might be unanswerable.

SQuAD2.0 combines the 100,000 questions in SQuAD1.1 with over 50,000 unanswerable questions
written adversarially by crowdworkers to look similar to answerable ones.
To do well on SQuAD2.0, systems must not only answer questions when possible, but also
determine when no answer is supported by the paragraph and abstain from answering.
'''

snake_case__	:     int      =    '''
Computes SQuAD v2 scores (F1 and EM).
Args:
    predictions: List of triple for question-answers to score with the following elements:
        - the question-answer \'id\' field as given in the references (see below)
        - the text of the answer
        - the probability that the question has no answer
    references: List of question-answers dictionaries with the following key-values:
            - \'id\': id of the question-answer pair (see above),
            - \'answers\': a list of Dict {\'text\': text of the answer as a string}
    no_answer_threshold: float
        Probability threshold to decide that a question has no answer.
Returns:
    \'exact\': Exact match (the normalized answer exactly match the gold answer)
    \'f1\': The F-score of predicted tokens versus the gold answer
    \'total\': Number of score considered
    \'HasAns_exact\': Exact match (the normalized answer exactly match the gold answer)
    \'HasAns_f1\': The F-score of predicted tokens versus the gold answer
    \'HasAns_total\': Number of score considered
    \'NoAns_exact\': Exact match (the normalized answer exactly match the gold answer)
    \'NoAns_f1\': The F-score of predicted tokens versus the gold answer
    \'NoAns_total\': Number of score considered
    \'best_exact\': Best exact match (with varying threshold)
    \'best_exact_thresh\': No-answer probability threshold associated to the best exact match
    \'best_f1\': Best F1 (with varying threshold)
    \'best_f1_thresh\': No-answer probability threshold associated to the best F1
Examples:

    >>> predictions = [{\'prediction_text\': \'1976\', \'id\': \'56e10a3be3433e1400422b22\', \'no_answer_probability\': 0.}]
    >>> references = [{\'answers\': {\'answer_start\': [97], \'text\': [\'1976\']}, \'id\': \'56e10a3be3433e1400422b22\'}]
    >>> squad_v2_metric = datasets.load_metric("squad_v2")
    >>> results = squad_v2_metric.compute(predictions=predictions, references=references)
    >>> print(results)
    {\'exact\': 100.0, \'f1\': 100.0, \'total\': 1, \'HasAns_exact\': 100.0, \'HasAns_f1\': 100.0, \'HasAns_total\': 1, \'best_exact\': 100.0, \'best_exact_thresh\': 0.0, \'best_f1\': 100.0, \'best_f1_thresh\': 0.0}
'''






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







  '''simple docstring'''






  def _UpperCamelCase	(					self		):




       '''simple docstring'''

       return datasets.MetricInfo(
           description=_DESCRIPTION ,						citation=_CITATION ,						inputs_description=_KWARGS_DESCRIPTION ,						features=datasets.Features(
               {
                   'predictions': {
                       'id': datasets.Value('string'		),
                       'prediction_text': datasets.Value('string'		),
                       'no_answer_probability': datasets.Value('float32'		),
                   },
                   'references': {
                       'id': datasets.Value('string'		),
                       'answers': datasets.features.Sequence(
                           {'text': datasets.Value('string'		), 'answer_start': datasets.Value('int32'		)}		),
                   },
               }		) ,						codebase_urls=['https://rajpurkar.github.io/SQuAD-explorer/'] ,						reference_urls=['https://rajpurkar.github.io/SQuAD-explorer/'] ,						)






  def _UpperCamelCase	(					self ,						snake_case_ ,						snake_case_ ,						snake_case_=1.0		):




       '''simple docstring'''

       UpperCAmelCase_				:  Optional[int]  = {p['id']: p['no_answer_probability'] for p in predictions}
       UpperCAmelCase_				:  Dict  = [{'paragraphs': [{'qas': references}]}]
       UpperCAmelCase_				:  Optional[int]  = {p['id']: p['prediction_text'] for p in predictions}

       UpperCAmelCase_				:  Optional[int]  = make_qid_to_has_ans(snake_case_		)  # maps qid to True/False
       UpperCAmelCase_				:  List[Any]  = [k for k, v in qid_to_has_ans.items() if v]
       UpperCAmelCase_				:  Union[str, Any]  = [k for k, v in qid_to_has_ans.items() if not v]

       UpperCAmelCase_  ,     UpperCAmelCase_				:  Optional[int]  = get_raw_scores(snake_case_ ,						snake_case_		)
       UpperCAmelCase_				:  Tuple  = apply_no_ans_threshold(snake_case_ ,						snake_case_ ,						snake_case_ ,						snake_case_		)
       UpperCAmelCase_				:  Dict  = apply_no_ans_threshold(snake_case_ ,						snake_case_ ,						snake_case_ ,						snake_case_		)
       UpperCAmelCase_				:  str  = make_eval_dict(snake_case_ ,						snake_case_		)

       if has_ans_qids:
            UpperCAmelCase_				:  Dict  = make_eval_dict(snake_case_ ,						snake_case_ ,						qid_list=snake_case_		)
            merge_eval(snake_case_ ,						snake_case_ ,						'HasAns'		)
       if no_ans_qids:
            UpperCAmelCase_				:  List[str]  = make_eval_dict(snake_case_ ,						snake_case_ ,						qid_list=snake_case_		)
            merge_eval(snake_case_ ,						snake_case_ ,						'NoAns'		)
       find_all_best_thresh(snake_case_ ,						snake_case_ ,						snake_case_ ,						snake_case_ ,						snake_case_ ,						snake_case_		)
       return dict(snake_case_		)








# DISCLAIMER: This code is strongly influenced by https://github.com/pesser/pytorch_diffusion
# and https://github.com/hojonathanho/diffusion

from dataclasses import dataclass
from typing import Optional, Tuple, Union

import flax
import jax.numpy as jnp

from ..configuration_utils import ConfigMixin, register_to_config
from .scheduling_utils_flax import (
    CommonSchedulerState,
    FlaxKarrasDiffusionSchedulers,
    FlaxSchedulerMixin,
    FlaxSchedulerOutput,
    add_noise_common,
    get_velocity_common,
)


@flax.struct.dataclass
class 			UpperCamelCase_				:




      '''simple docstring'''







      a		:CommonSchedulerState
      a		:jnp.ndarray

      # setable values
      a		:jnp.ndarray
      a		:jnp.ndarray
      a		:Optional[int]						 =      None







      @classmethod
      def lowercase__		( cls					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					):
            return cls(
                common=_UpperCAmelCase					,					final_alpha_cumprod=_UpperCAmelCase					,					init_noise_sigma=_UpperCAmelCase					,					timesteps=_UpperCAmelCase					,					)


@dataclass
class 			UpperCamelCase_				(  A     ):




      '''simple docstring'''







      a		:DDIMSchedulerState


class 			UpperCamelCase_				(  A					,       A     ):




      '''simple docstring'''







      a		:int						 =      [e.name for e in FlaxKarrasDiffusionSchedulers]

      a		:jnp.dtype







      @property
      def lowercase__		( self):
            return True







      @register_to_config
      def __init__( self					,					_UpperCAmelCase = 1_000					,					_UpperCAmelCase = 0.0001					,					_UpperCAmelCase = 0.02					,					_UpperCAmelCase = "linear"					,					_UpperCAmelCase = None					,					_UpperCAmelCase = True					,					_UpperCAmelCase = 0					,					_UpperCAmelCase = "epsilon"					,					_UpperCAmelCase = jnp.floataa					,					):
            lowerCAmelCase_						=      dtype







      def lowercase__		( self					,					_UpperCAmelCase = None):
            if common is None:
                  lowerCAmelCase_						=      CommonSchedulerState.create(self)

            # At every step in ddim, we are looking into the previous alphas_cumprod
            # For the final step, there is no previous alphas_cumprod because we are already at 0
            # `set_alpha_to_one` decides whether we set this parameter simply to one or
            # whether we use the final alpha of the "non-previous" one.
            lowerCAmelCase_						=      (
                jnp.array(1.0					,					dtype=self.dtype) if self.config.set_alpha_to_one else common.alphas_cumprod[0]
            )

            # standard deviation of the initial noise distribution
            lowerCAmelCase_						=      jnp.array(1.0					,					dtype=self.dtype)

            lowerCAmelCase_						=      jnp.arange(0					,					self.config.num_train_timesteps).round()[::-1]

            return DDIMSchedulerState.create(
                common=_UpperCAmelCase					,					final_alpha_cumprod=_UpperCAmelCase					,					init_noise_sigma=_UpperCAmelCase					,					timesteps=_UpperCAmelCase					,					)







      def lowercase__		( self					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase = None):
            return sample







      def lowercase__		( self					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase = ()):
            lowerCAmelCase_						=      self.config.num_train_timesteps // num_inference_steps
            # creates integer timesteps by multiplying by ratio
            # rounding to avoid issues when num_inference_step is power of 3
            lowerCAmelCase_						=      (jnp.arange(0					,					_UpperCAmelCase) * step_ratio).round()[::-1] + self.config.steps_offset

            return state.replace(
                num_inference_steps=_UpperCAmelCase					,					timesteps=_UpperCAmelCase					,					)







      def lowercase__		( self					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase):
            lowerCAmelCase_						=      state.common.alphas_cumprod[timestep]
            lowerCAmelCase_						=      jnp.where(
                prev_timestep >= 0					,					state.common.alphas_cumprod[prev_timestep]					,					state.final_alpha_cumprod)
            lowerCAmelCase_						=      1 - alpha_prod_t
            lowerCAmelCase_						=      1 - alpha_prod_t_prev

            lowerCAmelCase_						=      (beta_prod_t_prev / beta_prod_t) * (1 - alpha_prod_t / alpha_prod_t_prev)

            return variance







      def lowercase__		( self					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase = 0.0					,					_UpperCAmelCase = True					,					):
            if state.num_inference_steps is None:
                  raise ValueError(
                      '''Number of inference steps is \'None\', you need to run \'set_timesteps\' after creating the scheduler''')

            # See formulas (12) and (16) of DDIM paper https://arxiv.org/pdf/2010.02502.pdf
            # Ideally, read DDIM paper in-detail understanding

            # Notation (<variable name> -> <name in paper>
            # - pred_noise_t -> e_theta(x_t, t)
            # - pred_original_sample -> f_theta(x_t, t) or x_0
            # - std_dev_t -> sigma_t
            # - eta -> η
            # - pred_sample_direction -> "direction pointing to x_t"
            # - pred_prev_sample -> "x_t-1"

            # 1. get previous step value (=t-1)
            lowerCAmelCase_						=      timestep - self.config.num_train_timesteps // state.num_inference_steps

            lowerCAmelCase_						=      state.common.alphas_cumprod
            lowerCAmelCase_						=      state.final_alpha_cumprod

            # 2. compute alphas, betas
            lowerCAmelCase_						=      alphas_cumprod[timestep]
            lowerCAmelCase_						=      jnp.where(prev_timestep >= 0					,					alphas_cumprod[prev_timestep]					,					_UpperCAmelCase)

            lowerCAmelCase_						=      1 - alpha_prod_t

            # 3. compute predicted original sample from predicted noise also called
            # "predicted x_0" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf
            if self.config.prediction_type == "epsilon":
                  lowerCAmelCase_						=      (sample - beta_prod_t ** 0.5 * model_output) / alpha_prod_t ** 0.5
                  lowerCAmelCase_						=      model_output
            elif self.config.prediction_type == "sample":
                  lowerCAmelCase_						=      model_output
                  lowerCAmelCase_						=      (sample - alpha_prod_t ** 0.5 * pred_original_sample) / beta_prod_t ** 0.5
            elif self.config.prediction_type == "v_prediction":
                  lowerCAmelCase_						=      (alpha_prod_t**0.5) * sample - (beta_prod_t**0.5) * model_output
                  lowerCAmelCase_						=      (alpha_prod_t**0.5) * model_output + (beta_prod_t**0.5) * sample
            else:
                  raise ValueError(
                      f'prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample`, or'
                      ''' `v_prediction`''')

            # 4. compute variance: "sigma_t(η)" -> see formula (16)
            # σ_t = sqrt((1 − α_t−1)/(1 − α_t)) * sqrt(1 − α_t/α_t−1)
            lowerCAmelCase_						=      self._get_variance(_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase)
            lowerCAmelCase_						=      eta * variance ** 0.5

            # 5. compute "direction pointing to x_t" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf
            lowerCAmelCase_						=      (1 - alpha_prod_t_prev - std_dev_t**2) ** 0.5 * pred_epsilon

            # 6. compute x_t without "random noise" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf
            lowerCAmelCase_						=      alpha_prod_t_prev ** 0.5 * pred_original_sample + pred_sample_direction

            if not return_dict:
                  return (prev_sample, state)

            return FlaxDDIMSchedulerOutput(prev_sample=_UpperCAmelCase					,					state=_UpperCAmelCase)







      def lowercase__		( self					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					):
            return add_noise_common(state.common					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase)







      def lowercase__		( self					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase					,					):
            return get_velocity_common(state.common					,					_UpperCAmelCase					,					_UpperCAmelCase					,					_UpperCAmelCase)







      def __len__( self):
            return self.config.num_train_timesteps



