



import argparse
import json
import os

import numpy as np
import PIL
import requests
import tensorflow.keras.applications.efficientnet as efficientnet
import torch
from huggingface_hub import hf_hub_download
from PIL import Image
from tensorflow.keras.preprocessing import image

from transformers import (
    EfficientNetConfig,
    EfficientNetForImageClassification,
    EfficientNetImageProcessor,
)
from transformers.utils import logging


logging.set_verbosity_info()
__a     =			logging.get_logger(__name__)

__a     =			{
    """b0""": efficientnet.EfficientNetBa,
    """b1""": efficientnet.EfficientNetBa,
    """b2""": efficientnet.EfficientNetBa,
    """b3""": efficientnet.EfficientNetBa,
    """b4""": efficientnet.EfficientNetBa,
    """b5""": efficientnet.EfficientNetBa,
    """b6""": efficientnet.EfficientNetBa,
    """b7""": efficientnet.EfficientNetBa,
}

__a     =			{
    """b0""": {
        """hidden_dim""": 1280,
        """width_coef""": 1.0,
        """depth_coef""": 1.0,
        """image_size""": 224,
        """dropout_rate""": 0.2,
        """dw_padding""": [],
    },
    """b1""": {
        """hidden_dim""": 1280,
        """width_coef""": 1.0,
        """depth_coef""": 1.1,
        """image_size""": 240,
        """dropout_rate""": 0.2,
        """dw_padding""": [16],
    },
    """b2""": {
        """hidden_dim""": 1408,
        """width_coef""": 1.1,
        """depth_coef""": 1.2,
        """image_size""": 260,
        """dropout_rate""": 0.3,
        """dw_padding""": [5, 8, 16],
    },
    """b3""": {
        """hidden_dim""": 1536,
        """width_coef""": 1.2,
        """depth_coef""": 1.4,
        """image_size""": 300,
        """dropout_rate""": 0.3,
        """dw_padding""": [5, 18],
    },
    """b4""": {
        """hidden_dim""": 1792,
        """width_coef""": 1.4,
        """depth_coef""": 1.8,
        """image_size""": 380,
        """dropout_rate""": 0.4,
        """dw_padding""": [6],
    },
    """b5""": {
        """hidden_dim""": 2048,
        """width_coef""": 1.6,
        """depth_coef""": 2.2,
        """image_size""": 456,
        """dropout_rate""": 0.4,
        """dw_padding""": [13, 27],
    },
    """b6""": {
        """hidden_dim""": 2304,
        """width_coef""": 1.8,
        """depth_coef""": 2.6,
        """image_size""": 528,
        """dropout_rate""": 0.5,
        """dw_padding""": [31],
    },
    """b7""": {
        """hidden_dim""": 2560,
        """width_coef""": 2.0,
        """depth_coef""": 3.1,
        """image_size""": 600,
        """dropout_rate""": 0.5,
        """dw_padding""": [18],
    },
}
def   _UpperCamelCase				(						lowerCAmelCase_   )						->Optional[int]:
   UpperCAmelCase							=     EfficientNetConfig()
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""hidden_dim"""]
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""width_coef"""]
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""depth_coef"""]
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""image_size"""]
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""dropout_rate"""]
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""dw_padding"""]

   UpperCAmelCase							=     """huggingface/label-files"""
   UpperCAmelCase							=     """imagenet-1k-id2label.json"""
   UpperCAmelCase							=     1_0_0_0
   UpperCAmelCase							=     json.load(open(hf_hub_download(lowerCAmelCase_  ,						lowerCAmelCase_  ,						repo_type="""dataset"""   )  ,						"""r"""   )   )
   UpperCAmelCase							=     {int(lowerCAmelCase_   ): v for k, v in idalabel.items()}

   UpperCAmelCase							=     idalabel
   UpperCAmelCase							=     {v: k for k, v in idalabel.items()}
   return config
