
'''simple docstring'''

import argparse

import torch

from diffusers import UNetaDConditionModel



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	Any   ,     snake_case_				:	List[Any]   ,     snake_case_				:	int   ,     snake_case_				:	Optional[Any]=None   ,     snake_case_				:	int=None   ,     snake_case_				:	List[str]=None							)       ->	List[str]:
 assert isinstance(snake_case_   ,     snake_case_							), "Paths should be a list of dicts containing 'old' and 'new' keys."

 # Splits the attention layers into three variables.
 if attention_paths_to_split is not None:
  for path, path_map in attention_paths_to_split.items():
   SCREAMING_SNAKE_CASE  :  str								=		old_checkpoint[path]
   SCREAMING_SNAKE_CASE  :  Optional[Any]								=		old_tensor.shape[0] // 3

   SCREAMING_SNAKE_CASE  :  int								=		(-1, channels) if len(old_tensor.shape							) == 3 else (-1)

   SCREAMING_SNAKE_CASE  :  List[str]								=		old_tensor.shape[0] // config['num_head_channels'] // 3

   SCREAMING_SNAKE_CASE  :  Tuple								=		old_tensor.reshape((num_heads, 3 * channels // num_heads) + old_tensor.shape[1:]							)
   SCREAMING_SNAKE_CASE				, SCREAMING_SNAKE_CASE				, SCREAMING_SNAKE_CASE  :  Tuple								=		old_tensor.split(channels // num_heads   ,     dim=1							)

   SCREAMING_SNAKE_CASE  :  List[Any]								=		query.reshape(snake_case_							)
   SCREAMING_SNAKE_CASE  :  str								=		key.reshape(snake_case_							)
   SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		value.reshape(snake_case_							)

 for path in paths:
  SCREAMING_SNAKE_CASE  :  Dict								=		path['new']

  # These have already been assigned
  if attention_paths_to_split is not None and new_path in attention_paths_to_split:
   continue

  if additional_replacements is not None:
   for replacement in additional_replacements:
    SCREAMING_SNAKE_CASE  :  List[str]								=		new_path.replace(replacement['old']   ,     replacement['new']							)

        # proj_attn.weight has to be converted from conv 1D to linear
  SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		old_checkpoint[path['old']]
  SCREAMING_SNAKE_CASE  :  Optional[int]								=		['proj_attn.weight']
  SCREAMING_SNAKE_CASE  :  int								=		['proj_out.weight', 'proj_in.weight']
  if any(k in new_path for k in names							):
   SCREAMING_SNAKE_CASE  :  int								=		weight[:, :, 0]
  elif any(k in new_path for k in names_a							) and len(weight.shape							) > 2 and ".attentions." not in new_path:
   SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		weight[:, :, 0]
  else:
   SCREAMING_SNAKE_CASE  :  Any								=		weight



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	Any   ,     snake_case_				:	Optional[int]=0							)       ->	Optional[Any]:
 SCREAMING_SNAKE_CASE  :  Tuple								=		[]
 for old_item in old_list:
  SCREAMING_SNAKE_CASE  :  int								=		old_item

  #         new_item = new_item.replace('norm.weight', 'group_norm.weight')
  #         new_item = new_item.replace('norm.bias', 'group_norm.bias')

  #         new_item = new_item.replace('proj_out.weight', 'proj_attn.weight')
  #         new_item = new_item.replace('proj_out.bias', 'proj_attn.bias')

  #         new_item = shave_segments(new_item, n_shave_prefix_segments=n_shave_prefix_segments)

  mapping.append({'old': old_item, 'new': new_item}							)

 return mapping



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	List[str]   ,     snake_case_				:	List[str]=1							)       ->	Optional[Any]:
 if n_shave_prefix_segments >= 0:
  return ".".join(path.split('.'							)[n_shave_prefix_segments:]							)
 else:
  return ".".join(path.split('.'							)[:n_shave_prefix_segments]							)



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	Union[str, Any]   ,     snake_case_				:	str=0							)       ->	Optional[int]:
 SCREAMING_SNAKE_CASE  :  List[str]								=		[]
 for old_item in old_list:
  mapping.append({'old': old_item, 'new': old_item}							)

 return mapping



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	List[str]   ,     snake_case_				:	Optional[Any]=0							)       ->	Union[str, Any]:
 SCREAMING_SNAKE_CASE  :  Dict								=		[]
 for old_item in old_list:
  SCREAMING_SNAKE_CASE  :  List[Any]								=		old_item.replace('in_layers.0'   ,     'norm1'							)
  SCREAMING_SNAKE_CASE  :  Dict								=		new_item.replace('in_layers.2'   ,     'conv1'							)

  SCREAMING_SNAKE_CASE  :  List[str]								=		new_item.replace('out_layers.0'   ,     'norm2'							)
  SCREAMING_SNAKE_CASE  :  List[str]								=		new_item.replace('out_layers.3'   ,     'conv2'							)

  SCREAMING_SNAKE_CASE  :  Dict								=		new_item.replace('emb_layers.1'   ,     'time_emb_proj'							)
  SCREAMING_SNAKE_CASE  :  Dict								=		new_item.replace('skip_connection'   ,     'conv_shortcut'							)

  SCREAMING_SNAKE_CASE  :  Dict								=		shave_segments(snake_case_   ,     n_shave_prefix_segments=snake_case_							)

  if "temopral_conv" not in old_item:
   mapping.append({'old': old_item, 'new': new_item}							)

 return mapping



