






import importlib.metadata
import warnings
from copy import deepcopy

from packaging import version

from ..utils import logging
from .import_utils import is_accelerate_available, is_bitsandbytes_available


if is_bitsandbytes_available():
			import bitsandbytes as bnb
			import torch
			import torch.nn as nn

			from ..pytorch_utils import ConvaD

if is_accelerate_available():
			from accelerate import init_empty_weights
			from accelerate.utils import find_tied_parameters

UpperCAmelCase__      			=						logging.get_logger(__name__)







def     a_   (__A				,       __A				,       __A				,       __A=None				,       __A=None      )				->						Optional[Any]:



					"""simple docstring"""
					# Recurse if needed
					if "." in tensor_name:
										__a					:						int      =					tensor_name.split("."      )
										for split in splits[:-1]:
															__a					:						Tuple      =					getattr(__A				,       __A      )
															if new_module is None:
																				raise ValueError(f'{module} has no attribute {split}.'      )
															__a					:						Any      =					new_module
										__a					:						Optional[Any]      =					splits[-1]

					if tensor_name not in module._parameters and tensor_name not in module._buffers:
										raise ValueError(f'{module} does not have a parameter or a buffer named {tensor_name}.'      )
					__a					:						Optional[Any]      =					tensor_name in module._buffers
					__a					:						Tuple      =					getattr(__A				,       __A      )

					if old_value.device == torch.device("meta"      ) and device not in ["meta", torch.device("meta"      )] and value is None:
										raise ValueError(f'{tensor_name} is on the meta device, we need a `value` to put in on {device}.'      )

					__a					:						List[str]      =					False
					__a					:						int      =					False
					if is_buffer or not is_bitsandbytes_available():
										__a					:						List[Any]      =					False
										__a					:						Dict      =					False
					else:
										__a					:						int      =					hasattr(bnb.nn				,       "Params4bit"      ) and isinstance(module._parameters[tensor_name]				,       bnb.nn.Paramsabit      )
										__a					:						Optional[Any]      =					isinstance(module._parameters[tensor_name]				,       bnb.nn.IntaParams      )

					if is_abit or is_abit:
										__a					:						str      =					module._parameters[tensor_name]
										if param.device.type != "cuda":
															if value is None:
																				__a					:						Any      =					old_value.to(__A      )
															elif isinstance(__A				,       torch.Tensor      ):
																				__a					:						str      =					value.to("cpu"      )
																				if value.dtype == torch.inta:
																									__a					:						Dict      =					version.parse(importlib.metadata.version("bitsandbytes"      )      ) > version.parse(
																									    "0.37.2"      )
																									if not is_abit_serializable:
																														raise ValueError(
																														    "Detected int8 weights but the version of bitsandbytes is not compatible with int8 serialization. "
																														    "Make sure to download the latest `bitsandbytes` version. `pip install --upgrade bitsandbytes`."      )
															else:
																				__a					:						Optional[Any]      =					torch.tensor(__A				,       device="cpu"      )

															# Support models using `Conv1D` in place of `nn.Linear` (e.g. gpt2) by transposing the weight matrix prior to quantization.
															# Since weights are saved in the correct "orientation", we skip transposing when loading.
															if issubclass(module.source_cls				,       __A      ) and fpaa_statistics is None:
																				__a					:						List[Any]      =					new_value.T

															__a					:						Union[str, Any]      =					old_value.__dict__
															if is_abit:
																				__a					:						Union[str, Any]      =					bnb.nn.IntaParams(__A				,       requires_grad=__A				,       **__A      ).to(__A      )
															elif is_abit:
																				__a					:						Tuple      =					bnb.nn.Paramsabit(__A				,       requires_grad=__A				,       **__A      ).to(__A      )

															__a					:						int      =					new_value
															if fpaa_statistics is not None:
																				setattr(module.weight				,       "SCB"				,       fpaa_statistics.to(__A      )      )

					else:
										if value is None:
															__a					:						Optional[Any]      =					old_value.to(__A      )
										elif isinstance(__A				,       torch.Tensor      ):
															__a					:						Dict      =					value.to(__A      )
										else:
															__a					:						str      =					torch.tensor(__A				,       device=__A      )

										if is_buffer:
															__a					:						Tuple      =					new_value
										else:
															__a					:						int      =					nn.Parameter(__A				,       requires_grad=old_value.requires_grad      )
															__a					:						Tuple      =					new_value







