






import enum
import inspect
from typing import Iterable, List, Optional, Tuple, Union
class 	a_(		enum.Enum	):



     """simple docstring"""



     __snake_case		:				str  					='''timm'''
     __snake_case		:				Tuple  					='''transformers'''





def 						A_					(						lowercase_	,  lowercase_	,  lowercase_			)				->Optional[Any]:







 """simple docstring"""

 if stage_names is None:
  raise ValueError('Stage_names must be set for transformers backbones'			)

 if out_features is not None:
  if not isinstance(lowercase_	,  (list,)			):
   raise ValueError(f'''out_features must be a list {type(lowercase_			)}'''			)
  if any(feat not in stage_names for feat in out_features			):
   raise ValueError(f'''out_features must be a subset of stage_names: {stage_names} got {out_features}'''			)

 if out_indices is not None:
  if not isinstance(lowercase_	,  (list, tuple)			):
   raise ValueError(f'''out_indices must be a list or tuple, got {type(lowercase_			)}'''			)
  if any(idx >= len(lowercase_			) for idx in out_indices			):
   raise ValueError('out_indices must be valid indices for stage_names {stage_names}, got {out_indices}'			)

 if out_features is not None and out_indices is not None:
  if len(lowercase_			) != len(lowercase_			):
   raise ValueError('out_features and out_indices should have the same length if both are set'			)
  if out_features != [stage_names[idx] for idx in out_indices]:
   raise ValueError('out_features and out_indices should correspond to the same stages if both are set'			)





def 						A_					(						lowercase_	,  lowercase_	,  lowercase_	,  )				->Union[str, Any]:







 """simple docstring"""

 if out_indices is None and out_features is None:
  SCREAMING_SNAKE_CASE				    =		[len(lowercase_			) - 1]
  SCREAMING_SNAKE_CASE				    =		[stage_names[-1]]
 elif out_indices is None and out_features is not None:
  SCREAMING_SNAKE_CASE				    =		[stage_names.index(lowercase_			) for layer in out_features]
 elif out_features is None and out_indices is not None:
  SCREAMING_SNAKE_CASE				    =		[stage_names[idx] for idx in out_indices]
 return out_features, out_indices





def 						A_					(						lowercase_	,  lowercase_	,  lowercase_	,  )				->Tuple[List[str], List[int]]:







 """simple docstring"""

 verify_out_features_out_indices(out_features=lowercase_	,  out_indices=lowercase_	,  stage_names=lowercase_			)
 SCREAMING_SNAKE_CASE    ,   SCREAMING_SNAKE_CASE				    =		_align_output_features_output_indices(
     out_features=lowercase_	,  out_indices=lowercase_	,  stage_names=lowercase_			)
 # Verify that the aligned out_features and out_indices are valid
 verify_out_features_out_indices(out_features=lowercase_	,  out_indices=lowercase_	,  stage_names=lowercase_			)
 return output_features, output_indices
