





"""simple docstring"""





import logging
import math
from functools import partial
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Union

import torch

from .tensor_utils import tensor_tree_map, tree_map



def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				Tuple ):


							'''simple docstring'''







							__lowerCamelCase   :   str       =[]
							if isinstance(__snake_case     ,    __snake_case ):
														for v in tree.values():
																					shapes.extend(_fetch_dims(__snake_case ) )
							elif isinstance(__snake_case     ,    (list, tuple) ):
														for t in tree:
																					shapes.extend(_fetch_dims(__snake_case ) )
							elif isinstance(__snake_case     ,    torch.Tensor ):
														shapes.append(tree.shape )
							else:
														raise ValueError('''Not supported''' )

							return shapes



@torch.jit.ignore
def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				Union[str, Any]     ,    SCREAMING_SNAKE_CASE							:				int ):


							'''simple docstring'''







							__lowerCamelCase   :   Union[str, Any]       =[]
							for d in reversed(__snake_case ):
														idx.append(flat_idx % d )
														__lowerCamelCase   :   Optional[Any]       =flat_idx // d

							return tuple(reversed(__snake_case ) )



@torch.jit.ignore
def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				List[Any]     ,    SCREAMING_SNAKE_CASE							:				Tuple     ,    SCREAMING_SNAKE_CASE							:				str     ,    SCREAMING_SNAKE_CASE							:				Tuple = None     ,    SCREAMING_SNAKE_CASE							:				List[str] = None     ,    ):


							'''simple docstring'''







							def reduce_edge_list(SCREAMING_SNAKE_CASE							:				Tuple ) -> None:
														__lowerCamelCase   :   int       =True
														for i in range(len(__snake_case ) ):
																					__lowerCamelCase   :   str       =-1 * (i + 1)
																					l[reversed_idx] &= tally
																					__lowerCamelCase   :   Optional[int]       =l[reversed_idx]

							if start_edges is None:
														__lowerCamelCase   :   Union[str, Any]       =[s == 0 for s in start]
														reduce_edge_list(__snake_case )
							if end_edges is None:
														__lowerCamelCase   :   Union[str, Any]       =[e == (d - 1) for e, d in zip(__snake_case     ,    __snake_case )]
														reduce_edge_list(__snake_case )

							# Base cases. Either start/end are empty and we're done, or the final,
							# one-dimensional tensor can be simply sliced
							if len(__snake_case ) == 0:
														return [()]
							elif len(__snake_case ) == 1:
														return [(slice(start[0]     ,    end[0] + 1 ),)]

							__lowerCamelCase   :   List[Tuple[slice, ...]]       =[]
							__lowerCamelCase   :   List[slice]       =[]

							# Dimensions common to start and end can be selected directly
							for s, e in zip(__snake_case     ,    __snake_case ):
														if s == e:
																					path_list.append(slice(__snake_case     ,    s + 1 ) )
														else:
																					break

							__lowerCamelCase   :   Tuple[slice, ...]       =tuple(__snake_case )
							__lowerCamelCase   :   Optional[int]       =len(__snake_case )

							# start == end, and we're done
							if divergence_idx == len(__snake_case ):
														return [path]

							def upper() -> Tuple[Tuple[slice, ...], ...]:
														assert start_edges is not None
														assert end_edges is not None

														__lowerCamelCase   :   Optional[int]       =start[divergence_idx]
														return tuple(
														    path + (slice(__snake_case     ,    sdi + 1 ),) + s
														    for s in _get_minimal_slice_set(
														        start[divergence_idx + 1 :]     ,    [d - 1 for d in dims[divergence_idx + 1 :]]     ,    dims[divergence_idx + 1 :]     ,    start_edges=start_edges[divergence_idx + 1 :]     ,    end_edges=[True for _ in end_edges[divergence_idx + 1 :]]     ,    ) )

							def lower() -> Tuple[Tuple[slice, ...], ...]:
														assert start_edges is not None
														assert end_edges is not None

														__lowerCamelCase   :   Any       =end[divergence_idx]
														return tuple(
														    path + (slice(__snake_case     ,    edi + 1 ),) + s
														    for s in _get_minimal_slice_set(
														        [0 for _ in start[divergence_idx + 1 :]]     ,    end[divergence_idx + 1 :]     ,    dims[divergence_idx + 1 :]     ,    start_edges=[True for _ in start_edges[divergence_idx + 1 :]]     ,    end_edges=end_edges[divergence_idx + 1 :]     ,    ) )

							# If both start and end are at the edges of the subtree rooted at
							# divergence_idx, we can just select the whole subtree at once
							if start_edges[divergence_idx] and end_edges[divergence_idx]:
														slices.append(path + (slice(start[divergence_idx]     ,    end[divergence_idx] + 1 ),) )
							# If just start is at the edge, we can grab almost all of the subtree,
							# treating only the ragged bottom edge as an edge case
							elif start_edges[divergence_idx]:
														slices.append(path + (slice(start[divergence_idx]     ,    end[divergence_idx] ),) )
														slices.extend(lower() )
							# Analogous to the previous case, but the top is ragged this time
							elif end_edges[divergence_idx]:
														slices.extend(upper() )
														slices.append(path + (slice(start[divergence_idx] + 1     ,    end[divergence_idx] + 1 ),) )
							# If both sides of the range are ragged, we need to handle both sides
							# separately. If there's contiguous meat in between them, we can index it
							# in one big chunk
							else:
														slices.extend(upper() )
														__lowerCamelCase   :   str       =end[divergence_idx] - start[divergence_idx]
														if middle_ground > 1:
																					slices.append(path + (slice(start[divergence_idx] + 1     ,    end[divergence_idx] ),) )
														slices.extend(lower() )

							return slices



