


import logging
import os

import quant_trainer
import torch
from torch.utils.data import DataLoader

from transformers import Trainer, is_torch_tpu_available
from transformers.trainer_utils import PredictionOutput


_lowerCAmelCase  :		Union[str, Any]		     =	logging.getLogger(__name__)

if is_torch_tpu_available(check_device=False):
				import torch_xla.core.xla_model as xm
				import torch_xla.debug.metrics as met



class  lowerCAmelCase				(				_UpperCAmelCase							):



	def __init__(					self ,					*snake_case__ ,					snake_case__=None ,					snake_case__=None ,					snake_case__=None ,					**snake_case__    ):
		super().__init__(*A_ ,					**A_    )
		lowerCAmelCase					:    str      							= eval_examples
		lowerCAmelCase					:    str      							= post_process_function
		lowerCAmelCase					:    str      							= quant_trainer_args
		lowerCAmelCase					:    str      							= 128  # default number of calibration samples



	def 				lowercase     (					self ,					snake_case__=None    ):
		if calib_dataset is None and self.calib_dataset is None:
			raise ValueError('Trainer: calibration requires an calib_dataset.'    )
		lowerCAmelCase					:    Optional[Any]      							= calib_dataset if calib_dataset is not None else self.calib_dataset

		lowerCAmelCase					:    Any      							= self._remove_unused_columns(A_ ,					description='Calibration'    )

		return DataLoader(
		    A_ ,					batch_size=self.args.eval_batch_size ,					collate_fn=self.data_collator ,					drop_last=self.args.dataloader_drop_last ,					num_workers=self.args.dataloader_num_workers ,					pin_memory=self.args.dataloader_pin_memory ,					shuffle=A_ ,					)



	def 				lowercase     (					self ,					snake_case__=None    ):
		lowerCAmelCase					:    Optional[Any]      							= self.train_dataset if calib_dataset is None else calib_dataset
		lowerCAmelCase					:    Dict      							= self.get_calib_dataloader(A_    )

		lowerCAmelCase					:    Tuple      							= self.model
		quant_trainer.configure_model(A_ ,					self.quant_trainer_args ,					calib=A_    )
		model.eval()
		quant_trainer.enable_calibration(A_    )

		logger.info('***** Running calibration *****'    )
		logger.info(f"  Num examples = {self.calib_num}"    )
		logger.info(f"  Batch size = {calib_dataloader.batch_size}"    )

		for step, inputs in enumerate(A_    ):
			# Prediction step
			lowerCAmelCase							,   lowerCAmelCase							,   lowerCAmelCase					:    List[Any]      							= self.prediction_step(A_ ,					A_ ,					prediction_loss_only=A_    )
			if (step + 1) * calib_dataloader.batch_size >= self.calib_num:
				break

		quant_trainer.finish_calibration(A_ ,					self.quant_trainer_args    )
		lowerCAmelCase					:    str      							= model



	def 				lowercase     (					self ,					snake_case__=None ,					snake_case__=None ,					snake_case__=None ,					snake_case__ = "eval"    ):
		lowerCAmelCase					:    str      							= self.eval_dataset if eval_dataset is None else eval_dataset
		lowerCAmelCase					:    str      							= self.get_eval_dataloader(A_    )
		lowerCAmelCase					:    List[Any]      							= self.eval_examples if eval_examples is None else eval_examples

		# Temporarily disable metric computation, we will do it in the loop here.
		lowerCAmelCase					:    Optional[Any]      							= self.compute_metrics
		lowerCAmelCase					:    int      							= None
		lowerCAmelCase					:    Union[str, Any]      							= self.prediction_loop if self.args.use_legacy_prediction_loop else self.evaluation_loop
		try:
			lowerCAmelCase					:    Optional[int]      							= eval_loop(
			    A_ ,					description='Evaluation' ,					prediction_loss_only=True if compute_metrics is None else None ,					ignore_keys=A_ ,					)
		finally:
			lowerCAmelCase					:    int      							= compute_metrics

		if self.post_process_function is not None and self.compute_metrics is not None:
			lowerCAmelCase					:    str      							= self.post_process_function(A_ ,					A_ ,					output.predictions    )
			lowerCAmelCase					:    Union[str, Any]      							= self.compute_metrics(A_    )

			# Prefix all keys with metric_key_prefix + '_'
			for key in list(metrics.keys()    ):
				if not key.startswith(f"{metric_key_prefix}_"    ):
					lowerCAmelCase					:    Dict      							= metrics.pop(A_    )

			self.log(A_    )
		else:
			lowerCAmelCase					:    Dict      							= {}

		if self.args.tpu_metrics_debug or self.args.debug:
			# tpu-comment: Logging debug metrics for PyTorch/XLA (compile, execute times, ops, etc.)
			xm.master_print(met.metrics_report()    )

		lowerCAmelCase					:    Dict      							= self.callback_handler.on_evaluate(self.args ,					self.state ,					self.control ,					A_    )
		return metrics



	def 				lowercase     (					self ,					snake_case__ ,					snake_case__ ,					snake_case__=None ,					snake_case__ = "test"    ):
		lowerCAmelCase					:    Optional[int]      							= self.get_test_dataloader(A_    )

		# Temporarily disable metric computation, we will do it in the loop here.
		lowerCAmelCase					:    Any      							= self.compute_metrics
		lowerCAmelCase					:    Dict      							= None
		lowerCAmelCase					:    Union[str, Any]      							= self.prediction_loop if self.args.use_legacy_prediction_loop else self.evaluation_loop
		try:
			lowerCAmelCase					:    List[Any]      							= eval_loop(
			    A_ ,					description='Prediction' ,					prediction_loss_only=True if compute_metrics is None else None ,					ignore_keys=A_ ,					)
		finally:
			lowerCAmelCase					:    Dict      							= compute_metrics

		if self.post_process_function is None or self.compute_metrics is None:
			return output

		lowerCAmelCase					:    Any      							= self.post_process_function(A_ ,					A_ ,					output.predictions ,					'predict'    )
		lowerCAmelCase					:    Dict      							= self.compute_metrics(A_    )

		# Prefix all keys with metric_key_prefix + '_'
		for key in list(metrics.keys()    ):
			if not key.startswith(f"{metric_key_prefix}_"    ):
				lowerCAmelCase					:    Optional[Any]      							= metrics.pop(A_    )

		return PredictionOutput(predictions=predictions.predictions ,					label_ids=predictions.label_ids ,					metrics=A_    )



	def 				lowercase     (					self ,					snake_case__="./"    ):
		lowerCAmelCase					:    Dict      							= self.eval_dataset
		lowerCAmelCase					:    Dict      							= self.get_eval_dataloader(A_    )

		lowerCAmelCase					:    Dict      							= next(iter(A_    )    )

		# saving device - to make it consistent
		lowerCAmelCase					:    List[str]      							= torch.device('cuda' if torch.cuda.is_available() else 'cpu'    )

		# convert to tuple
		lowerCAmelCase					:    List[Any]      							= tuple(v.to(A_    ) for k, v in batch.items()    )

		logger.info('Converting model to be onnx compatible'    )
		from pytorch_quantization.nn import TensorQuantizer

		lowerCAmelCase					:    Dict      							= True

		lowerCAmelCase					:    Any      							= self.model.to(A_    )

		model.eval()
		model.float()

		lowerCAmelCase					:    Union[str, Any]      							= model.module if hasattr(A_ ,					'module'    ) else model
		quant_trainer.configure_model(A_ ,					self.quant_trainer_args    )

		lowerCAmelCase					:    List[str]      							= os.path.join(A_ ,					'model.onnx'    )
		logger.info(f"exporting model to {output_model_file}"    )

		lowerCAmelCase					:    List[str]      							= {0: 'batch_size', 1: 'seq_len'}

		torch.onnx.export(
		    A_ ,					A_ ,					A_ ,					export_params=A_ ,					opset_version=13 ,					do_constant_folding=A_ ,					input_names=['input_ids', 'attention_mask', 'token_type_ids'] ,					output_names=['output_start_logits', 'output_end_logits'] ,					dynamic_axes={
		        'input_ids': axes,
		        'attention_mask': axes,
		        'token_type_ids': axes,
		        'output_start_logits': axes,
		        'output_end_logits': axes,
		    } ,					verbose=A_ ,					)
		logger.info('onnx export finished'    )




