
from typing import List, Optional, Tuple, Union

import torch
from torch import nn
from torch.nn import CrossEntropyLoss

from ... import AutoBackbone
from ...modeling_outputs import SemanticSegmenterOutput
from ...modeling_utils import PreTrainedModel
from ...utils import add_start_docstrings, add_start_docstrings_to_model_forward, replace_return_docstrings
from ...utils.backbone_utils import BackboneMixin
from .configuration_upernet import UperNetConfig


SCREAMING_SNAKE_CASE :		Any       			=							[
    "openmmlab/upernet-convnext-tiny",
    # See all UperNet models at https://huggingface.co/models?filter=upernet
]

# General docstring
SCREAMING_SNAKE_CASE :		Optional[Any]       			=							"UperNetConfig"






class        __lowercase		(       nn.Module							):


					def __init__(						self							,							a__							,							a__							,							a__							,							a__ = 0							,							a__ = False							,							a__ = 1							,							)		->				None:





									'''simple docstring'''
									super().__init__()
									A_													=	nn.Convad(
									    in_channels=a__							,							out_channels=a__							,							kernel_size=a__							,							padding=a__							,							bias=a__							,							dilation=a__							,							)
									A_													=	nn.BatchNormad(a__    )
									A_													=	nn.ReLU()


					def 							lowerCAmelCase_     (						self							,							a__    )		->				torch.Tensor:





									'''simple docstring'''
									A_													=	self.conv(a__    )
									A_													=	self.batch_norm(a__    )
									A_													=	self.activation(a__    )

									return output






class        __lowercase		(       nn.Module							):


					def __init__(						self							,							a__							,							a__							,							a__    )		->				None:





									'''simple docstring'''
									super().__init__()
									A_													=	[
									    nn.AdaptiveAvgPoolad(a__    ),
									    UperNetConvModule(a__							,							a__							,							kernel_size=1    ),
									]
									for i, layer in enumerate(self.layers    ):
													self.add_module(str(a__    )							,							a__    )


					def 							lowerCAmelCase_     (						self							,							a__    )		->				torch.Tensor:





									'''simple docstring'''
									A_													=	input
									for layer in self.layers:
													A_													=	layer(a__    )
									return hidden_state






class        __lowercase		(       nn.Module							):


					def __init__(						self							,							a__							,							a__							,							a__							,							a__    )		->				None:





									'''simple docstring'''
									super().__init__()
									A_													=	pool_scales
									A_													=	align_corners
									A_													=	in_channels
									A_													=	channels
									A_													=	[]
									for i, pool_scale in enumerate(a__    ):
													A_													=	UperNetPyramidPoolingBlock(pool_scale=a__							,							in_channels=a__							,							channels=a__    )
													self.blocks.append(a__    )
													self.add_module(str(a__    )							,							a__    )


					def 							lowerCAmelCase_     (						self							,							a__    )		->				List[torch.Tensor]:





									'''simple docstring'''
									A_													=	[]
									for ppm in self.blocks:
													A_													=	ppm(a__    )
													A_													=	nn.functional.interpolate(
													    a__							,							size=x.size()[2:]							,							mode='''bilinear'''							,							align_corners=self.align_corners    )
													ppm_outs.append(a__    )
									return ppm_outs






