
import copy
import os
from typing import Union

from ...configuration_utils import PretrainedConfig
from ...utils import logging


_A   =			logging.get_logger(__name__)

_A   =			{
    '''BAAI/AltCLIP''': '''https://huggingface.co/BAAI/AltCLIP/resolve/main/config.json''',
    # See all AltCLIP models at https://huggingface.co/models?filter=altclip
}







class 					lowerCamelCase		(  _UpperCAmelCase  ):
     UpperCAmelCase__    :							Optional[int]									=		'altclip_text_model'





     def __init__(self				:   Union[str, Any]    ,   _A				:   Optional[int]=2_5_0_0_0_2    ,   _A				:   Any=1_0_2_4    ,   _A				:   Optional[Any]=2_4    ,   _A				:   Tuple=1_6    ,   _A				:   Tuple=4_0_9_6    ,   _A				:   Tuple="gelu"    ,   _A				:   int=0.1    ,   _A				:   Optional[Any]=0.1    ,   _A				:   int=5_1_4    ,   _A				:   Optional[int]=1    ,   _A				:   Optional[Any]=0.02    ,   _A				:   Optional[Any]=0.02    ,   _A				:   Union[str, Any]=1E-05    ,   _A				:   Tuple=1    ,   _A				:   Optional[int]=0    ,   _A				:   List[str]=2    ,   _A				:   List[str]="absolute"    ,   _A				:   Optional[Any]=True    ,   _A				:   Optional[int]=7_6_8    ,   **_A				:   Union[str, Any]    ,   )						->						Optional[int]:
         super().__init__(pad_token_id=SCREAMING_SNAKE_CASE_    ,   bos_token_id=SCREAMING_SNAKE_CASE_    ,   eos_token_id=SCREAMING_SNAKE_CASE_    ,   **SCREAMING_SNAKE_CASE_       )

         snake_case								= vocab_size
         snake_case								= hidden_size
         snake_case								= num_hidden_layers
         snake_case								= num_attention_heads
         snake_case								= hidden_act
         snake_case								= intermediate_size
         snake_case								= hidden_dropout_prob
         snake_case								= attention_probs_dropout_prob
         snake_case								= max_position_embeddings
         snake_case								= type_vocab_size
         snake_case								= initializer_range
         snake_case								= initializer_factor
         snake_case								= layer_norm_eps
         snake_case								= position_embedding_type
         snake_case								= use_cache
         snake_case								= project_dim







class 					lowerCamelCase		(  _UpperCAmelCase  ):
     UpperCAmelCase__    :							List[Any]									=		'altclip_vision_model'





     def __init__(self				:   int    ,   _A				:   Union[str, Any]=7_6_8    ,   _A				:   Optional[int]=3_0_7_2    ,   _A				:   Optional[Any]=5_1_2    ,   _A				:   Optional[Any]=1_2    ,   _A				:   List[str]=1_2    ,   _A				:   Tuple=3    ,   _A				:   Optional[int]=2_2_4    ,   _A				:   Tuple=3_2    ,   _A				:   str="quick_gelu"    ,   _A				:   Dict=1E-5    ,   _A				:   List[Any]=0.0    ,   _A				:   Optional[Any]=0.02    ,   _A				:   List[str]=1.0    ,   **_A				:   List[str]    ,   )						->						str:
         super().__init__(**SCREAMING_SNAKE_CASE_       )

         snake_case								= hidden_size
         snake_case								= intermediate_size
         snake_case								= projection_dim
         snake_case								= num_hidden_layers
         snake_case								= num_attention_heads
         snake_case								= num_channels
         snake_case								= patch_size
         snake_case								= image_size
         snake_case								= initializer_range
         snake_case								= initializer_factor
         snake_case								= attention_dropout
         snake_case								= layer_norm_eps
         snake_case								= hidden_act





     @classmethod
     def 		UpperCAmelCase(cls				:   Optional[Any]    ,   _A				:   List[str]    ,   **_A				:   Dict       )						->						Any:
         cls._set_token_in_kwargs(SCREAMING_SNAKE_CASE_       )

         snake_case								= cls.get_config_dict(SCREAMING_SNAKE_CASE_    ,   **SCREAMING_SNAKE_CASE_       )

         # get the vision config dict if we are loading from AltCLIPConfig
         if config_dict.get("model_type"       ) == "altclip":
             snake_case								= config_dict["""vision_config"""]

         if "model_type" in config_dict and hasattr(cls    ,   "model_type"       ) and config_dict["model_type"] != cls.model_type:
             logger.warning(
                 f'You are using a model of type {config_dict["model_type"]} to instantiate a model of type '
                 f'{cls.model_type}. This is not supported for all configurations of models and can yield errors.'       )

         return cls.from_dict(SCREAMING_SNAKE_CASE_    ,   **SCREAMING_SNAKE_CASE_       )