'''simple docstring'''




from typing import Any



class  lowerCAmelCase				:



	def __init__(					self ,					snake_case__    ):
		lowerCAmelCase					:    Optional[int]      							= data
		lowerCAmelCase					:    Optional[Any]      							= None



	def __repr__(					self    ):
		return f"Node({self.data})"



class  lowerCAmelCase				:



	def __init__(					self    ):
		lowerCAmelCase					:    Dict      							= None



	def __iter__(					self    ):
		lowerCAmelCase					:    Optional[Any]      							= self.head
		while node:
			yield node.data
			lowerCAmelCase					:    Optional[int]      							= node.next



	def __len__(					self    ):
		return sum(1 for _ in self    )



	def __repr__(					self    ):
		return "->".join([str(snake_case__    ) for item in self]    )



	def __getitem__(					self ,					snake_case__    ):
		if not 0 <= index < len(self    ):
			raise ValueError('list index out of range.'    )
		for i, node in enumerate(self    ):
			if i == index:
				return node
		return None



	def __setitem__(					self ,					snake_case__ ,					snake_case__    ):
		if not 0 <= index < len(self    ):
			raise ValueError('list index out of range.'    )
		lowerCAmelCase					:    Any      							= self.head
		for _ in range(snake_case__    ):
			lowerCAmelCase					:    List[str]      							= current.next
		lowerCAmelCase					:    int      							= data



	def 				lowercase     (					self ,					snake_case__    ):
		self.insert_nth(len(self    ) ,					snake_case__    )



	def 				lowercase     (					self ,					snake_case__    ):
		self.insert_nth(0 ,					snake_case__    )



	def 				lowercase     (					self ,					snake_case__ ,					snake_case__    ):
		if not 0 <= index <= len(self    ):
			raise IndexError('list index out of range'    )
		lowerCAmelCase					:    List[str]      							= Node(snake_case__    )
		if self.head is None:
			lowerCAmelCase					:    int      							= new_node
		elif index == 0:
			lowerCAmelCase					:    List[Any]      							= self.head  # link new_node to head
			lowerCAmelCase					:    List[Any]      							= new_node
		else:
			lowerCAmelCase					:    List[Any]      							= self.head
			for _ in range(index - 1    ):
				lowerCAmelCase					:    Union[str, Any]      							= temp.next
			lowerCAmelCase					:    Any      							= temp.next
			lowerCAmelCase					:    str      							= new_node



	def 				lowercase     (					self    ):  # print every node data
		print(self    )



	def 				lowercase     (					self    ):
		return self.delete_nth(0    )



	def 				lowercase     (					self    ):  # delete from tail
		return self.delete_nth(len(self    ) - 1    )



	def 				lowercase     (					self ,					snake_case__ = 0    ):
		if not 0 <= index <= len(self    ) - 1:  # test if index is valid
			raise IndexError('List index out of range.'    )
		lowerCAmelCase					:    List[str]      							= self.head  # default first node
		if index == 0:
			lowerCAmelCase					:    Tuple      							= self.head.next
		else:
			lowerCAmelCase					:    Dict      							= self.head
			for _ in range(index - 1    ):
				lowerCAmelCase					:    Tuple      							= temp.next
			lowerCAmelCase					:    Dict      							= temp.next
			lowerCAmelCase					:    Tuple      							= temp.next.next
		return delete_node.data



	def 				lowercase     (					self    ):
		return self.head is None



	def 				lowercase     (					self    ):
		lowerCAmelCase					:    List[Any]      							= None
		lowerCAmelCase					:    Any      							= self.head

		while current:
			# Store the current node's next node.
			lowerCAmelCase					:    List[str]      							= current.next
			# Make the current node's next point backwards
			lowerCAmelCase					:    int      							= prev
			# Make the previous node be the current node
			lowerCAmelCase					:    int      							= current
			# Make the current node the next node (to progress iteration)
			lowerCAmelCase					:    Optional[Any]      							= next_node
		# Return prev in order to put the head at the end
		lowerCAmelCase					:    List[Any]      							= prev