class        __lowercase		(       nn.Module							):


					def __init__(						self							,							a__							,							a__    )		->				Any:





									'''simple docstring'''
									super().__init__()

									A_													=	config
									A_													=	config.pool_scales  # e.g. (1, 2, 3, 6)
									A_													=	in_channels
									A_													=	config.hidden_size
									A_													=	False
									A_													=	nn.Convad(self.channels							,							config.num_labels							,							kernel_size=1    )

									# PSP Module
									A_													=	UperNetPyramidPoolingModule(
									    self.pool_scales							,							self.in_channels[-1]							,							self.channels							,							align_corners=self.align_corners							,							)
									A_													=	UperNetConvModule(
									    self.in_channels[-1] + len(self.pool_scales    ) * self.channels							,							self.channels							,							kernel_size=3							,							padding=1							,							)
									# FPN Module
									A_													=	nn.ModuleList()
									A_													=	nn.ModuleList()
									for in_channels in self.in_channels[:-1]:  # skip the top layer
													A_													=	UperNetConvModule(a__							,							self.channels							,							kernel_size=1    )
													A_													=	UperNetConvModule(self.channels							,							self.channels							,							kernel_size=3							,							padding=1    )
													self.lateral_convs.append(a__    )
													self.fpn_convs.append(a__    )

									A_													=	UperNetConvModule(
									    len(self.in_channels    ) * self.channels							,							self.channels							,							kernel_size=3							,							padding=1							,							)


					def 							lowerCAmelCase_     (						self    )		->				Dict:





									'''simple docstring'''
									self.apply(self._init_weights    )


					def 							lowerCAmelCase_     (						self							,							a__    )		->				List[str]:





									'''simple docstring'''
									if isinstance(a__							,							nn.Convad    ):
													module.weight.data.normal_(mean=0.0							,							std=self.config.initializer_range    )
													if module.bias is not None:
																	module.bias.data.zero_()


					def 							lowerCAmelCase_     (						self							,							a__    )		->				Union[str, Any]:





									'''simple docstring'''
									A_													=	inputs[-1]
									A_													=	[x]
									psp_outs.extend(self.psp_modules(a__    )    )
									A_													=	torch.cat(a__							,							dim=1    )
									A_													=	self.bottleneck(a__    )

									return output


					def 							lowerCAmelCase_     (						self							,							a__    )		->				torch.Tensor:





									'''simple docstring'''
									# build laterals
									A_													=	[lateral_conv(encoder_hidden_states[i]    ) for i, lateral_conv in enumerate(self.lateral_convs    )]

									laterals.append(self.psp_forward(a__    )    )

									# build top-down path
									A_													=	len(a__    )
									for i in range(used_backbone_levels - 1							,							0							,							-1    ):
													A_													=	laterals[i - 1].shape[2:]
													A_													=	laterals[i - 1] + nn.functional.interpolate(
													    laterals[i]							,							size=a__							,							mode='''bilinear'''							,							align_corners=self.align_corners    )

									# build outputs
									A_													=	[self.fpn_convs[i](laterals[i]    ) for i in range(used_backbone_levels - 1    )]
									# append psp feature
									fpn_outs.append(laterals[-1]    )

									for i in range(used_backbone_levels - 1							,							0							,							-1    ):
													A_													=	nn.functional.interpolate(
													    fpn_outs[i]							,							size=fpn_outs[0].shape[2:]							,							mode='''bilinear'''							,							align_corners=self.align_corners    )
									A_													=	torch.cat(a__							,							dim=1    )
									A_													=	self.fpn_bottleneck(a__    )
									A_													=	self.classifier(a__    )

									return output