class 	a_:



     """simple docstring"""



     __snake_case		:				Optional[BackboneType]  					=None





     def     __UpperCamelCase						(		self					:	Optional[Any]  ,  lowerCAmelCase__					:	List[str])							->	None:

      """simple docstring"""
      if getattr(self  ,  '_backbone'  ,  lowerCAmelCase__) is None:
       raise ValueError('self._backbone must be set before calling _init_timm_backbone')

      # These will diagree with the defaults for the transformers models e.g. for resnet50
      # the transformer model has out_features = ['stem', 'stage1', 'stage2', 'stage3', 'stage4']
      # the timm model has out_features = ['act', 'layer1', 'layer2', 'layer3', 'layer4']
      SCREAMING_SNAKE_CASE				    =		[stage['module'] for stage in self._backbone.feature_info.info]
      SCREAMING_SNAKE_CASE				    =		[stage['num_chs'] for stage in self._backbone.feature_info.info]
      SCREAMING_SNAKE_CASE				    =		self._backbone.feature_info.out_indices
      SCREAMING_SNAKE_CASE				    =		self._backbone.feature_info.module_name()

      # We verify the out indices and out features are valid
      verify_out_features_out_indices(
          out_features=lowerCAmelCase__  ,  out_indices=lowerCAmelCase__  ,  stage_names=self.stage_names)
      SCREAMING_SNAKE_CASE    ,   SCREAMING_SNAKE_CASE				    =		out_features, out_indices





     def     __UpperCamelCase						(		self					:	str  ,  lowerCAmelCase__					:	Dict)							->	None:

      """simple docstring"""
      SCREAMING_SNAKE_CASE				    =		getattr(lowerCAmelCase__  ,  'stage_names')
      SCREAMING_SNAKE_CASE				    =		getattr(lowerCAmelCase__  ,  'out_features'  ,  lowerCAmelCase__)
      SCREAMING_SNAKE_CASE				    =		getattr(lowerCAmelCase__  ,  'out_indices'  ,  lowerCAmelCase__)

      SCREAMING_SNAKE_CASE				    =		stage_names
      SCREAMING_SNAKE_CASE    ,   SCREAMING_SNAKE_CASE				    =		get_aligned_output_features_output_indices(
          out_features=lowerCAmelCase__  ,  out_indices=lowerCAmelCase__  ,  stage_names=lowerCAmelCase__)
      # Number of channels for each stage. This is set in the transformer backbone model init
      SCREAMING_SNAKE_CASE				    =		None





     def     __UpperCamelCase						(		self					:	Dict  ,  lowerCAmelCase__					:	int)							->	None:

      """simple docstring"""
      SCREAMING_SNAKE_CASE				    =		config

      SCREAMING_SNAKE_CASE				    =		getattr(lowerCAmelCase__  ,  'use_timm_backbone'  ,  lowerCAmelCase__)
      SCREAMING_SNAKE_CASE				    =		BackboneType.TIMM if self.use_timm_backbone else BackboneType.TRANSFORMERS

      if self.backbone_type == BackboneType.TIMM:
       self._init_timm_backbone(lowerCAmelCase__)
      elif self.backbone_type == BackboneType.TRANSFORMERS:
       self._init_transformers_backbone(lowerCAmelCase__)
      else:
       raise ValueError(f'''backbone_type {self.backbone_type} not supported.''')





     @property
     def     __UpperCamelCase						(		self					:	int)							->	Optional[int]:

      """simple docstring"""
      return self._out_features





     @out_features.setter
     def     __UpperCamelCase						(		self					:	Union[str, Any]  ,  lowerCAmelCase__					:	List[str])							->	Dict:

      """simple docstring"""
      SCREAMING_SNAKE_CASE    ,   SCREAMING_SNAKE_CASE				    =		get_aligned_output_features_output_indices(
          out_features=lowerCAmelCase__  ,  out_indices=lowerCAmelCase__  ,  stage_names=self.stage_names)





     @property
     def     __UpperCamelCase						(		self					:	str)							->	List[str]:

      """simple docstring"""
      return self._out_indices





     @out_indices.setter
     def     __UpperCamelCase						(		self					:	Tuple  ,  lowerCAmelCase__					:	Union[Tuple[int], List[int]])							->	Optional[int]:

      """simple docstring"""
      SCREAMING_SNAKE_CASE    ,   SCREAMING_SNAKE_CASE				    =		get_aligned_output_features_output_indices(
          out_features=lowerCAmelCase__  ,  out_indices=lowerCAmelCase__  ,  stage_names=self.stage_names)





     @property
     def     __UpperCamelCase						(		self					:	List[str])							->	Optional[Any]:

      """simple docstring"""
      # the current backbones will output the number of channels for each stage
      # even if that stage is not in the out_features list.
      return {stage: self.num_features[i] for i, stage in enumerate(self.stage_names)}





     @property
     def     __UpperCamelCase						(		self					:	Optional[int])							->	List[str]:

      """simple docstring"""
      return [self.out_feature_channels[name] for name in self.out_features]





     def     __UpperCamelCase						(		self					:	List[str]  ,  *lowerCAmelCase__					:	Any  ,  **lowerCAmelCase__					:	Tuple)							->	Tuple:

      """simple docstring"""
      SCREAMING_SNAKE_CASE				    =		dict(inspect.signature(self.forward).parameters)
      SCREAMING_SNAKE_CASE				    =		{k: v for k, v in kwargs.items() if k in signature}
      return self(*lowerCAmelCase__  ,  **lowerCAmelCase__)





     def     __UpperCamelCase						(		self					:	Optional[int]  ,  lowerCAmelCase__					:	Any  ,  lowerCAmelCase__					:	Optional[bool] = None  ,  lowerCAmelCase__					:	Optional[bool] = None  ,  lowerCAmelCase__					:	Optional[bool] = None  ,  )							->	Union[str, Any]:

      """simple docstring"""
      raise NotImplementedError('This method should be implemented by the derived class.')





     def     __UpperCamelCase						(		self					:	Tuple)							->	Dict:

      """simple docstring"""
      SCREAMING_SNAKE_CASE				    =		super().to_dict()
      SCREAMING_SNAKE_CASE				    =		output.pop('_out_features')
      SCREAMING_SNAKE_CASE				    =		output.pop('_out_indices')
      return output