def 			__UpperCamelCase    (    )    ->      None:




	"""simple docstring"""





	lowerCAmelCase					:    Tuple      							= LinkedList()
	assert linked_list.is_empty() is True
	assert str(_A				) == ""

	try:
		linked_list.delete_head()
		raise AssertionError  # This should not happen.
	except IndexError:
		assert True  # This should happen.

	try:
		linked_list.delete_tail()
		raise AssertionError  # This should not happen.
	except IndexError:
		assert True  # This should happen.

	for i in range(10				):
		assert len(_A				) == i
		linked_list.insert_nth(_A					,   i + 1				)
	assert str(_A				) == "->".join(str(_A				) for i in range(1					,   11				)				)

	linked_list.insert_head(0				)
	linked_list.insert_tail(11				)
	assert str(_A				) == "->".join(str(_A				) for i in range(0					,   12				)				)

	assert linked_list.delete_head() == 0
	assert linked_list.delete_nth(9				) == 10
	assert linked_list.delete_tail() == 11
	assert len(_A				) == 9
	assert str(_A				) == "->".join(str(_A				) for i in range(1					,   10				)				)

	assert all(linked_list[i] == i + 1 for i in range(0					,   9				)				) is True

	for i in range(0					,   9				):
		lowerCAmelCase					:    Optional[Any]      							= -i
	assert all(linked_list[i] == -i for i in range(0					,   9				)				) is True

	linked_list.reverse()
	assert str(_A				) == "->".join(str(_A				) for i in range(-8					,   1				)				)

