
import dataclasses
import enum
import functools
import math
import re

# The following script is adapted from the script of TaPas.
# Original: https://github.com/google-research/tapas/master/wikisql_utils.py
from typing import Any, List, Text


SCREAMING_SNAKE_CASE   :		Union[str, Any]					 =		"none"
SCREAMING_SNAKE_CASE   :		int					 =		"none"



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase     ):
				A_       	=  value.split(__UpperCamelCase     )
				return len(__UpperCamelCase     ) > 1 and any((len(__UpperCamelCase     ) == 3 for x in split)     )



def        lowerCamelCase_  (   __UpperCamelCase     ):
				if isinstance(__UpperCamelCase ,						__UpperCamelCase     ):
								return value
				if isinstance(__UpperCamelCase ,						__UpperCamelCase     ):
								return float(__UpperCamelCase     )
				if not isinstance(__UpperCamelCase ,						__UpperCamelCase     ):
								raise ValueError('''Argument value is not a string. Can\'t parse it as float'''     )
				A_       	=  value

				try:
								# Example: 1,000.7
								if "." in sanitized and "," in sanitized:
												return float(sanitized.replace(''',''' ,						''''''     )     )
								# 1,000
								if "," in sanitized and _split_thousands(''',''' ,						__UpperCamelCase     ):
												return float(sanitized.replace(''',''' ,						''''''     )     )
								# 5,5556
								if "," in sanitized and sanitized.count(''','''     ) == 1 and not _split_thousands(''',''' ,						__UpperCamelCase     ):
												return float(sanitized.replace(''',''' ,						'''.'''     )     )
								# 0.0.0.1
								if sanitized.count('''.'''     ) > 1:
												return float(sanitized.replace('''.''' ,						''''''     )     )
								# 0,0,0,1
								if sanitized.count(''','''     ) > 1:
												return float(sanitized.replace(''',''' ,						''''''     )     )
								return float(__UpperCamelCase     )
				except ValueError:
								# Avoid adding the sanitized value in the error message.
								raise ValueError('''Unable to convert value to float'''     )



def        lowerCamelCase_  (   __UpperCamelCase     ):
				if answer is None:
								return None
				try:
								A_       	=  convert_to_float(__UpperCamelCase     )
								if isinstance(__UpperCamelCase ,						__UpperCamelCase     ) and math.isnan(__UpperCamelCase     ):
												return None
								return value
				except ValueError:
								return answer.lower()


SCREAMING_SNAKE_CASE   :		Optional[Any]					 =		{
    "text": lambda x: x,
    "real": convert_to_float,
}






class 					__lowercase		(					enum.Enum       ):
					__magic_name__						:							Tuple     	=	0
					__magic_name__						:							Union[str, Any]     	=	1
					__magic_name__						:							List[str]     	=	2
					__magic_name__						:							int     	=	3
					__magic_name__						:							Optional[int]     	=	4
					__magic_name__						:							Tuple     	=	5






class 					__lowercase		(					enum.Enum       ):
					__magic_name__						:							Any     	=	0
					__magic_name__						:							str     	=	1
					__magic_name__						:							Dict     	=	2






@dataclasses.dataclass
class 					__lowercase		:
					__magic_name__						:							Text
					__magic_name__						:							_Operator
					__magic_name__						:							Any
SCREAMING_SNAKE_CASE   :		Union[str, Any]					 =		re.compile(R"\w+|[^\w\s]+", re.UNICODE | re.MULTILINE | re.DOTALL)



def        lowerCamelCase_  (   __UpperCamelCase     ):
				return list(_TOKENIZER.findall(x.lower()     )     )



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase ,						__UpperCamelCase     ):
				if operator == _Operator.EQUALS:
								return src == tgt
				elif operator == _Operator.GREATER:
								return src > tgt
				elif operator == _Operator.LESSER:
								return src < tgt
				raise ValueError(F"Unknown operator: {operator}"     )



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase ,						__UpperCamelCase     ):
				A_       	=  table['''types''']
				return _TYPE_CONVERTER[types[column]](__UpperCamelCase     )