@torch.jit.ignore
def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				Optional[int]     ,    SCREAMING_SNAKE_CASE							:				Dict     ,    SCREAMING_SNAKE_CASE							:				List[str]     ,    SCREAMING_SNAKE_CASE							:				Optional[Any] ):


							'''simple docstring'''







							__lowerCamelCase   :   str       =t.shape[:no_batch_dims]
							__lowerCamelCase   :   Optional[int]       =list(_flat_idx_to_idx(__snake_case     ,    __snake_case ) )
							# _get_minimal_slice_set is inclusive
							__lowerCamelCase   :   int       =list(_flat_idx_to_idx(flat_end - 1     ,    __snake_case ) )

							# Get an ordered list of slices to perform
							__lowerCamelCase   :   Optional[int]       =_get_minimal_slice_set(
							    __snake_case     ,    __snake_case     ,    __snake_case     ,    )

							__lowerCamelCase   :   Union[str, Any]       =[t[s] for s in slices]

							return torch.cat([s.view((-1,) + t.shape[no_batch_dims:] ) for s in sliced_tensors] )



def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				Optional[int]     ,    SCREAMING_SNAKE_CASE							:				Tuple     ,    SCREAMING_SNAKE_CASE							:				Optional[Any]     ,    SCREAMING_SNAKE_CASE							:				int     ,    SCREAMING_SNAKE_CASE							:				int = False     ,    SCREAMING_SNAKE_CASE							:				Optional[int] = None     ,    SCREAMING_SNAKE_CASE							:				Optional[int] = False     ,    ):


							'''simple docstring'''







							if not (len(__snake_case ) > 0):
														raise ValueError('''Must provide at least one input''' )

							__lowerCamelCase   :   List[Any]       =[shape[:no_batch_dims] for shape in _fetch_dims(__snake_case )]
							__lowerCamelCase   :   Any       =tuple([max(__snake_case ) for s in zip(*__snake_case )] )

							def _prep_inputs(SCREAMING_SNAKE_CASE							:				str ) -> torch.Tensor:
														if not low_mem:
																					if not sum(t.shape[:no_batch_dims] ) == no_batch_dims:
																												__lowerCamelCase   :   int       =t.expand(orig_batch_dims + t.shape[no_batch_dims:] )
																					__lowerCamelCase   :   Tuple       =t.reshape(-1     ,    *t.shape[no_batch_dims:] )
														else:
																					__lowerCamelCase   :   Optional[Any]       =t.expand(orig_batch_dims + t.shape[no_batch_dims:] )
														return t

							__lowerCamelCase   :   Dict[str, Any]       =tensor_tree_map(_prep_inputs     ,    __snake_case )
							__lowerCamelCase   :   Optional[Any]       =None
							if _out is not None:
														__lowerCamelCase   :   Optional[int]       =tensor_tree_map(lambda SCREAMING_SNAKE_CASE : t.view([-1] + list(t.shape[no_batch_dims:] ) )     ,    _out )

							__lowerCamelCase   :   Optional[Any]       =1
							for d in orig_batch_dims:
														flat_batch_dim *= d

							__lowerCamelCase   :   Tuple       =flat_batch_dim // chunk_size + (flat_batch_dim % chunk_size != 0)

							def _select_chunk(SCREAMING_SNAKE_CASE							:				Any ) -> torch.Tensor:
														return t[i : i + chunk_size] if t.shape[0] != 1 else t

							__lowerCamelCase   :   int       =0
							__lowerCamelCase   :   List[str]       =prepped_outputs
							for _ in range(__snake_case ):
														# Chunk the input
														if not low_mem:
																					__lowerCamelCase   :   Union[str, Any]       =_select_chunk
														else:
																					__lowerCamelCase   :   Union[str, Any]       =partial(
																					    _chunk_slice     ,    flat_start=__snake_case     ,    flat_end=min(__snake_case     ,    i + chunk_size )     ,    no_batch_dims=len(__snake_case )     ,    )

														__lowerCamelCase   :   Dict[str, Any]       =tensor_tree_map(__snake_case     ,    __snake_case )

														# Run the layer on the chunk
														__lowerCamelCase   :   List[str]       =layer(**__snake_case )

														# Allocate space for the output
														if out is None:
																					__lowerCamelCase   :   Tuple       =tensor_tree_map(lambda SCREAMING_SNAKE_CASE : t.new_zeros((flat_batch_dim,) + t.shape[1:] )     ,    __snake_case )

														# Put the chunk in its pre-allocated space
														if isinstance(__snake_case     ,    __snake_case ):

																					def assign(SCREAMING_SNAKE_CASE							:				Optional[Any]     ,    SCREAMING_SNAKE_CASE							:				str ) -> None:
																												for k, v in da.items():
																																			if isinstance(__snake_case     ,    __snake_case ):
																																										assign(__snake_case     ,    da[k] )
																																			else:
																																										if _add_into_out:
																																																	v[i : i + chunk_size] += da[k]
																																										else:
																																																	__lowerCamelCase   :   Union[str, Any]       =da[k]

																					assign(__snake_case     ,    __snake_case )
														elif isinstance(__snake_case     ,    __snake_case ):
																					for xa, xa in zip(__snake_case     ,    __snake_case ):
																												if _add_into_out:
																																			xa[i : i + chunk_size] += xa
																												else:
																																			__lowerCamelCase   :   Optional[Any]       =xa
														elif isinstance(__snake_case     ,    torch.Tensor ):
																					if _add_into_out:
																												out[i : i + chunk_size] += output_chunk
																					else:
																												__lowerCamelCase   :   List[Any]       =output_chunk
														else:
																					raise ValueError('''Not supported''' )

														i += chunk_size

							__lowerCamelCase   :   Tuple       =tensor_tree_map(lambda SCREAMING_SNAKE_CASE : t.view(orig_batch_dims + t.shape[1:] )     ,    __snake_case )

							return out