def   _UpperCamelCase				(						)						->Tuple:
   UpperCAmelCase							=     """http://images.cocodataset.org/val2017/000000039769.jpg"""
   UpperCAmelCase							=     Image.open(requests.get(lowerCAmelCase_  ,						stream=lowerCAmelCase_   ).raw   )
   return im
def   _UpperCamelCase				(						lowerCAmelCase_   )						->List[str]:
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""image_size"""]
   UpperCAmelCase							=     EfficientNetImageProcessor(
       size={"""height""": size, """width""": size}  ,						image_mean=[0.485, 0.456, 0.406]  ,						image_std=[0.4785_3944, 0.473_2864, 0.4743_4163]  ,						do_center_crop=lowerCAmelCase_  ,						)
   return preprocessor
def   _UpperCamelCase				(						lowerCAmelCase_   )						->Any:
   UpperCAmelCase							=     [v.split("""_"""   )[0].split("""block"""   )[1] for v in original_param_names if v.startswith("""block"""   )]
   UpperCAmelCase							=     sorted(set(lowerCAmelCase_   )   )
   UpperCAmelCase							=     len(lowerCAmelCase_   )
   UpperCAmelCase							=     {b: str(lowerCAmelCase_   ) for b, i in zip(lowerCAmelCase_  ,						range(lowerCAmelCase_   )   )}

   UpperCAmelCase							=     []
   rename_keys.append(("""stem_conv/kernel:0""", """embeddings.convolution.weight""")   )
   rename_keys.append(("""stem_bn/gamma:0""", """embeddings.batchnorm.weight""")   )
   rename_keys.append(("""stem_bn/beta:0""", """embeddings.batchnorm.bias""")   )
   rename_keys.append(("""stem_bn/moving_mean:0""", """embeddings.batchnorm.running_mean""")   )
   rename_keys.append(("""stem_bn/moving_variance:0""", """embeddings.batchnorm.running_var""")   )

   for b in block_names:
      UpperCAmelCase							=     block_name_mapping[b]
      rename_keys.append((F"""block{b}_expand_conv/kernel:0""", F"""encoder.blocks.{hf_b}.expansion.expand_conv.weight""")   )
      rename_keys.append((F"""block{b}_expand_bn/gamma:0""", F"""encoder.blocks.{hf_b}.expansion.expand_bn.weight""")   )
      rename_keys.append((F"""block{b}_expand_bn/beta:0""", F"""encoder.blocks.{hf_b}.expansion.expand_bn.bias""")   )
      rename_keys.append(
          (F"""block{b}_expand_bn/moving_mean:0""", F"""encoder.blocks.{hf_b}.expansion.expand_bn.running_mean""")   )
      rename_keys.append(
          (F"""block{b}_expand_bn/moving_variance:0""", F"""encoder.blocks.{hf_b}.expansion.expand_bn.running_var""")   )
      rename_keys.append(
          (F"""block{b}_dwconv/depthwise_kernel:0""", F"""encoder.blocks.{hf_b}.depthwise_conv.depthwise_conv.weight""")   )
      rename_keys.append((F"""block{b}_bn/gamma:0""", F"""encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.weight""")   )
      rename_keys.append((F"""block{b}_bn/beta:0""", F"""encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.bias""")   )
      rename_keys.append(
          (F"""block{b}_bn/moving_mean:0""", F"""encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.running_mean""")   )
      rename_keys.append(
          (F"""block{b}_bn/moving_variance:0""", F"""encoder.blocks.{hf_b}.depthwise_conv.depthwise_norm.running_var""")   )

      rename_keys.append((F"""block{b}_se_reduce/kernel:0""", F"""encoder.blocks.{hf_b}.squeeze_excite.reduce.weight""")   )
      rename_keys.append((F"""block{b}_se_reduce/bias:0""", F"""encoder.blocks.{hf_b}.squeeze_excite.reduce.bias""")   )
      rename_keys.append((F"""block{b}_se_expand/kernel:0""", F"""encoder.blocks.{hf_b}.squeeze_excite.expand.weight""")   )
      rename_keys.append((F"""block{b}_se_expand/bias:0""", F"""encoder.blocks.{hf_b}.squeeze_excite.expand.bias""")   )
      rename_keys.append(
          (F"""block{b}_project_conv/kernel:0""", F"""encoder.blocks.{hf_b}.projection.project_conv.weight""")   )
      rename_keys.append((F"""block{b}_project_bn/gamma:0""", F"""encoder.blocks.{hf_b}.projection.project_bn.weight""")   )
      rename_keys.append((F"""block{b}_project_bn/beta:0""", F"""encoder.blocks.{hf_b}.projection.project_bn.bias""")   )
      rename_keys.append(
          (F"""block{b}_project_bn/moving_mean:0""", F"""encoder.blocks.{hf_b}.projection.project_bn.running_mean""")   )
      rename_keys.append(
          (F"""block{b}_project_bn/moving_variance:0""", F"""encoder.blocks.{hf_b}.projection.project_bn.running_var""")   )

   rename_keys.append(("""top_conv/kernel:0""", """encoder.top_conv.weight""")   )
   rename_keys.append(("""top_bn/gamma:0""", """encoder.top_bn.weight""")   )
   rename_keys.append(("""top_bn/beta:0""", """encoder.top_bn.bias""")   )
   rename_keys.append(("""top_bn/moving_mean:0""", """encoder.top_bn.running_mean""")   )
   rename_keys.append(("""top_bn/moving_variance:0""", """encoder.top_bn.running_var""")   )

   UpperCAmelCase							=     {}
   for item in rename_keys:
      if item[0] in original_param_names:
         UpperCAmelCase							=     """efficientnet.""" + item[1]

   UpperCAmelCase							=     """classifier.weight"""
   UpperCAmelCase							=     """classifier.bias"""
   return key_mapping
def   _UpperCamelCase				(						lowerCAmelCase_  ,						lowerCAmelCase_  ,						lowerCAmelCase_   )						->Tuple:
   for key, value in tf_params.items():
      if "normalization" in key:
         continue

      UpperCAmelCase							=     key_mapping[key]
      if "_conv" in key and "kernel" in key:
         UpperCAmelCase							=     torch.from_numpy(lowerCAmelCase_   ).permute(3  ,						2  ,						0  ,						1   )
      elif "depthwise_kernel" in key:
         UpperCAmelCase							=     torch.from_numpy(lowerCAmelCase_   ).permute(2  ,						3  ,						0  ,						1   )
      elif "kernel" in key:
         UpperCAmelCase							=     torch.from_numpy(np.transpose(lowerCAmelCase_   )   )
      else:
         UpperCAmelCase							=     torch.from_numpy(lowerCAmelCase_   )

      # Replace HF parameters with original TF model parameters
      assert hf_params[hf_key].shape == new_hf_value.shape
      hf_params[hf_key].copy_(lowerCAmelCase_   )
@torch.no_grad()
def   _UpperCamelCase				(						lowerCAmelCase_  ,						lowerCAmelCase_  ,						lowerCAmelCase_  ,						lowerCAmelCase_   )						->Optional[Any]:
   UpperCAmelCase							=     model_classes[model_name](
       include_top=lowerCAmelCase_  ,						weights="""imagenet"""  ,						input_tensor=lowerCAmelCase_  ,						input_shape=lowerCAmelCase_  ,						pooling=lowerCAmelCase_  ,						classes=1_0_0_0  ,						classifier_activation="""softmax"""  ,						)

   UpperCAmelCase							=     original_model.trainable_variables
   UpperCAmelCase							=     original_model.non_trainable_variables
   UpperCAmelCase							=     {param.name: param.numpy() for param in tf_params}
   for param in tf_non_train_params:
      UpperCAmelCase							=     param.numpy()
   UpperCAmelCase							=     list(tf_params.keys()   )

   # Load HuggingFace model
   UpperCAmelCase							=     get_efficientnet_config(lowerCAmelCase_   )
   UpperCAmelCase							=     EfficientNetForImageClassification(lowerCAmelCase_   ).eval()
   UpperCAmelCase							=     hf_model.state_dict()

   # Create src-to-dst parameter name mapping dictionary
   print("""Converting parameters..."""   )
   UpperCAmelCase							=     rename_keys(lowerCAmelCase_   )
   replace_params(lowerCAmelCase_  ,						lowerCAmelCase_  ,						lowerCAmelCase_   )

   # Initialize preprocessor and preprocess input image
   UpperCAmelCase							=     convert_image_processor(lowerCAmelCase_   )
   UpperCAmelCase							=     preprocessor(images=prepare_img()  ,						return_tensors="""pt"""   )

   # HF model inference
   hf_model.eval()
   with torch.no_grad():
      UpperCAmelCase							=     hf_model(**lowerCAmelCase_   )
   UpperCAmelCase							=     outputs.logits.detach().numpy()

   # Original model inference
   UpperCAmelCase							=     False
   UpperCAmelCase							=     CONFIG_MAP[model_name]["""image_size"""]
   UpperCAmelCase							=     prepare_img().resize((image_size, image_size)  ,						resample=PIL.Image.NEAREST   )
   UpperCAmelCase							=     image.img_to_array(lowerCAmelCase_   )
   UpperCAmelCase							=     np.expand_dims(lowerCAmelCase_  ,						axis=0   )
   UpperCAmelCase							=     original_model.predict(lowerCAmelCase_   )

   # Check whether original and HF model outputs match  -> np.allclose
   assert np.allclose(lowerCAmelCase_  ,						lowerCAmelCase_  ,						atol=1e-3   ), "The predicted logits are not the same."
   print("""Model outputs match!"""   )

   if save_model:
      # Create folder to save model
      if not os.path.isdir(lowerCAmelCase_   ):
         os.mkdir(lowerCAmelCase_   )
      # Save converted model and image processor
      hf_model.save_pretrained(lowerCAmelCase_   )
      preprocessor.save_pretrained(lowerCAmelCase_   )

   if push_to_hub:
      # Push model and image processor to hub
      print(F"""Pushing converted {model_name} to the hub..."""   )
      UpperCAmelCase							=     F"""efficientnet-{model_name}"""
      preprocessor.push_to_hub(lowerCAmelCase_   )
      hf_model.push_to_hub(lowerCAmelCase_   )


if __name__ == "__main__":
 __a     =			argparse.ArgumentParser()
 # Required parameters
 parser.add_argument(
     """--model_name""",
     default="""b0""",
     type=str,
     help="""Version name of the EfficientNet model you want to convert, select from [b0, b1, b2, b3, b4, b5, b6, b7].""",
 )
 parser.add_argument(
     """--pytorch_dump_folder_path""",
     default="""hf_model""",
     type=str,
     help="""Path to the output PyTorch model directory.""",
 )
 parser.add_argument("""--save_model""", action="""store_true""", help="""Save model to local""")
 parser.add_argument("""--push_to_hub""", action="""store_true""", help="""Push model and image processor to the hub""")

 __a     =			parser.parse_args()
 convert_efficientnet_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.save_model, args.push_to_hub)







from math import sqrt
def   _UpperCamelCase				(						lowerCAmelCase_ = 1_0_0_0_0_0_0   )						->int:
   UpperCAmelCase							=     0
   UpperCAmelCase							=     0
   UpperCAmelCase							=     42

   while num_cuboids <= limit:
      max_cuboid_size += 1
      for sum_shortest_sides in range(2  ,						2 * max_cuboid_size + 1   ):
         if sqrt(sum_shortest_sides**2 + max_cuboid_size**2   ).is_integer():
            num_cuboids += (
                min(lowerCAmelCase_  ,						sum_shortest_sides // 2   )
                - max(1  ,						sum_shortest_sides - max_cuboid_size   )
                + 1
            )

   return max_cuboid_size


if __name__ == "__main__":
 print(F"""{solution() = }""")