def 			__UpperCamelCase    (    )    ->      None:




	"""simple docstring"""





	lowerCAmelCase					:    Optional[int]      							= [
	    -9,
	    1_00,
	    Node(77_34_51_12				),
	    'dlrow olleH',
	    7,
	    55_55,
	    0,
	    -1_92.5_55_55,
	    'Hello, world!',
	    77.9,
	    Node(10				),
	    None,
	    None,
	    12.20,
	]
	lowerCAmelCase					:    Dict      							= LinkedList()

	for i in test_input:
		linked_list.insert_tail(_A				)

	# Check if it's empty or not
	assert linked_list.is_empty() is False
	assert (
	    str(_A				) == "-9->100->Node(77345112)->dlrow olleH->7->5555->0->"
	    "-192.55555->Hello, world!->77.9->Node(10)->None->None->12.2"
	)

	# Delete the head
	lowerCAmelCase					:    Optional[Any]      							= linked_list.delete_head()
	assert result == -9
	assert (
	    str(_A				) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
	    "Hello, world!->77.9->Node(10)->None->None->12.2"
	)

	# Delete the tail
	lowerCAmelCase					:    List[str]      							= linked_list.delete_tail()
	assert result == 12.2
	assert (
	    str(_A				) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
	    "Hello, world!->77.9->Node(10)->None->None"
	)

	# Delete a node in specific location in linked list
	lowerCAmelCase					:    List[str]      							= linked_list.delete_nth(10				)
	assert result is None
	assert (
	    str(_A				) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
	    "Hello, world!->77.9->Node(10)->None"
	)

	# Add a Node instance to its head
	linked_list.insert_head(Node('Hello again, world!'				)				)
	assert (
	    str(_A				)
	    == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->"
	    "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None"
	)

	# Add None to its tail
	linked_list.insert_tail(_A				)
	assert (
	    str(_A				)
	    == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->"
	    "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None->None"
	)

	# Reverse the linked list
	linked_list.reverse()
	assert (
	    str(_A				)
	    == "None->None->Node(10)->77.9->Hello, world!->-192.55555->0->5555->"
	    "7->dlrow olleH->Node(77345112)->100->Node(Hello again, world!)"
	)

def 			__UpperCamelCase    (    )    ->      List[Any]:




	"""simple docstring"""





	from doctest import testmod

	testmod()

	lowerCAmelCase					:    Optional[Any]      							= LinkedList()
	linked_list.insert_head(input('Inserting 1st at head '				).strip()				)
	linked_list.insert_head(input('Inserting 2nd at head '				).strip()				)
	print('\nPrint list:'				)
	linked_list.print_list()
	linked_list.insert_tail(input('\nInserting 1st at tail '				).strip()				)
	linked_list.insert_tail(input('Inserting 2nd at tail '				).strip()				)
	print('\nPrint list:'				)
	linked_list.print_list()
	print('\nDelete head'				)
	linked_list.delete_head()
	print('Delete tail'				)
	linked_list.delete_tail()
	print('\nPrint list:'				)
	linked_list.print_list()
	print('\nReverse linked list'				)
	linked_list.reverse()
	print('\nPrint list:'				)
	linked_list.print_list()
	print('\nString representation of linked list:'				)
	print(_A				)
	print('\nReading/changing Node data using indexing:'				)
	print(F"Element at Position 1: {linked_list[1]}"				)
	lowerCAmelCase					:    Tuple      							= input('Enter New Value: '				).strip()
	print('New list:'				)
	print(_A				)
	print(F"length of linked_list is : {len(_A				)}"				)


if __name__ == "__main__":
				main()