class 	a_:



     """simple docstring"""



     @property
     def     __UpperCamelCase						(		self					:	Any)							->	Union[str, Any]:

      """simple docstring"""
      return self._out_features





     @out_features.setter
     def     __UpperCamelCase						(		self					:	Optional[Any]  ,  lowerCAmelCase__					:	List[str])							->	List[str]:

      """simple docstring"""
      SCREAMING_SNAKE_CASE    ,   SCREAMING_SNAKE_CASE				    =		get_aligned_output_features_output_indices(
          out_features=lowerCAmelCase__  ,  out_indices=lowerCAmelCase__  ,  stage_names=self.stage_names)





     @property
     def     __UpperCamelCase						(		self					:	Tuple)							->	List[str]:

      """simple docstring"""
      return self._out_indices





     @out_indices.setter
     def     __UpperCamelCase						(		self					:	Optional[Any]  ,  lowerCAmelCase__					:	Union[Tuple[int], List[int]])							->	Dict:

      """simple docstring"""
      SCREAMING_SNAKE_CASE    ,   SCREAMING_SNAKE_CASE				    =		get_aligned_output_features_output_indices(
          out_features=lowerCAmelCase__  ,  out_indices=lowerCAmelCase__  ,  stage_names=self.stage_names)





     def     __UpperCamelCase						(		self					:	str)							->	Tuple:

      """simple docstring"""
      SCREAMING_SNAKE_CASE				    =		super().to_dict()
      SCREAMING_SNAKE_CASE				    =		output.pop('_out_features')
      SCREAMING_SNAKE_CASE				    =		output.pop('_out_indices')
      return output












"""simple docstring"""





class   _lowercase			:


      def __init__(     self					:						Optional[Any]				, a					:						Union[str, Any]    ):





            """simple docstring"""







            __snake_case   :     Union[str, Any]	      =data
            __snake_case   :     Optional[Any]	      =None
            __snake_case   :     Any	      =None







      def __str__(     self					:						Any    ):





            """simple docstring"""







            return f'''{self.data}'''