def     a_   (__A				,       __A=None				,       __A=None				,       __A=None				,       __A=False      )				->						List[Any]:



					"""simple docstring"""
					for name, module in model.named_children():
										if current_key_name is None:
															__a					:						Union[str, Any]      =					[]
										current_key_name.append(__A      )

										if (isinstance(__A				,       nn.Linear      ) or isinstance(__A				,       __A      )) and name not in modules_to_not_convert:
															# Check if the current key is not in the `modules_to_not_convert`
															if not any(key in ".".join(__A      ) for key in modules_to_not_convert      ):
																				with init_empty_weights():
																									if isinstance(__A				,       __A      ):
																														__a      ,			__a					:						Optional[Any]      =					module.weight.shape
																									else:
																														__a					:						str      =					module.in_features
																														__a					:						int      =					module.out_features

																									if quantization_config.quantization_method() == "llm_int8":
																														__a					:						Union[str, Any]      =					bnb.nn.LinearabitLt(
																														    __A				,       __A				,       module.bias is not None				,       has_fpaa_weights=quantization_config.llm_inta_has_fpaa_weight				,       threshold=quantization_config.llm_inta_threshold				,       )
																														__a					:						Union[str, Any]      =					True
																									else:
																														if (
																														    quantization_config.llm_inta_skip_modules is not None
																														    and name in quantization_config.llm_inta_skip_modules
																														):
																																			pass
																														else:
																																			__a					:						Dict      =					bnb.nn.Linearabit(
																																			    __A				,       __A				,       module.bias is not None				,       quantization_config.bnb_abit_compute_dtype				,       compress_statistics=quantization_config.bnb_abit_use_double_quant				,       quant_type=quantization_config.bnb_abit_quant_type				,       )
																																			__a					:						Tuple      =					True
                    # Store the module class in case we need to transpose the weight later
																									__a					:						Tuple      =					type(__A      )
																									# Force requires grad to False to avoid unexpected errors
																									model._modules[name].requires_grad_(__A      )
										if len(list(module.children()      )      ) > 0:
															__a      ,			__a					:						Optional[Any]      =					_replace_with_bnb_linear(
															    __A				,       __A				,       __A				,       __A				,       has_been_replaced=__A				,       )
										# Remove the last key for recursion
										current_key_name.pop(-1      )
					return model, has_been_replaced







def     a_   (__A				,       __A=None				,       __A=None				,       __A=None      )				->						Optional[Any]:



					"""simple docstring"""
					__a					:						Optional[Any]      =					["lm_head"] if modules_to_not_convert is None else modules_to_not_convert
					__a      ,			__a					:						Dict      =					_replace_with_bnb_linear(
					    __A				,       __A				,       __A				,       __A      )

					if not has_been_replaced:
										logger.warning(
										    "You are loading your model in 8bit or 4bit but no linear modules were found in your model."
										    " Please double check your model architecture, or submit an issue on github if you think this is"
										    " a bug."      )

					return model







def     a_   (*__A				,       **__A      )				->						Any:



					"""simple docstring"""
					warnings.warn(
					    "`replace_8bit_linear` will be deprecated in a future version, please use `replace_with_bnb_linear` instead"				,       __A				,       )
					return replace_with_bnb_linear(*__A				,       **__A      )







def     a_   (*__A				,       **__A      )				->						List[Any]:



					"""simple docstring"""
					warnings.warn(
					    "`set_module_8bit_tensor_to_device` will be deprecated in a future version, please use `set_module_quantized_tensor_to_device` instead"				,       __A				,       )
					return set_module_quantized_tensor_to_device(*__A				,       **__A      )