class 					lowerCamelCase		(  _UpperCAmelCase  ):
     UpperCAmelCase__    :							int									=		'altclip'
     UpperCAmelCase__    :							str									=		True





     def __init__(self				:   Any    ,   _A				:   Union[str, Any]=None    ,   _A				:   Any=None    ,   _A				:   Union[str, Any]=7_6_8    ,   _A				:   List[Any]=2.65_92    ,   **_A				:   Optional[int]       )						->						str:
         # If `_config_dict` exist, we use them for the backward compatibility.
         # We pop out these 2 attributes before calling `super().__init__` to avoid them being saved (which causes a lot
         # of confusion!).
         snake_case								= kwargs.pop("text_config_dict"    ,   SCREAMING_SNAKE_CASE_       )
         snake_case								= kwargs.pop("vision_config_dict"    ,   SCREAMING_SNAKE_CASE_       )

         super().__init__(**SCREAMING_SNAKE_CASE_       )

         # Instead of simply assigning `[text|vision]_config_dict` to `[text|vision]_config`, we use the values in
         # `[text|vision]_config_dict` to update the values in `[text|vision]_config`. The values should be same in most
         # cases, but we don't want to break anything regarding `_config_dict` that existed before commit `8827e1b2`.
         if text_config_dict is not None:
             if text_config is None:
                 snake_case								= {}

             # This is the complete result when using `text_config_dict`.
             snake_case								= AltCLIPTextConfig(**SCREAMING_SNAKE_CASE_       ).to_dict()

             # Give a warning if the values exist in both `_text_config_dict` and `text_config` but being different.
             for key, value in _text_config_dict.items():
                 if key in text_config and value != text_config[key] and key not in ["transformers_version"]:
                     # If specified in `text_config_dict`
                     if key in text_config_dict:
                         snake_case								= (
                             f'`{key}` is found in both `text_config_dict` and `text_config` but with different values. '
                             f'The value `text_config_dict["{key}"]` will be used instead.'
                         )
                     # If inferred from default argument values (just to be super careful)
                     else:
                         snake_case								= (
                             f'`text_config_dict` is provided which will be used to initialize `AltCLIPTextConfig`. The '
                             f'value `text_config["{key}"]` will be overriden.'
                         )
                     logger.warning(SCREAMING_SNAKE_CASE_       )

            # Update all values in `text_config` with the ones in `_text_config_dict`.
             text_config.update(_text_config_dict       )

         if vision_config_dict is not None:
             if vision_config is None:
                 snake_case								= {}

             # This is the complete result when using `vision_config_dict`.
             snake_case								= AltCLIPVisionConfig(**SCREAMING_SNAKE_CASE_       ).to_dict()
             # convert keys to string instead of integer
             if "id2label" in _vision_config_dict:
                 snake_case								= {
                     str(SCREAMING_SNAKE_CASE_       ): value for key, value in _vision_config_dict["""id2label"""].items()
                 }

             # Give a warning if the values exist in both `_vision_config_dict` and `vision_config` but being different.
             for key, value in _vision_config_dict.items():
                 if key in vision_config and value != vision_config[key] and key not in ["transformers_version"]:
                     # If specified in `vision_config_dict`
                     if key in vision_config_dict:
                         snake_case								= (
                             f'`{key}` is found in both `vision_config_dict` and `vision_config` but with different '
                             f'values. The value `vision_config_dict["{key}"]` will be used instead.'
                         )
                     # If inferred from default argument values (just to be super careful)
                     else:
                         snake_case								= (
                             f'`vision_config_dict` is provided which will be used to initialize `AltCLIPVisionConfig`. '
                             f'The value `vision_config["{key}"]` will be overriden.'
                         )
                     logger.warning(SCREAMING_SNAKE_CASE_       )

            # Update all values in `vision_config` with the ones in `_vision_config_dict`.
             vision_config.update(_vision_config_dict       )

         if text_config is None:
             snake_case								= {}
             logger.info("`text_config` is `None`. Initializing the `AltCLIPTextConfig` with default values."       )

         if vision_config is None:
             snake_case								= {}
             logger.info("`vision_config` is `None`. initializing the `AltCLIPVisionConfig` with default values."       )

         snake_case								= AltCLIPTextConfig(**SCREAMING_SNAKE_CASE_       )
         snake_case								= AltCLIPVisionConfig(**SCREAMING_SNAKE_CASE_       )

         snake_case								= projection_dim
         snake_case								= logit_scale_init_value
         snake_case								= 1.0





     @classmethod
     def 		UpperCAmelCase(cls				:   Any    ,   _A				:   int    ,   _A				:   Dict    ,   **_A				:   int       )						->						Dict:
         return cls(text_config=text_config.to_dict()    ,   vision_config=vision_config.to_dict()    ,   **SCREAMING_SNAKE_CASE_       )





     def 		UpperCAmelCase(self				:   Tuple       )						->						Dict:
         snake_case								= copy.deepcopy(self.__dict__       )
         snake_case								= self.text_config.to_dict()
         snake_case								= self.vision_config.to_dict()
         snake_case								= self.__class__.model_type
         return output