class   _lowercase			:


      def __init__(     self					:						Optional[int]    ):





            """simple docstring"""







            __snake_case   :     Any	      =None
            __snake_case   :     int	      =None


      def __iter__(     self					:						int    ):





            """simple docstring"""







            __snake_case   :     List[str]	      =self.head
            while node:
                  yield node.data
                  __snake_case   :     str	      =node.next


      def __str__(     self					:						Optional[int]    ):





            """simple docstring"""







            return "->".join([str(a    ) for item in self]    )


      def __len__(     self					:						str    ):





            """simple docstring"""







            return sum(1 for _ in self    )


      def _UpperCamelCase    (     self					:						int				, a					:						List[Any]    ):





            """simple docstring"""







            self.insert_at_nth(0				, a    )


      def _UpperCamelCase    (     self					:						str				, a					:						Optional[int]    ):





            """simple docstring"""







            self.insert_at_nth(len(self    )				, a    )


      def _UpperCamelCase    (     self					:						Optional[Any]				, a					:						int				, a					:						Tuple    ):





            """simple docstring"""







            __snake_case   :     List[str]	      =len(self    )

            if not 0 <= index <= length:
                  raise IndexError('''list index out of range'''    )
            __snake_case   :     List[Any]	      =Node(a    )
            if self.head is None:
                  __snake_case   :     Dict	      =new_node
            elif index == 0:
                  __snake_case   :     Union[str, Any]	      =new_node
                  __snake_case   :     Any	      =self.head
                  __snake_case   :     List[Any]	      =new_node
            elif index == length:
                  __snake_case   :     int	      =new_node
                  __snake_case   :     Optional[Any]	      =self.tail
                  __snake_case   :     Optional[Any]	      =new_node
            else:
                  __snake_case   :     Any	      =self.head
                  for _ in range(0				, a    ):
                        __snake_case   :     Optional[Any]	      =temp.next
                  __snake_case   :     Optional[Any]	      =new_node
                  __snake_case   :     Union[str, Any]	      =temp.previous
                  __snake_case   :     List[Any]	      =temp
                  __snake_case   :     str	      =new_node


      def _UpperCamelCase    (     self					:						List[str]    ):





            """simple docstring"""







            return self.delete_at_nth(0    )


      def _UpperCamelCase    (     self					:						List[Any]    ):





            """simple docstring"""







            return self.delete_at_nth(len(self    ) - 1    )


      def _UpperCamelCase    (     self					:						Optional[int]				, a					:						int    ):





            """simple docstring"""







            __snake_case   :     Tuple	      =len(self    )

            if not 0 <= index <= length - 1:
                  raise IndexError('''list index out of range'''    )
            __snake_case   :     str	      =self.head  # default first node
            if length == 1:
                  __snake_case   :     List[Any]	      =None
            elif index == 0:
                  __snake_case   :     List[Any]	      =self.head.next
                  __snake_case   :     Optional[int]	      =None
            elif index == length - 1:
                  __snake_case   :     str	      =self.tail
                  __snake_case   :     Union[str, Any]	      =self.tail.previous
                  __snake_case   :     Optional[Any]	      =None
            else:
                  __snake_case   :     Optional[int]	      =self.head
                  for _ in range(0				, a    ):
                        __snake_case   :     List[Any]	      =temp.next
                  __snake_case   :     Union[str, Any]	      =temp
                  __snake_case   :     Optional[int]	      =temp.previous
                  __snake_case   :     int	      =temp.next
            return delete_node.data


      def _UpperCamelCase    (     self					:						List[Any]				, a					:						Any    ):





            """simple docstring"""







            __snake_case   :     Optional[int]	      =self.head

            while current.data != data:  # Find the position to delete
                  if current.next:
                        __snake_case   :     Dict	      =current.next
                  else:  # We have reached the end an no value matches
                        raise ValueError('''No data matching given value'''    )

            if current == self.head:
                  self.delete_head()

            elif current == self.tail:
                  self.delete_tail()

            else:  # Before: 1 <--> 2(current) <--> 3
                  __snake_case   :     Tuple	      =current.next  # 1 --> 3
                  __snake_case   :     Optional[Any]	      =current.previous  # 1 <--> 3
            return data







      def _UpperCamelCase    (     self					:						int    ):





            """simple docstring"""







            return len(self    ) == 0



def      __lowercase       (     )       ->       None:
      __snake_case   :     List[str]	      =DoublyLinkedList()
      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_at_nth(a							,		i + 1			)
      assert str(a			) == "->".join(str(a			) for i in range(1							,		11			)			)

      linked_list.insert_at_head(0			)
      linked_list.insert_at_tail(11			)
      assert str(a			) == "->".join(str(a			) for i in range(0							,		12			)			)

      assert linked_list.delete_head() == 0
      assert linked_list.delete_at_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			)			)


if __name__ == "__main__":
    from doctest import testmod

    testmod()