class        __lowercase		(       nn.Module							):


					def __init__(						self							,							a__							,							a__ = 2							,							a__ = 3							,							a__ = 1    )		->				None:





									'''simple docstring'''
									super().__init__()

									A_													=	config
									A_													=	config.auxiliary_in_channels
									A_													=	config.auxiliary_channels
									A_													=	config.auxiliary_num_convs
									A_													=	config.auxiliary_concat_input
									A_													=	in_index

									A_													=	(kernel_size // 2) * dilation
									A_													=	[]
									convs.append(
									    UperNetConvModule(
									        self.in_channels							,							self.channels							,							kernel_size=a__							,							padding=a__							,							dilation=a__    )    )
									for i in range(self.num_convs - 1    ):
													convs.append(
													    UperNetConvModule(
													        self.channels							,							self.channels							,							kernel_size=a__							,							padding=a__							,							dilation=a__    )    )
									if self.num_convs == 0:
													A_													=	nn.Identity()
									else:
													A_													=	nn.Sequential(*a__    )
									if self.concat_input:
													A_													=	UperNetConvModule(
													    self.in_channels + self.channels							,							self.channels							,							kernel_size=a__							,							padding=kernel_size // 2    )

									A_													=	nn.Convad(self.channels							,							config.num_labels							,							kernel_size=1    )


					def 							lowerCAmelCase_     (						self    )		->				int:





									'''simple docstring'''
									self.apply(self._init_weights    )


					def 							lowerCAmelCase_     (						self							,							a__    )		->				List[Any]:





									'''simple docstring'''
									if isinstance(a__							,							nn.Convad    ):
													module.weight.data.normal_(mean=0.0							,							std=self.config.initializer_range    )
													if module.bias is not None:
																	module.bias.data.zero_()


					def 							lowerCAmelCase_     (						self							,							a__    )		->				torch.Tensor:





									'''simple docstring'''
									# just take the relevant feature maps
									A_													=	encoder_hidden_states[self.in_index]
									A_													=	self.convs(a__    )
									if self.concat_input:
													A_													=	self.conv_cat(torch.cat([hidden_states, output]							,							dim=1    )    )
									A_													=	self.classifier(a__    )
									return output






class        __lowercase		(       A							):
					__magic_name__    :				List[str]  						=						UperNetConfig
					__magic_name__    :				Optional[Any]  						=						"""pixel_values"""
					__magic_name__    :				List[Any]  						=						True


					def 							lowerCAmelCase_     (						self							,							a__    )		->				int:





									'''simple docstring'''
									if isinstance(a__							,							a__    ):
													module.backbone.init_weights()
													module.decode_head.init_weights()
													module.auxiliary_head.init_weights()


					def 							lowerCAmelCase_     (						self    )		->				str:





									'''simple docstring'''
									self.backbone.init_weights()
									self.decode_head.init_weights()
									self.auxiliary_head.init_weights()


					def 							lowerCAmelCase_     (						self							,							a__							,							a__=False    )		->				Optional[Any]:





									'''simple docstring'''
									if isinstance(a__							,							a__    ):
													A_													=	value
SCREAMING_SNAKE_CASE :		Optional[Any]       			=							R"\n    Parameters:\n    This model is a PyTorch [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) sub-class. Use\n    it as a regular PyTorch Module and refer to the PyTorch documentation for all matter related to general usage and\n    behavior.\n        config ([`UperNetConfig`]): Model configuration class with all the parameters of the model.\n            Initializing with a config file does not load the weights associated with the model, only the\n            configuration. Check out the [`~PreTrainedModel.from_pretrained`] method to load the model weights.\n"

SCREAMING_SNAKE_CASE :		str       			=							R"\n    Args:\n        pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)`):\n            Pixel values. Padding will be ignored by default should you provide it. Pixel values can be obtained using\n            [`AutoImageProcessor`]. See [`SegformerImageProcessor.__call__`] for details.\n        output_attentions (`bool`, *optional*):\n            Whether or not to return the attentions tensors of all attention layers in case the backbone has them. See\n            `attentions` under returned tensors for more detail.\n        output_hidden_states (`bool`, *optional*):\n            Whether or not to return the hidden states of all layers of the backbone. See `hidden_states` under\n            returned tensors for more detail.\n        return_dict (`bool`, *optional*):\n            Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.\n"






@add_start_docstrings(
    '''UperNet framework leveraging any vision backbone e.g. for ADE20k, CityScapes.'''				,							A				,							)
class        __lowercase		(       A							):


					def __init__(						self							,							a__    )		->				str:





									'''simple docstring'''
									super().__init__(a__    )

									A_													=	AutoBackbone.from_config(config.backbone_config    )

									# Semantic segmentation head(s)
									A_													=	UperNetHead(a__							,							in_channels=self.backbone.channels    )
									A_													=	UperNetFCNHead(a__    ) if config.use_auxiliary_head else None

									# Initialize weights and apply final processing
									self.post_init()


					@add_start_docstrings_to_model_forward(UPERNET_INPUTS_DOCSTRING.format('''batch_size, sequence_length'''    )    )
					@replace_return_docstrings(output_type=a__							,							config_class=_CONFIG_FOR_DOC    )
					def 							lowerCAmelCase_     (						self							,							a__ = None							,							a__ = None							,							a__ = None							,							a__ = None							,							a__ = None							,							)		->				Union[tuple, SemanticSegmenterOutput]:





									'''simple docstring'''
									A_													=	return_dict if return_dict is not None else self.config.use_return_dict
									A_													=	(
									    output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
									)
									A_													=	output_attentions if output_attentions is not None else self.config.output_attentions

									A_													=	self.backbone.forward_with_filtered_kwargs(
									    a__							,							output_hidden_states=a__							,							output_attentions=a__    )
									A_													=	outputs.feature_maps

									A_													=	self.decode_head(a__    )
									A_													=	nn.functional.interpolate(a__							,							size=pixel_values.shape[2:]							,							mode='''bilinear'''							,							align_corners=a__    )

									A_													=	None
									if self.auxiliary_head is not None:
													A_													=	self.auxiliary_head(a__    )
													A_													=	nn.functional.interpolate(
													    a__							,							size=pixel_values.shape[2:]							,							mode='''bilinear'''							,							align_corners=a__    )

									A_													=	None
									if labels is not None:
													if self.config.num_labels == 1:
																	raise ValueError('''The number of labels should be greater than one'''    )
													else:
																	# compute weighted loss
																	A_													=	CrossEntropyLoss(ignore_index=self.config.loss_ignore_index    )
																	A_													=	loss_fct(a__							,							a__    )
																	A_													=	loss_fct(a__							,							a__    )
																	A_													=	main_loss + self.config.auxiliary_loss_weight * auxiliary_loss

									if not return_dict:
													if output_hidden_states:
																	A_													=	(logits,) + outputs[1:]
													else:
																	A_													=	(logits,) + outputs[2:]
													return ((loss,) + output) if loss is not None else output

									return SemanticSegmenterOutput(
									    loss=a__							,							logits=a__							,							hidden_states=outputs.hidden_states							,							attentions=outputs.attentions							,							)







"""simple docstring"""


from __future__ import annotations

from collections import namedtuple
from dataclasses import dataclass




@dataclass
class 						__UpperCamelCase     :
					lowercase_    :				int
					lowercase_    :				TreeNode | None      =  None
					lowercase_    :				TreeNode | None      =  None


__SCREAMING_SNAKE_CASE   =   namedtuple('CoinsDistribResult', 'moves excess')


def        UpperCAmelCase      (					a__ ):





						'''simple docstring'''






						if root is None:
												return 0

						# Validation
						def count_nodes(a__ ) -> int:
												if node is None:
																		return 0

												return count_nodes(node.left ) + count_nodes(node.right ) + 1

						def count_coins(a__ ) -> int:
												if node is None:
																		return 0

												return count_coins(node.left ) + count_coins(node.right ) + node.data

						if count_nodes(a__ ) != count_coins(a__ ):
												raise ValueError('The nodes number should be same as the number of coins' )

						# Main calculation
						def get_distrib(a__ ) -> CoinsDistribResult:

												if node is None:
																		return CoinsDistribResult(0     ,      1 )

												lowerCAmelCase	, lowerCAmelCase   :Optional[int]						=			get_distrib(node.left )
												lowerCAmelCase	, lowerCAmelCase   :str						=			get_distrib(node.right )

												lowerCAmelCase   :str						=			1 - left_distrib_excess
												lowerCAmelCase   :Optional[Any]						=			1 - right_distrib_excess

												lowerCAmelCase   :Any						=			(
												    left_distrib_moves
												    + right_distrib_moves
												    + abs(a__ )
												    + abs(a__ )
												)
												lowerCAmelCase   :Tuple						=			node.data - coins_to_left - coins_to_right

												return CoinsDistribResult(a__     ,      a__ )

						return get_distrib(a__ )[0]


if __name__ == "__main__":
		import doctest

		doctest.testmod()