def        lowerCamelCase_  (   __UpperCamelCase     ):
				return isinstance(__UpperCamelCase ,						__UpperCamelCase     )



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase ,						__UpperCamelCase     ):
				for cond in conditions:
								A_       	=  row[cond.column]

								A_       	=  _parse_value(__UpperCamelCase ,						cond.column ,						cond.cmp_value     )

								if _is_string(__UpperCamelCase     ) and _is_string(__UpperCamelCase     ):
												A_       	=  _normalize_for_match(__UpperCamelCase     )
												A_       	=  _normalize_for_match(__UpperCamelCase     )

								if not isinstance(__UpperCamelCase ,						type(__UpperCamelCase     )     ):
												raise ValueError('''Type difference {} != {}'''.format(type(__UpperCamelCase     ) ,						type(__UpperCamelCase     )     )     )

								if not _compare(cond.operator ,						__UpperCamelCase ,						__UpperCamelCase     ):
												return False
				return True



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase ,						__UpperCamelCase     ):
				if not answer_coordinates:
								if aggregation_op == _Aggregation.COUNT:
												return 0.0
								else:
												return EMPTY_ANSWER_AGG

    # Count can support non numeric answers.
				if aggregation_op == _Aggregation.COUNT:
								return float(len(__UpperCamelCase     )     )

				# If we have just one answer, if float returns it or try a conversion.
				A_       	=  [table['''rows'''][i][j] for (i, j) in answer_coordinates]
				if len(__UpperCamelCase     ) == 1:
								try:
												return convert_to_float(values[0]     )
								except ValueError as e:
												if aggregation_op != _Aggregation.NONE:
																raise e

				if aggregation_op == _Aggregation.NONE:
								return None

				# Other aggregation only support numeric values. Bail out if we have strings.
				if not all((isinstance(__UpperCamelCase ,						(int, float)     ) for v in values)     ):
								return None

				if aggregation_op == _Aggregation.SUM:
								return float(sum(__UpperCamelCase     )     )
				elif aggregation_op == _Aggregation.AVERAGE:
								return sum(__UpperCamelCase     ) / len(__UpperCamelCase     )
				else:
								raise ValueError(F"Unknown aggregation: {aggregation_op}"     )



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase     ):
				A_       	=  sql_query['''agg''']
				if aggregation_op_index >= 3:
								A_       	=  _Aggregation(__UpperCamelCase     )
				else:
								A_       	=  _Aggregation.NONE

				A_       	=  sql_query['''sel''']
				A_       	=  [
				    _Condition(__UpperCamelCase ,						_Operator(__UpperCamelCase     ) ,						__UpperCamelCase     )
				    for column, operator, cmp_value in zip(
				        sql_query['''conds''']['''column_index'''] ,						sql_query['''conds''']['''operator_index'''] ,						sql_query['''conds''']['''condition''']     )
				]

				A_       	=  []
				for row in range(len(table['''rows''']     )     ):
								if _respect_conditions(__UpperCamelCase ,						table['''rows'''][row] ,						__UpperCamelCase     ):
												indices.append((row, target_column)     )

				if not indices:
								return [], aggregation_op

				if len(__UpperCamelCase     ) == 1:
								return indices, aggregation_op

				# Parsing of MIN/MAX.
				if aggregation_op_index in (1, 2):
								A_       	=  {2: min, 1: max}
								A_       	=  [(table['''rows'''][i][j], index) for index, (i, j) in enumerate(__UpperCamelCase     )]
								A_       	=  functools.reduce(operators[sql_query['''agg''']] ,						__UpperCamelCase     )

								A_       	=  [indices[reduced[1]]]
								return ret, _Aggregation.NONE

				return indices, aggregation_op



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase ,						__UpperCamelCase     ):
				if float_answer is not None:
								return [str(__UpperCamelCase     )]
				return [str(table['''real_rows'''][r][c]     ) for r, c in answer_coordinates]



def        lowerCamelCase_  (   __UpperCamelCase ,						__UpperCamelCase     ):
				A_	,					A_       	=  _get_answer_coordinates(__UpperCamelCase ,						__UpperCamelCase     )
				A_       	=  _get_float_answer(__UpperCamelCase ,						__UpperCamelCase ,						__UpperCamelCase     )
				A_       	=  _get_answer_text(__UpperCamelCase ,						__UpperCamelCase ,						__UpperCamelCase     )
				# keep the original data the same with TaPas
				if len(__UpperCamelCase     ) == 0:
								A_       	=  [EMPTY_ANSWER]
				return answer_text

import math
from typing import Optional

import torch
import torch.utils.checkpoint as checkpoint
from torch import nn

from ....modeling_utils import PreTrainedModel
from ....utils import add_start_docstrings, logging
from ...bert.modeling_bert import BertModel
from .configuration_retribert import RetriBertConfig


SCREAMING_SNAKE_CASE   :		str					 =       logging.get_logger(__name__)

SCREAMING_SNAKE_CASE   :		List[str]					 =       [
    "yjernite/retribert-base-uncased",
    # See all RetriBert models at https://huggingface.co/models?filter=retribert
]






class 					__lowercase		(					A       ):
					__magic_name__						:							Any     	=	RetriBertConfig
					__magic_name__						:							Optional[Any]     	=	None
					__magic_name__						:							str     	=	'''retribert'''


					def        lowerCAmelCase_    (	self       ,       a__						)		->							int:





									'''simple docstring'''
									if isinstance(a__       ,       nn.Linear						):
													module.weight.data.normal_(mean=0.0       ,       std=self.config.initializer_range						)
													if module.bias is not None:
																	module.bias.data.zero_()
									elif isinstance(a__       ,       nn.Embedding						):
													module.weight.data.normal_(mean=0.0       ,       std=self.config.initializer_range						)
													if module.padding_idx is not None:
																	module.weight.data[module.padding_idx].zero_()
									elif isinstance(a__       ,       nn.LayerNorm						):
													module.bias.data.zero_()
													module.weight.data.fill_(1.0						)
