




import glob
import os
from typing import Dict, List, Union

import torch

from diffusers.utils import is_safetensors_available


if is_safetensors_available():
      import safetensors.torch

from huggingface_hub import snapshot_download

from diffusers import DiffusionPipeline, __version__
from diffusers.schedulers.scheduling_utils import SCHEDULER_CONFIG_NAME
from diffusers.utils import CONFIG_NAME, DIFFUSERS_CACHE, ONNX_WEIGHTS_NAME, WEIGHTS_NAME






class 	A	(						_lowerCAmelCase						):
     """simple docstring"""

     def __init__(			self     :      Optional[Any]	) ->				Dict:
           self.register_to_config()
           super().__init__()




     def        __snake_case      (			self     :      str		,     A__     :      Union[str, Any]		,     A__     :      Tuple	) ->				Dict:
           if dicta == dicta:
                 return True
           else:
                 lowerCamelCase__     ,						lowerCamelCase__					     = self._remove_meta_keys(A__	)
                 lowerCamelCase__     ,						lowerCamelCase__					     = self._remove_meta_keys(A__	)
                 if configa == configa:
                       print(F"""Warning !: Mismatch in keys {meta_keysa} and {meta_keysa}."""	)
                       return True
           return False




     def        __snake_case      (			self     :      Optional[Any]		,     A__     :      Dict	) ->				Optional[Any]:
           lowerCamelCase__					     = []
           lowerCamelCase__					     = config_dict.copy()
           for key in config_dict.keys():
                 if key.startswith('_'	):
                       temp_dict.pop(A__	)
                       meta_keys.append(A__	)
           return (temp_dict, meta_keys)




     @torch.no_grad()
     def        __snake_case      (			self     :      Union[str, Any]		,     A__     :      List[Union[str, os.PathLike]]		,     **A__     :      Union[str, Any]	) ->				Union[str, Any]:
           lowerCamelCase__					     = kwargs.pop('cache_dir'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('resume_download'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('force_download'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('proxies'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('local_files_only'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('use_auth_token'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('revision'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('torch_dtype'		,     A__	)
           lowerCamelCase__					     = kwargs.pop('device_map'		,     A__	)

           lowerCamelCase__					     = kwargs.pop('alpha'		,     0.5	)
           lowerCamelCase__					     = kwargs.pop('interp'		,     A__	)

           print('Received list'		,     A__	)
           print(F"""Combining with alpha={alpha}, interpolation mode={interp}"""	)

           lowerCamelCase__					     = len(A__	)
           # Ignore result from model_index_json comparision of the two checkpoints
           lowerCamelCase__					     = kwargs.pop('force'		,     A__	)

           # If less than 2 checkpoints, nothing to merge. If more than 3, not supported for now.
           if checkpoint_count > 3 or checkpoint_count < 2:
                 raise ValueError(
                     'Received incorrect number of checkpoints to merge. Ensure that either 2 or 3 checkpoints are being'
                     ' passed.'	)

           print('Received the right number of checkpoints'	)
           # chkpt0, chkpt1 = pretrained_model_name_or_path_list[0:2]
           # chkpt2 = pretrained_model_name_or_path_list[2] if checkpoint_count == 3 else None

           # Validate that the checkpoints can be merged
           # Step 1: Load the model config and compare the checkpoints. We'll compare the model_index.json first while ignoring the keys starting with '_'
           lowerCamelCase__					     = []
           for pretrained_model_name_or_path in pretrained_model_name_or_path_list:
                 lowerCamelCase__					     = DiffusionPipeline.load_config(
                     A__		,     cache_dir=A__		,     resume_download=A__		,     force_download=A__		,     proxies=A__		,     local_files_only=A__		,     use_auth_token=A__		,     revision=A__		,     )
                 config_dicts.append(A__	)

           lowerCamelCase__					     = True
           for idx in range(1		,     len(A__	)	):
                 comparison_result &= self._compare_model_configs(config_dicts[idx - 1]		,     config_dicts[idx]	)
                 if not force and comparison_result is False:
                       raise ValueError('Incompatible checkpoints. Please check model_index.json for the models.'	)
                       print(config_dicts[0]		,     config_dicts[1]	)
           print('Compatible model_index.json files found'	)
           # Step 2: Basic Validation has succeeded. Let's download the models and save them into our local files.
           lowerCamelCase__					     = []
           for pretrained_model_name_or_path, config_dict in zip(A__		,     A__	):
                 lowerCamelCase__					     = [k for k in config_dict.keys() if not k.startswith('_'	)]
                 lowerCamelCase__					     = [os.path.join(A__		,     '*'	) for k in folder_names]
                 allow_patterns += [
                     WEIGHTS_NAME,
                     SCHEDULER_CONFIG_NAME,
                     CONFIG_NAME,
                     ONNX_WEIGHTS_NAME,
                     DiffusionPipeline.config_name,
                 ]
                 lowerCamelCase__					     = config_dict.get('_class_name'	)
                 lowerCamelCase__					     = {'diffusers': __version__, 'pipeline_class': requested_pipeline_class}

                 lowerCamelCase__					     = (
                     pretrained_model_name_or_path
                     if os.path.isdir(A__	)
                     else snapshot_download(
                         A__		,     cache_dir=A__		,     resume_download=A__		,     proxies=A__		,     local_files_only=A__		,     use_auth_token=A__		,     revision=A__		,     allow_patterns=A__		,     user_agent=A__		,     )
                 )
                 print('Cached Folder'		,     A__	)
                 cached_folders.append(A__	)

           # Step 3:-
           # Load the first checkpoint as a diffusion pipeline and modify its module state_dict in place
           lowerCamelCase__					     = DiffusionPipeline.from_pretrained(
               cached_folders[0]		,     torch_dtype=A__		,     device_map=A__	)
           final_pipe.to(self.device	)

           lowerCamelCase__					     = None
           if len(A__	) > 2:
                 lowerCamelCase__					     = os.path.join(cached_folders[2]	)

           if interp == "sigmoid":
                 lowerCamelCase__					     = CheckpointMergerPipeline.sigmoid
           elif interp == "inv_sigmoid":
                 lowerCamelCase__					     = CheckpointMergerPipeline.inv_sigmoid
           elif interp == "add_diff":
                 lowerCamelCase__					     = CheckpointMergerPipeline.add_difference
           else:
                 lowerCamelCase__					     = CheckpointMergerPipeline.weighted_sum

           # Find each module's state dict.
           for attr in final_pipe.config.keys():
                 if not attr.startswith('_'	):
                       lowerCamelCase__					     = os.path.join(cached_folders[1]		,     A__	)
                       if os.path.exists(A__	):
                             lowerCamelCase__					     = [
                                 *glob.glob(os.path.join(A__		,     '*.safetensors'	)	),
                                 *glob.glob(os.path.join(A__		,     '*.bin'	)	),
                             ]
                             lowerCamelCase__					     = files[0] if len(A__	) > 0 else None
                       if len(A__	) < 3:
                             lowerCamelCase__					     = None
                       else:
                             lowerCamelCase__					     = os.path.join(cached_folders[2]		,     A__	)
                             if os.path.exists(A__	):
                                   lowerCamelCase__					     = [
                                       *glob.glob(os.path.join(A__		,     '*.safetensors'	)	),
                                       *glob.glob(os.path.join(A__		,     '*.bin'	)	),
                                   ]
                                   lowerCamelCase__					     = files[0] if len(A__	) > 0 else None
                # For an attr if both checkpoint_path_1 and 2 are None, ignore.
                # If atleast one is present, deal with it according to interp method, of course only if the state_dict keys match.
                       if checkpoint_path_a is None and checkpoint_path_a is None:
                             print(F"""Skipping {attr}: not present in 2nd or 3d model"""	)
                             continue
                       try:
                             lowerCamelCase__					     = getattr(A__		,     A__	)
                             if isinstance(A__		,     A__	):  # ignore requires_safety_checker boolean
                                   continue
                             lowerCamelCase__					     = getattr(A__		,     'state_dict'	)
                             lowerCamelCase__					     = theta_a()

                             lowerCamelCase__					     = getattr(A__		,     'load_state_dict'	)
                             lowerCamelCase__					     = (
                                 safetensors.torch.load_file(A__	)
                                 if (is_safetensors_available() and checkpoint_path_a.endswith('.safetensors'	))
                                 else torch.load(A__		,     map_location='cpu'	)
                             )
                             lowerCamelCase__					     = None
                             if checkpoint_path_a:
                                   lowerCamelCase__					     = (
                                       safetensors.torch.load_file(A__	)
                                       if (is_safetensors_available() and checkpoint_path_a.endswith('.safetensors'	))
                                       else torch.load(A__		,     map_location='cpu'	)
                                   )

                             if not theta_a.keys() == theta_a.keys():
                                   print(F"""Skipping {attr}: key mismatch"""	)
                                   continue
                             if theta_a and not theta_a.keys() == theta_a.keys():
                                   print(F"""Skipping {attr}:y mismatch"""	)
                       except Exception as e:
                             print(F"""Skipping {attr} do to an unexpected error: {str(A__	)}"""	)
                             continue
                       print(F"""MERGING {attr}"""	)

                       for key in theta_a.keys():
                             if theta_a:
                                   lowerCamelCase__					     = theta_func(theta_a[key]		,     theta_a[key]		,     theta_a[key]		,     A__	)
                             else:
                                   lowerCamelCase__					     = theta_func(theta_a[key]		,     theta_a[key]		,     A__		,     A__	)

                       del theta_a
                       del theta_a
                       update_theta_a(A__	)

                       del theta_a
           return final_pipe




     @staticmethod
     def        __snake_case      (			A__     :      Tuple		,     A__     :      List[Any]		,     A__     :      Tuple		,     A__     :      Union[str, Any]	) ->				Union[str, Any]:
           return ((1 - alpha) * thetaa) + (alpha * thetaa)




     @staticmethod
     def        __snake_case      (			A__     :      Any		,     A__     :      Optional[int]		,     A__     :      Any		,     A__     :      Dict	) ->				Any:
           lowerCamelCase__					     = alpha * alpha * (3 - (2 * alpha))
           return thetaa + ((thetaa - thetaa) * alpha)




     @staticmethod
     def        __snake_case      (			A__     :      Any		,     A__     :      Union[str, Any]		,     A__     :      Any		,     A__     :      Optional[Any]	) ->				Any:
           import math

           lowerCamelCase__					     = 0.5 - math.sin(math.asin(1.0 - 2.0 * alpha	) / 3.0	)
           return thetaa + ((thetaa - thetaa) * alpha)




     @staticmethod
     def        __snake_case      (			A__     :      Optional[Any]		,     A__     :      Optional[int]		,     A__     :      List[str]		,     A__     :      List[Any]	) ->				Dict:
           return thetaa + (thetaa - thetaa) * (1.0 - alpha)





import os
import random
from pathlib import Path
from typing import List

import numpy as np
import torch
from torch.cuda.amp import GradScaler

from .utils import (
    MODEL_NAME,
    OPTIMIZER_NAME,
    RNG_STATE_NAME,
    SCALER_NAME,
    SCHEDULER_NAME,
    get_pretty_name,
    is_tpu_available,
    is_xpu_available,
    save,
)


if is_tpu_available(check_device=False):
      import torch_xla.core.xla_model as xm

from .logging import get_logger
from .state import PartialState


__SCREAMING_SNAKE_CASE			:      Union[str, Any]      			=get_logger(__name__)

def 	lowerCAmelCase_	(     lowerCamelCase:				str   , lowerCamelCase:				List[dict]   , lowerCamelCase:				list   , lowerCamelCase:				list   , lowerCamelCase:				int   , lowerCamelCase:				GradScaler = None   , )    ->	Any:


      '''simple docstring'''




      for i, state in enumerate(lowerCamelCase  ):
            lowerCamelCase__					     = f"""{MODEL_NAME}.bin""" if i == 0 else f"""{MODEL_NAME}_{i}.bin"""
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            save(lowerCamelCase   , lowerCamelCase  )
            logger.info(f"""Model weights saved in {output_model_file}"""  )
      # Optimizer states
      for i, opt in enumerate(lowerCamelCase  ):
            lowerCamelCase__					     = opt.state_dict()
            lowerCamelCase__					     = f"""{OPTIMIZER_NAME}.bin""" if i == 0 else f"""{OPTIMIZER_NAME}_{i}.bin"""
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            save(lowerCamelCase   , lowerCamelCase  )
            logger.info(f"""Optimizer state saved in {output_optimizer_file}"""  )
      # Scheduler states
      for i, scheduler in enumerate(lowerCamelCase  ):
            lowerCamelCase__					     = scheduler.state_dict()
            lowerCamelCase__					     = f"""{SCHEDULER_NAME}.bin""" if i == 0 else f"""{SCHEDULER_NAME}_{i}.bin"""
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            save(lowerCamelCase   , lowerCamelCase  )
            logger.info(f"""Scheduler state saved in {output_scheduler_file}"""  )
      # GradScaler state
      if scaler is not None:
            lowerCamelCase__					     = scaler.state_dict()
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            torch.save(lowerCamelCase   , lowerCamelCase  )
            logger.info(f"""Gradient scaler state saved in {output_scaler_file}"""  )
      # Random number generator states
      lowerCamelCase__					     = {}
      lowerCamelCase__					     = f"""{RNG_STATE_NAME}_{process_index}.pkl"""
      lowerCamelCase__					     = random.getstate()
      lowerCamelCase__					     = np.random.get_state()
      lowerCamelCase__					     = torch.get_rng_state()
      if is_xpu_available():
            lowerCamelCase__					     = torch.xpu.get_rng_state_all()
      else:
            lowerCamelCase__					     = torch.cuda.get_rng_state_all()
      if is_tpu_available():
            lowerCamelCase__					     = xm.get_rng_state()
      lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
      torch.save(lowerCamelCase   , lowerCamelCase  )
      logger.info(f"""Random states saved in {output_states_file}"""  )
      return output_dir

def 	lowerCAmelCase_	(     lowerCamelCase:				int   , lowerCamelCase:				Dict   , lowerCamelCase:				Union[str, Any]   , lowerCamelCase:				Any   , lowerCamelCase:				Any   , lowerCamelCase:				Any=None   , lowerCamelCase:				Dict=None   , **lowerCamelCase:				Optional[Any]   , )    ->	Any:


      '''simple docstring'''




      if map_location not in [None, "cpu", "on_device"]:
            raise TypeError(
                'Unsupported optimizer map location passed, please choose one of `None`, `\'cpu\'`, or `\'on_device\'`'  )
      if map_location is None:
            lowerCamelCase__					     = 'cpu'
      elif map_location == "on_device":
            lowerCamelCase__					     = PartialState().device
      # Model states
      for i, model in enumerate(lowerCamelCase  ):
            lowerCamelCase__					     = f"""{MODEL_NAME}.bin""" if i == 0 else f"""{MODEL_NAME}_{i}.bin"""
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            models[i].load_state_dict(torch.load(lowerCamelCase   , map_location=lowerCamelCase  )   , **lowerCamelCase  )
      logger.info('All model weights loaded successfully'  )

      # Optimizer states
      for i, opt in enumerate(lowerCamelCase  ):
            lowerCamelCase__					     = f"""{OPTIMIZER_NAME}.bin""" if i == 0 else f"""{OPTIMIZER_NAME}_{i}.bin"""
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            lowerCamelCase__					     = torch.load(lowerCamelCase   , map_location=lowerCamelCase  )
            optimizers[i].load_state_dict(lowerCamelCase  )
      logger.info('All optimizer states loaded successfully'  )

      # Scheduler states
      for i, scheduler in enumerate(lowerCamelCase  ):
            lowerCamelCase__					     = f"""{SCHEDULER_NAME}.bin""" if i == 0 else f"""{SCHEDULER_NAME}_{i}.bin"""
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            scheduler.load_state_dict(torch.load(lowerCamelCase  )  )
      logger.info('All scheduler states loaded successfully'  )

      # GradScaler state
      if scaler is not None:
            lowerCamelCase__					     = os.path.join(lowerCamelCase   , lowerCamelCase  )
            scaler.load_state_dict(torch.load(lowerCamelCase  )  )
            logger.info('GradScaler state loaded successfully'  )

      # Random states
      try:
            lowerCamelCase__					     = torch.load(os.path.join(lowerCamelCase   , f"""{RNG_STATE_NAME}_{process_index}.pkl"""  )  )
            random.setstate(states['random_state']  )
            np.random.set_state(states['numpy_random_seed']  )
            torch.set_rng_state(states['torch_manual_seed']  )
            if is_xpu_available():
                  torch.xpu.set_rng_state_all(states['torch_xpu_manual_seed']  )
            else:
                  torch.cuda.set_rng_state_all(states['torch_cuda_manual_seed']  )
            if is_tpu_available():
                  xm.set_rng_state(states['xm_seed']  )
            logger.info('All random states loaded successfully'  )
      except Exception:
            logger.info('Could not load random states'  )

def 	lowerCAmelCase_	(     lowerCamelCase:				Dict   , lowerCamelCase:				Any   , lowerCamelCase:				int = 0  )    ->	Union[str, Any]:


      '''simple docstring'''




      lowerCamelCase__					     = Path(lowerCamelCase  ) / f"""custom_checkpoint_{index}.pkl"""
      logger.info(f"""Saving the state of {get_pretty_name(lowerCamelCase  )} to {save_location}"""  )
      torch.save(obj.state_dict()   , lowerCamelCase  )


def 	lowerCAmelCase_	(     lowerCamelCase:				int   , lowerCamelCase:				Optional[int]   , lowerCamelCase:				int = 0  )    ->	Any:


      '''simple docstring'''




      lowerCamelCase__					     = f"""{path}/custom_checkpoint_{index}.pkl"""
      logger.info(f"""Loading the state of {get_pretty_name(lowerCamelCase  )} from {load_location}"""  )
      obj.load_state_dict(torch.load(lowerCamelCase   , map_location='cpu'  )  )