def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	str   ,     snake_case_				:	Optional[Any]   ,     snake_case_				:	Any=None   ,     snake_case_				:	Optional[int]=False							)       ->	Optional[int]:
 SCREAMING_SNAKE_CASE  :  Optional[Any]								=		{}
 SCREAMING_SNAKE_CASE  :  Dict								=		list(checkpoint.keys()							)

 SCREAMING_SNAKE_CASE  :  Tuple								=		'model.diffusion_model.'

 # at least a 100 parameters have to start with `model_ema` in order for the checkpoint to be EMA
 if sum(k.startswith('model_ema'							) for k in keys							) > 100 and extract_ema:
  print(f"""Checkpoint {path} has both EMA and non-EMA weights."""							)
  print(
      'In this conversion only the EMA weights are extracted. If you want to instead extract the non-EMA'
      ' weights (useful to continue fine-tuning), please make sure to remove the `--extract_ema` flag.'							)
  for key in keys:
   if key.startswith('model.diffusion_model'							):
    SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		'model_ema.' + ''.join(key.split('.'							)[1:]							)
    SCREAMING_SNAKE_CASE  :  Dict								=		checkpoint.pop(snake_case_							)
 else:
  if sum(k.startswith('model_ema'							) for k in keys							) > 100:
   print(
       'In this conversion only the non-EMA weights are extracted. If you want to instead extract the EMA'
       ' weights (usually better for inference), please make sure to add the `--extract_ema` flag.'							)

  for key in keys:
   SCREAMING_SNAKE_CASE  :  Optional[Any]								=		checkpoint.pop(snake_case_							)

 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		{}

 SCREAMING_SNAKE_CASE  :  Any								=		unet_state_dict['time_embed.0.weight']
 SCREAMING_SNAKE_CASE  :  Tuple								=		unet_state_dict['time_embed.0.bias']
 SCREAMING_SNAKE_CASE  :  str								=		unet_state_dict['time_embed.2.weight']
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		unet_state_dict['time_embed.2.bias']

 if config["class_embed_type"] is None:
  # No parameters to port
  ...
 elif config["class_embed_type"] == "timestep" or config["class_embed_type"] == "projection":
  SCREAMING_SNAKE_CASE  :  str								=		unet_state_dict['label_emb.0.0.weight']
  SCREAMING_SNAKE_CASE  :  Dict								=		unet_state_dict['label_emb.0.0.bias']
  SCREAMING_SNAKE_CASE  :  Dict								=		unet_state_dict['label_emb.0.2.weight']
  SCREAMING_SNAKE_CASE  :  Dict								=		unet_state_dict['label_emb.0.2.bias']
 else:
  raise NotImplementedError(f"""Not implemented `class_embed_type`: {config["class_embed_type"]}"""							)

 SCREAMING_SNAKE_CASE  :  Any								=		unet_state_dict['input_blocks.0.0.weight']
 SCREAMING_SNAKE_CASE  :  List[str]								=		unet_state_dict['input_blocks.0.0.bias']

 SCREAMING_SNAKE_CASE  :  Dict								=		[v for v in unet_state_dict if v.startswith('input_blocks.0.1'							)]
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		renew_attention_paths(snake_case_							)
 SCREAMING_SNAKE_CASE  :  Tuple								=		{'old': 'input_blocks.0.1', 'new': 'transformer_in'}
 assign_to_checkpoint(snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

 SCREAMING_SNAKE_CASE  :  str								=		unet_state_dict['out.0.weight']
 SCREAMING_SNAKE_CASE  :  str								=		unet_state_dict['out.0.bias']
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		unet_state_dict['out.2.weight']
 SCREAMING_SNAKE_CASE  :  Tuple								=		unet_state_dict['out.2.bias']

 # Retrieves the keys for the input blocks only
 SCREAMING_SNAKE_CASE  :  Any								=		len({'.'.join(layer.split('.'							)[:2]							) for layer in unet_state_dict if 'input_blocks' in layer}							)
 SCREAMING_SNAKE_CASE  :  Optional[Any]								=		{
     layer_id: [key for key in unet_state_dict if f"""input_blocks.{layer_id}""" in key]
     for layer_id in range(snake_case_							)
 }

 # Retrieves the keys for the middle blocks only
 SCREAMING_SNAKE_CASE  :  int								=		len({'.'.join(layer.split('.'							)[:2]							) for layer in unet_state_dict if 'middle_block' in layer}							)
 SCREAMING_SNAKE_CASE  :  Optional[Any]								=		{
     layer_id: [key for key in unet_state_dict if f"""middle_block.{layer_id}""" in key]
     for layer_id in range(snake_case_							)
 }

 # Retrieves the keys for the output blocks only
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		len({'.'.join(layer.split('.'							)[:2]							) for layer in unet_state_dict if 'output_blocks' in layer}							)
 SCREAMING_SNAKE_CASE  :  List[str]								=		{
     layer_id: [key for key in unet_state_dict if f"""output_blocks.{layer_id}""" in key]
     for layer_id in range(snake_case_							)
 }

 for i in range(1   ,     snake_case_							):
  SCREAMING_SNAKE_CASE  :  Any								=		(i - 1) // (config['layers_per_block'] + 1)
  SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		(i - 1) % (config['layers_per_block'] + 1)

  SCREAMING_SNAKE_CASE  :  Tuple								=		[
      key for key in input_blocks[i] if f"""input_blocks.{i}.0""" in key and f"""input_blocks.{i}.0.op""" not in key
  ]
  SCREAMING_SNAKE_CASE  :  List[Any]								=		[key for key in input_blocks[i] if f"""input_blocks.{i}.1""" in key]
  SCREAMING_SNAKE_CASE  :  Dict								=		[key for key in input_blocks[i] if f"""input_blocks.{i}.2""" in key]

  if f"""input_blocks.{i}.op.weight""" in unet_state_dict:
   SCREAMING_SNAKE_CASE  :  Any								=		unet_state_dict.pop(
       f"""input_blocks.{i}.op.weight"""							)
   SCREAMING_SNAKE_CASE  :  Optional[Any]								=		unet_state_dict.pop(
       f"""input_blocks.{i}.op.bias"""							)

  SCREAMING_SNAKE_CASE  :  Tuple								=		renew_resnet_paths(snake_case_							)
  SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		{'old': f"""input_blocks.{i}.0""", 'new': f"""down_blocks.{block_id}.resnets.{layer_in_block_id}"""}
  assign_to_checkpoint(
      snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

  SCREAMING_SNAKE_CASE  :  Dict								=		[key for key in resnets if 'temopral_conv' in key]
  SCREAMING_SNAKE_CASE  :  Tuple								=		renew_temp_conv_paths(snake_case_							)
  SCREAMING_SNAKE_CASE  :  int								=		{
      'old': f"""input_blocks.{i}.0.temopral_conv""",
      'new': f"""down_blocks.{block_id}.temp_convs.{layer_in_block_id}""",
  }
  assign_to_checkpoint(
      snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

  if len(snake_case_							):
   SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		renew_attention_paths(snake_case_							)
   SCREAMING_SNAKE_CASE  :  Tuple								=		{'old': f"""input_blocks.{i}.1""", 'new': f"""down_blocks.{block_id}.attentions.{layer_in_block_id}"""}
   assign_to_checkpoint(
       snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

  if len(snake_case_							):
   SCREAMING_SNAKE_CASE  :  Optional[int]								=		renew_attention_paths(snake_case_							)
   SCREAMING_SNAKE_CASE  :  Optional[int]								=		{
       'old': f"""input_blocks.{i}.2""",
       'new': f"""down_blocks.{block_id}.temp_attentions.{layer_in_block_id}""",
   }
   assign_to_checkpoint(
       snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

 SCREAMING_SNAKE_CASE  :  str								=		middle_blocks[0]
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		[key for key in resnet_a if 'temopral_conv' in key]
 SCREAMING_SNAKE_CASE  :  Any								=		middle_blocks[1]
 SCREAMING_SNAKE_CASE  :  Optional[int]								=		middle_blocks[2]
 SCREAMING_SNAKE_CASE  :  List[Any]								=		middle_blocks[3]
 SCREAMING_SNAKE_CASE  :  List[Any]								=		[key for key in resnet_a if 'temopral_conv' in key]

 SCREAMING_SNAKE_CASE  :  List[Any]								=		renew_resnet_paths(snake_case_							)
 SCREAMING_SNAKE_CASE  :  List[str]								=		{'old': 'middle_block.0', 'new': 'mid_block.resnets.0'}
 assign_to_checkpoint(
     snake_case_   ,     snake_case_   ,     snake_case_   ,     config=snake_case_   ,     additional_replacements=[meta_path]							)

 SCREAMING_SNAKE_CASE  :  Any								=		renew_temp_conv_paths(snake_case_							)
 SCREAMING_SNAKE_CASE  :  Any								=		{'old': 'middle_block.0.temopral_conv', 'new': 'mid_block.temp_convs.0'}
 assign_to_checkpoint(
     snake_case_   ,     snake_case_   ,     snake_case_   ,     config=snake_case_   ,     additional_replacements=[meta_path]							)

 SCREAMING_SNAKE_CASE  :  Optional[Any]								=		renew_resnet_paths(snake_case_							)
 SCREAMING_SNAKE_CASE  :  Optional[int]								=		{'old': 'middle_block.3', 'new': 'mid_block.resnets.1'}
 assign_to_checkpoint(
     snake_case_   ,     snake_case_   ,     snake_case_   ,     config=snake_case_   ,     additional_replacements=[meta_path]							)

 SCREAMING_SNAKE_CASE  :  Optional[int]								=		renew_temp_conv_paths(snake_case_							)
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		{'old': 'middle_block.3.temopral_conv', 'new': 'mid_block.temp_convs.1'}
 assign_to_checkpoint(
     snake_case_   ,     snake_case_   ,     snake_case_   ,     config=snake_case_   ,     additional_replacements=[meta_path]							)

 SCREAMING_SNAKE_CASE  :  Tuple								=		renew_attention_paths(snake_case_							)
 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		{'old': 'middle_block.1', 'new': 'mid_block.attentions.0'}
 assign_to_checkpoint(
     snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

 SCREAMING_SNAKE_CASE  :  Optional[int]								=		renew_attention_paths(snake_case_							)
 SCREAMING_SNAKE_CASE  :  Dict								=		{'old': 'middle_block.2', 'new': 'mid_block.temp_attentions.0'}
 assign_to_checkpoint(
     snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

 for i in range(snake_case_							):
  SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		i // (config['layers_per_block'] + 1)
  SCREAMING_SNAKE_CASE  :  int								=		i % (config['layers_per_block'] + 1)
  SCREAMING_SNAKE_CASE  :  str								=		[shave_segments(snake_case_   ,     2							) for name in output_blocks[i]]
  SCREAMING_SNAKE_CASE  :  str								=		{}

  for layer in output_block_layers:
   SCREAMING_SNAKE_CASE				, SCREAMING_SNAKE_CASE  :  Optional[Any]								=		layer.split('.'							)[0], shave_segments(snake_case_   ,     1							)
   if layer_id in output_block_list:
    output_block_list[layer_id].append(snake_case_							)
   else:
    SCREAMING_SNAKE_CASE  :  Any								=		[layer_name]

  if len(snake_case_							) > 1:
   SCREAMING_SNAKE_CASE  :  List[str]								=		[key for key in output_blocks[i] if f"""output_blocks.{i}.0""" in key]
   SCREAMING_SNAKE_CASE  :  List[str]								=		[key for key in output_blocks[i] if f"""output_blocks.{i}.1""" in key]
   SCREAMING_SNAKE_CASE  :  Any								=		[key for key in output_blocks[i] if f"""output_blocks.{i}.2""" in key]

   SCREAMING_SNAKE_CASE  :  Optional[int]								=		renew_resnet_paths(snake_case_							)
   SCREAMING_SNAKE_CASE  :  int								=		renew_resnet_paths(snake_case_							)

   SCREAMING_SNAKE_CASE  :  List[str]								=		{'old': f"""output_blocks.{i}.0""", 'new': f"""up_blocks.{block_id}.resnets.{layer_in_block_id}"""}
   assign_to_checkpoint(
       snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

   SCREAMING_SNAKE_CASE  :  int								=		[key for key in resnets if 'temopral_conv' in key]
   SCREAMING_SNAKE_CASE  :  List[str]								=		renew_temp_conv_paths(snake_case_							)
   SCREAMING_SNAKE_CASE  :  str								=		{
       'old': f"""output_blocks.{i}.0.temopral_conv""",
       'new': f"""up_blocks.{block_id}.temp_convs.{layer_in_block_id}""",
   }
   assign_to_checkpoint(
       snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

   SCREAMING_SNAKE_CASE  :  Optional[int]								=		{k: sorted(snake_case_							) for k, v in output_block_list.items()}
   if ["conv.bias", "conv.weight"] in output_block_list.values():
    SCREAMING_SNAKE_CASE  :  str								=		list(output_block_list.values()							).index(['conv.bias', 'conv.weight']							)
    SCREAMING_SNAKE_CASE  :  Tuple								=		unet_state_dict[
        f"""output_blocks.{i}.{index}.conv.weight"""
    ]
    SCREAMING_SNAKE_CASE  :  List[str]								=		unet_state_dict[
        f"""output_blocks.{i}.{index}.conv.bias"""
    ]

    # Clear attentions as they have been attributed above.
    if len(snake_case_							) == 2:
     SCREAMING_SNAKE_CASE  :  Optional[Any]								=		[]

   if len(snake_case_							):
    SCREAMING_SNAKE_CASE  :  Optional[Any]								=		renew_attention_paths(snake_case_							)
    SCREAMING_SNAKE_CASE  :  Dict								=		{
        'old': f"""output_blocks.{i}.1""",
        'new': f"""up_blocks.{block_id}.attentions.{layer_in_block_id}""",
    }
    assign_to_checkpoint(
        snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)

   if len(snake_case_							):
    SCREAMING_SNAKE_CASE  :  Tuple								=		renew_attention_paths(snake_case_							)
    SCREAMING_SNAKE_CASE  :  List[Any]								=		{
        'old': f"""output_blocks.{i}.2""",
        'new': f"""up_blocks.{block_id}.temp_attentions.{layer_in_block_id}""",
    }
    assign_to_checkpoint(
        snake_case_   ,     snake_case_   ,     snake_case_   ,     additional_replacements=[meta_path]   ,     config=snake_case_							)
  else:
   SCREAMING_SNAKE_CASE  :  Any								=		renew_resnet_paths(snake_case_   ,     n_shave_prefix_segments=1							)
   for path in resnet_0_paths:
    SCREAMING_SNAKE_CASE  :  List[Any]								=		'.'.join(['output_blocks', str(snake_case_							), path['old']]							)
    SCREAMING_SNAKE_CASE  :  str								=		'.'.join(['up_blocks', str(snake_case_							), 'resnets', str(snake_case_							), path['new']]							)
    SCREAMING_SNAKE_CASE  :  Optional[Any]								=		unet_state_dict[old_path]

   SCREAMING_SNAKE_CASE  :  Optional[Any]								=		[l for l in output_block_layers if 'temopral_conv' in l]
   for path in temopral_conv_paths:
    SCREAMING_SNAKE_CASE  :  str								=		path.split('temopral_conv.'							)[-1]
    SCREAMING_SNAKE_CASE  :  int								=		'.'.join(['output_blocks', str(snake_case_							), str(snake_case_							), 'temopral_conv', pruned_path]							)
    SCREAMING_SNAKE_CASE  :  Tuple								=		'.'.join(['up_blocks', str(snake_case_							), 'temp_convs', str(snake_case_							), pruned_path]							)
    SCREAMING_SNAKE_CASE  :  int								=		unet_state_dict[old_path]

 return new_checkpoint


if __name__ == "__main__":
   __UpperCAmelCase												=   argparse.ArgumentParser()

   parser.add_argument(
       '--checkpoint_path', default=None, type=str, required=True, help='Path to the checkpoint to convert.'
   )
   parser.add_argument('--dump_path', default=None, type=str, required=True, help='Path to the output model.')
   __UpperCAmelCase												=   parser.parse_args()

   __UpperCAmelCase												=   torch.load(args.checkpoint_path, map_location='cpu')
   __UpperCAmelCase												=   UNetaDConditionModel()

   __UpperCAmelCase												=   convert_ldm_unet_checkpoint(unet_checkpoint, unet.config)

   __UpperCAmelCase												=   set(unet.state_dict().keys()) - set(converted_ckpt.keys())
   __UpperCAmelCase												=   set(converted_ckpt.keys()) - set(unet.state_dict().keys())

   assert len(diff_a) == len(diff_a) == 0, "Converted weights don't match"

   # load state_dict
   unet.load_state_dict(converted_ckpt)

   unet.save_pretrained(args.dump_path)

   # -- finish converting the unet --




'''simple docstring'''

def        SCREAMING_SNAKE_CASE_  (	snake_case_				:	int   ,     snake_case_				:	list[tuple[int, int, int]]							)       ->	list[tuple[int, int, int]]:
 SCREAMING_SNAKE_CASE  :  List[Any]								=		sorted(snake_case_   ,     key=lambda snake_case_							: edge[2]							)

 SCREAMING_SNAKE_CASE  :  str								=		list(range(snake_case_							)							)

 def find_parent(snake_case_				:	Union[str, Any]							):
  if i != parent[i]:
   SCREAMING_SNAKE_CASE  :  int								=		find_parent(parent[i]							)
  return parent[i]

 SCREAMING_SNAKE_CASE  :  Union[str, Any]								=		0
 SCREAMING_SNAKE_CASE  :  Any								=		[]

 for edge in edges:
  SCREAMING_SNAKE_CASE  :  Dict								=		find_parent(edge[0]							)
  SCREAMING_SNAKE_CASE  :  Optional[int]								=		find_parent(edge[1]							)
  if parent_a != parent_b:
   minimum_spanning_tree_cost += edge[2]
   minimum_spanning_tree.append(snake_case_							)
   SCREAMING_SNAKE_CASE  :  Tuple								=		parent_b

 return minimum_spanning_tree


if __name__ == "__main__":  # pragma: no cover
   __UpperCAmelCase						,						__UpperCAmelCase												=   list(map(int, input().strip().split()))
   __UpperCAmelCase												=   []

   for _ in range(num_edges):
      __UpperCAmelCase						,						__UpperCAmelCase						,						__UpperCAmelCase												=   (int(x) for x in input().strip().split())
      edges.append((nodea, nodea, cost))

   kruskal(num_nodes, edges)