SCREAMING_SNAKE_CASE   :		Optional[Any]					 =       R"\n\n    This model inherits from [`PreTrainedModel`]. Check the superclass documentation for the generic methods the\n    library implements for all its model (such as downloading or saving, resizing the input embeddings, pruning heads\n    etc.)\n\n    This model is also a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) subclass.\n    Use it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage\n    and behavior.\n\n    Parameters:\n        config ([`RetriBertConfig`]): Model configuration class with all the parameters of the model.\n            Initializing with a config file does not load the weights associated with the model, only the\n            configuration. Check out the [`~PreTrainedModel.from_pretrained`] method to load the model weights.\n"






@add_start_docstrings(
    '''Bert Based model to embed queries or document for document retrieval.'''							,       A							,       )
class 					__lowercase		(					A       ):


					def __init__(	self       ,       a__						)		->							None:





									'''simple docstring'''
									super().__init__(a__						)
									A_       	=  config.projection_dim

									A_       	=  BertModel(a__						)
									A_       	=  None if config.share_encoders else BertModel(a__						)
									A_       	=  nn.Dropout(config.hidden_dropout_prob						)
									A_       	=  nn.Linear(config.hidden_size       ,       config.projection_dim       ,       bias=a__						)
									A_       	=  nn.Linear(config.hidden_size       ,       config.projection_dim       ,       bias=a__						)

									A_       	=  nn.CrossEntropyLoss(reduction='''mean'''						)

									# Initialize weights and apply final processing
									self.post_init()


					def        lowerCAmelCase_    (	self       ,       a__       ,       a__       ,       a__       ,       a__=-1       ,       )		->							int:





									'''simple docstring'''
									# reproduces BERT forward pass with checkpointing
									if checkpoint_batch_size < 0 or input_ids.shape[0] < checkpoint_batch_size:
													return sent_encoder(a__       ,       attention_mask=a__						)[1]
									else:
													# prepare implicit variables
													A_       	=  input_ids.device
													A_       	=  input_ids.size()
													A_       	=  torch.zeros(a__       ,       dtype=torch.long       ,       device=a__						)
													A_       	=  [None] * sent_encoder.config.num_hidden_layers
													A_       	=  sent_encoder.get_extended_attention_mask(
													    a__       ,       a__						)

													# define function for checkpointing
													def partial_encode(*a__						):
																	A_       	=  sent_encoder.encoder(
																	    inputs[0]       ,       attention_mask=inputs[1]       ,       head_mask=a__       ,       )
																	A_       	=  encoder_outputs[0]
																	A_       	=  sent_encoder.pooler(a__						)
																	return pooled_output

													# run embedding layer on everything at once
													A_       	=  sent_encoder.embeddings(
													    input_ids=a__       ,       position_ids=a__       ,       token_type_ids=a__       ,       inputs_embeds=a__						)
													# run encoding and pooling on one mini-batch at a time
													A_       	=  []
													for b in range(math.ceil(input_ids.shape[0] / checkpoint_batch_size						)						):
																	A_       	=  embedding_output[b * checkpoint_batch_size : (b + 1) * checkpoint_batch_size]
																	A_       	=  extended_attention_mask[b * checkpoint_batch_size : (b + 1) * checkpoint_batch_size]
																	A_       	=  checkpoint.checkpoint(a__       ,       a__       ,       a__						)
																	pooled_output_list.append(a__						)
													return torch.cat(a__       ,       dim=0						)


					def        lowerCAmelCase_    (	self       ,       a__       ,       a__=None       ,       a__=-1       ,       )		->							int:





									'''simple docstring'''
									A_       	=  self.embed_sentences_checkpointed(
									    a__       ,       a__       ,       self.bert_query       ,       a__       ,       )
									return self.project_query(a__						)


					def        lowerCAmelCase_    (	self       ,       a__       ,       a__=None       ,       a__=-1       ,       )		->							Optional[Any]:





									'''simple docstring'''
									A_       	=  self.embed_sentences_checkpointed(
									    a__       ,       a__       ,       self.bert_query if self.bert_doc is None else self.bert_doc       ,       a__       ,       )
									return self.project_doc(a__						)


					def        lowerCAmelCase_    (	self       ,       a__       ,       a__       ,       a__       ,       a__       ,       a__ = -1       ,       )		->							torch.FloatTensor:





									'''simple docstring'''
									A_       	=  input_ids_query.device
									A_       	=  self.embed_questions(a__       ,       a__       ,       a__						)
									A_       	=  self.embed_answers(a__       ,       a__       ,       a__						)
									A_       	=  torch.mm(a__       ,       a_reps.t()						)
									A_       	=  self.ce_loss(a__       ,       torch.arange(compare_scores.shape[1]						).to(a__						)						)
									A_       	=  self.ce_loss(compare_scores.t()       ,       torch.arange(compare_scores.shape[0]						).to(a__						)						)
									A_       	=  (loss_qa + loss_aq) / 2
									return loss