class 		SCREAMING_SNAKE_CASE_				:
				"""simple docstring"""




				def __init__(  self	:Dict    ,     __lowercase	:int = 512    ,     ):
											__lowerCamelCase   :   List[Any]       =max_chunk_size
											__lowerCamelCase   :   Optional[int]       =None
											__lowerCamelCase   :   Optional[tuple]       =None




				def        __lowercase	(  self	:Dict    ,     __lowercase	:Callable    ,     __lowercase	:tuple    ,     __lowercase	:int      ):
											logging.info('''Tuning chunk size...'''      )

											if min_chunk_size >= self.max_chunk_size:
																		return min_chunk_size

											__lowerCamelCase   :   List[int]       =[2**l for l in range(int(math.log(self.max_chunk_size    ,     2      )      ) + 1      )]
											__lowerCamelCase   :   Any       =[c for c in candidates if c > min_chunk_size]
											__lowerCamelCase   :   int       =[min_chunk_size] + candidates
											candidates[-1] += 4

											def test_chunk_size(__lowercase	:int      ) -> bool:
																		try:
																									with torch.no_grad():
																																fn(*_SCREAMING_SNAKE_CASE    ,     chunk_size=_SCREAMING_SNAKE_CASE      )
																									return True
																		except RuntimeError:
																									return False

											__lowerCamelCase   :   int       =0
											__lowerCamelCase   :   Optional[Any]       =len(_SCREAMING_SNAKE_CASE      ) - 1
											while i > min_viable_chunk_size_index:
																		__lowerCamelCase   :   List[Any]       =test_chunk_size(candidates[i]      )
																		if not viable:
																									__lowerCamelCase   :   List[str]       =(min_viable_chunk_size_index + i) // 2
																		else:
																									__lowerCamelCase   :   str       =i
																									__lowerCamelCase   :   Tuple       =(i + len(_SCREAMING_SNAKE_CASE      ) - 1) // 2

											return candidates[min_viable_chunk_size_index]




				def        __lowercase	(  self	:str    ,     __lowercase	:Iterable    ,     __lowercase	:Iterable      ):
											__lowerCamelCase   :   Optional[Any]       =True
											for aa, aa in zip(_SCREAMING_SNAKE_CASE    ,     _SCREAMING_SNAKE_CASE      ):
																		assert type(_SCREAMING_SNAKE_CASE      ) == type(_SCREAMING_SNAKE_CASE      )
																		if isinstance(_SCREAMING_SNAKE_CASE    ,     (list, tuple)      ):
																									consistent &= self._compare_arg_caches(_SCREAMING_SNAKE_CASE    ,     _SCREAMING_SNAKE_CASE      )
																		elif isinstance(_SCREAMING_SNAKE_CASE    ,     _SCREAMING_SNAKE_CASE      ):
																									__lowerCamelCase   :   Optional[int]       =[v for _, v in sorted(aa.items()    ,     key=lambda __lowercase      : x[0]      )]
																									__lowerCamelCase   :   Optional[int]       =[v for _, v in sorted(aa.items()    ,     key=lambda __lowercase      : x[0]      )]
																									consistent &= self._compare_arg_caches(_SCREAMING_SNAKE_CASE    ,     _SCREAMING_SNAKE_CASE      )
																		else:
																									consistent &= aa == aa

											return consistent




				def        __lowercase	(  self	:int    ,     __lowercase	:Callable    ,     __lowercase	:tuple    ,     __lowercase	:int    ,     ):
											__lowerCamelCase   :   Any       =True
											__lowerCamelCase   :   tuple       =tree_map(lambda __lowercase      : a.shape if isinstance(_SCREAMING_SNAKE_CASE    ,     torch.Tensor      ) else a    ,     _SCREAMING_SNAKE_CASE    ,     _SCREAMING_SNAKE_CASE      )
											if self.cached_arg_data is not None:
																		# If args have changed shape/value, we need to re-tune
																		assert len(self.cached_arg_data      ) == len(_SCREAMING_SNAKE_CASE      )
																		__lowerCamelCase   :   Union[str, Any]       =self._compare_arg_caches(self.cached_arg_data    ,     _SCREAMING_SNAKE_CASE      )
											else:
																		# Otherwise, we can reuse the precomputed value
																		__lowerCamelCase   :   Tuple       =False

											if not consistent:
																		__lowerCamelCase   :   List[Any]       =self._determine_favorable_chunk_size(
																		    _SCREAMING_SNAKE_CASE    ,     _SCREAMING_SNAKE_CASE    ,     _SCREAMING_SNAKE_CASE    ,     )
																		__lowerCamelCase   :   Tuple       =arg_data

											assert self.cached_chunk_size is not None

											return self.cached_chunk_size









"""simple docstring"""






# NOTE: This file is deprecated and will be removed in a future version.
# It only exists so that temporarely `from diffusers.pipelines import DiffusionPipeline` works

from ...utils import deprecate
from ..controlnet.pipeline_flax_controlnet import FlaxStableDiffusionControlNetPipeline  # noqa: F401


deprecate(
    'stable diffusion controlnet',
    '0.22.0',
    'Importing `FlaxStableDiffusionControlNetPipeline` from diffusers.pipelines.stable_diffusion.flax_pipeline_stable_diffusion_controlnet is deprecated. Please import `from diffusers import FlaxStableDiffusionControlNetPipeline` instead.',
    standard_warn=False,
    stacklevel=3,
)