from collections import defaultdict







class 					lowerCamelCase		:





     def __init__(self				:   Tuple    ,   _A				:   Optional[int]    ,   _A				:   List[str]       )						->						Union[str, Any]:
         snake_case								= total  # total no of tasks (N)

         # DP table will have a dimension of (2^M)*N
         # initially all values are set to -1
         snake_case								= [
             [-1 for i in range(total + 1       )] for j in range(2 ** len(_A       )       )
         ]

         snake_case								= defaultdict(_A       )  # stores the list of persons for each task

         # final_mask is used to check if all persons are included by setting all bits
         # to 1
         snake_case								= (1 << len(_A       )) - 1





     def 		UpperCAmelCase(self				:   str    ,   _A				:   Optional[Any]    ,   _A				:   List[Any]       )						->						str:
         # if mask == self.finalmask all persons are distributed tasks, return 1
         if mask == self.final_mask:
             return 1

         # if not everyone gets the task and no more tasks are available, return 0
         if task_no > self.total_tasks:
             return 0

         # if case already considered
         if self.dp[mask][task_no] != -1:
             return self.dp[mask][task_no]

         # Number of ways when we don't this task in the arrangement
         snake_case								= self.count_ways_until(_A    ,   task_no + 1       )

         # now assign the tasks one by one to all possible persons and recursively
         # assign for the remaining tasks.
         if task_no in self.task:
             for p in self.task[task_no]:
                 # if p is already given a task
                 if mask & (1 << p):
                     continue

                 # assign this task to p and change the mask value. And recursively
                 # assign tasks with the new mask value.
                 total_ways_util += self.count_ways_until(mask | (1 << p)    ,   task_no + 1       )

        # save the value.
         snake_case								= total_ways_util

         return self.dp[mask][task_no]





     def 		UpperCAmelCase(self				:   Any    ,   _A				:   Dict       )						->						Optional[Any]:
         # Store the list of persons for each task
         for i in range(len(_A       )       ):
             for j in task_performed[i]:
                 self.task[j].append(_A       )

        # call the function to fill the DP table, final answer is stored in dp[0][1]
         return self.count_ways_until(0    ,   1       )


if __name__ == "__main__":
   _A   =			5  # total no of tasks (the value of N)

   # the list of tasks that can be done by M persons.
   _A   =			[[1, 3, 4], [1, 2, 5], [3, 4]]
   print(
       AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
           task_performed
       )
   )