def     a_   (__A      )				->						Union[str, Any]:



					"""simple docstring"""
					__a					:						int      =					deepcopy(__A      )  # this has 0 cost since it is done inside `init_empty_weights` context manager`
					tied_model.tie_weights()

					__a					:						List[str]      =					find_tied_parameters(__A      )
					# For compatibility with Accelerate < 0.18
					if isinstance(__A				,       __A      ):
										__a					:						Optional[int]      =					sum(list(tied_params.values()      )				,       []      ) + list(tied_params.keys()      )
					else:
										__a					:						Optional[Any]      =					sum(__A				,       []      )
					__a					:						Tuple      =					len(__A      ) > 0

					# Check if it is a base model
					__a					:						List[Any]      =					not hasattr(__A				,       model.base_model_prefix      )

					# Ignore this for base models (BertModel, GPT2Model, etc.)
					if (not has_tied_params) and is_base_model:
										return []

					# otherwise they have an attached head
					__a					:						Optional[int]      =					list(model.named_children()      )
					__a					:						Optional[Any]      =					[list_modules[-1][0]]

					# add last module together with tied weights
					__a					:						Dict      =					set(__A      ) - set(__A      )
					__a					:						str      =					list(set(__A      )      ) + list(__A      )

					# remove ".weight" from the keys
					__a					:						str      =					[".weight", ".bias"]
					__a					:						Tuple      =					[]
					for name in list_untouched:
										for name_to_remove in names_to_remove:
															if name_to_remove in name:
																				__a					:						Dict      =					name.replace(__A				,       ""      )
										filtered_module_names.append(__A      )

					return filtered_module_names













def     a_   (__A      )				->						Dict:



					"""simple docstring"""
					if not head:
										return True
					# split the list to two parts
					__a      ,			__a					:						Any      =					head.next, head
					while fast and fast.next:
										__a					:						Optional[int]      =					fast.next.next
										__a					:						Optional[int]      =					slow.next
					__a					:						Optional[int]      =					slow.next
					__a					:						Tuple      =					None  # Don't forget here! But forget still works!
					# reverse the second part
					__a					:						Any      =					None
					while second:
										__a					:						int      =					second.next
										__a					:						int      =					node
										__a					:						Union[str, Any]      =					second
										__a					:						Union[str, Any]      =					nxt
					# compare two parts
					# second part has the same or one less node
					while node:
										if node.val != head.val:
															return False
										__a					:						int      =					node.next
										__a					:						Dict      =					head.next
					return True







def     a_   (__A      )				->						Union[str, Any]:



					"""simple docstring"""
					if not head or not head.next:
										return True

					# 1. Get the midpoint (slow)
					__a					:						Union[str, Any]      =					head
					while fast and fast.next:
										__a      ,			__a					:						List[str]      =					fast.next.next, slow.next

					# 2. Push the second half into the stack
					__a					:						Dict      =					[slow.val]
					while slow.next:
										__a					:						Optional[Any]      =					slow.next
										stack.append(slow.val      )

					# 3. Comparison
					while stack:
										if stack.pop() != cur.val:
															return False
										__a					:						List[str]      =					cur.next

					return True







def     a_   (__A      )				->						List[str]:



					"""simple docstring"""
					if not head or not head.next:
										return True
					__a					:						Optional[int]      =					{}
					__a					:						Optional[int]      =					0
					while head:
										if head.val in d:
															d[head.val].append(__A      )
										else:
															__a					:						Dict      =					[pos]
										__a					:						Dict      =					head.next
										pos += 1
					__a					:						Dict      =					pos - 1
					__a					:						Optional[int]      =					0
					for v in d.values():
										if len(__A      ) % 2 != 0:
															middle += 1
										else:
															__a					:						Dict      =					0
															for i in range(0				,       len(__A      )      ):
																				if v[i] + v[len(__A      ) - 1 - step] != checksum:
																									return False
																				step += 1
										if middle > 1:
															return False
					return True





