






import argparse
import os
import shutil
from pathlib import Path

import onnx
import torch
from packaging import version
from torch.onnx import export

from diffusers import OnnxRuntimeModel, OnnxStableDiffusionPipeline, StableDiffusionPipeline


__lowerCAmelCase :List[str]     =    version.parse(version.parse(torch.__version__).base_version) < version.parse('1.11')







def    A				(							UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase=False  ,  ):
					output_path.parent.mkdir(parents=UpperCAmelCase  ,  exist_ok=UpperCAmelCase				)
					# PyTorch deprecated the `enable_onnx_checker` and `use_external_data_format` arguments in v1.11,
					# so we check the torch version for backwards compatibility
					if is_torch_less_than_1_11:
										export(
										    UpperCAmelCase  ,  UpperCAmelCase  ,  f=output_path.as_posix()  ,  input_names=UpperCAmelCase  ,  output_names=UpperCAmelCase  ,  dynamic_axes=UpperCAmelCase  ,  do_constant_folding=UpperCAmelCase  ,  use_external_data_format=UpperCAmelCase  ,  enable_onnx_checker=UpperCAmelCase  ,  opset_version=UpperCAmelCase  ,  )
					else:
										export(
										    UpperCAmelCase  ,  UpperCAmelCase  ,  f=output_path.as_posix()  ,  input_names=UpperCAmelCase  ,  output_names=UpperCAmelCase  ,  dynamic_axes=UpperCAmelCase  ,  do_constant_folding=UpperCAmelCase  ,  opset_version=UpperCAmelCase  ,  )







@torch.no_grad()
def    A				(							UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase = False				):
					_snake_case       :					Dict				       =   torch.floataa if fpaa else torch.floataa
					if fpaa and torch.cuda.is_available():
										_snake_case       :					Optional[Any]				       =   "cuda"
					elif fpaa and not torch.cuda.is_available():
										raise ValueError("`float16` model export is only supported on GPUs with CUDA"				)
					else:
										_snake_case       :					Dict				       =   "cpu"
					_snake_case       :					Optional[int]				       =   StableDiffusionPipeline.from_pretrained(UpperCAmelCase  ,  torch_dtype=UpperCAmelCase				).to(UpperCAmelCase				)
					_snake_case       :					Any				       =   Path(UpperCAmelCase				)

					# TEXT ENCODER
					_snake_case       :					Optional[int]				       =   pipeline.text_encoder.config.max_position_embeddings
					_snake_case       :					Optional[int]				       =   pipeline.text_encoder.config.hidden_size
					_snake_case       :					str				       =   pipeline.tokenizer(
					    "A sample prompt"  ,  padding="max_length"  ,  max_length=pipeline.tokenizer.model_max_length  ,  truncation=UpperCAmelCase  ,  return_tensors="pt"  ,  )
					onnx_export(
					    pipeline.text_encoder  ,  model_args=(text_input.input_ids.to(device=UpperCAmelCase  ,  dtype=torch.intaa				))  ,  output_path=output_path / "text_encoder" / "model.onnx"  ,  ordered_input_names=["input_ids"]  ,  output_names=["last_hidden_state", "pooler_output"]  ,  dynamic_axes={
					        "input_ids": {0: "batch", 1: "sequence"},
					    }  ,  opset=UpperCAmelCase  ,  )
					del pipeline.text_encoder

					# UNET
					_snake_case       :					Optional[Any]				       =   pipeline.unet.config.in_channels
					_snake_case       :					Union[str, Any]				       =   pipeline.unet.config.sample_size
					_snake_case       :					Optional[Any]				       =   output_path / "unet" / "model.onnx"
					onnx_export(
					    pipeline.unet  ,  model_args=(
					        torch.randn(2  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase				).to(device=UpperCAmelCase  ,  dtype=UpperCAmelCase				),
					        torch.randn(2				).to(device=UpperCAmelCase  ,  dtype=UpperCAmelCase				),
					        torch.randn(2  ,  UpperCAmelCase  ,  UpperCAmelCase				).to(device=UpperCAmelCase  ,  dtype=UpperCAmelCase				),
					        False,
					    )  ,  output_path=UpperCAmelCase  ,  ordered_input_names=["sample", "timestep", "encoder_hidden_states", "return_dict"]  ,  output_names=["out_sample"]  ,  dynamic_axes={
					        "sample": {0: "batch", 1: "channels", 2: "height", 3: "width"},
					        "timestep": {0: "batch"},
					        "encoder_hidden_states": {0: "batch", 1: "sequence"},
					    }  ,  opset=UpperCAmelCase  ,  use_external_data_format=UpperCAmelCase  ,  )
					_snake_case       :					Dict				       =   str(unet_path.absolute().as_posix()				)
					_snake_case       :					Union[str, Any]				       =   os.path.dirname(UpperCAmelCase				)
					_snake_case       :					str				       =   onnx.load(UpperCAmelCase				)
					# clean up existing tensor files
					shutil.rmtree(UpperCAmelCase				)
					os.mkdir(UpperCAmelCase				)
					# collate external tensor files into one
					onnx.save_model(
					    UpperCAmelCase  ,  UpperCAmelCase  ,  save_as_external_data=UpperCAmelCase  ,  all_tensors_to_one_file=UpperCAmelCase  ,  location="weights.pb"  ,  convert_attribute=UpperCAmelCase  ,  )
					del pipeline.unet

					# VAE ENCODER
					_snake_case       :					str				       =   pipeline.vae
					_snake_case       :					Dict				       =   vae_encoder.config.in_channels
					_snake_case       :					List[str]				       =   vae_encoder.config.sample_size
					# need to get the raw tensor output (sample) from the encoder
					_snake_case       :					int				       =   lambda UpperCAmelCase  ,  UpperCAmelCase				: vae_encoder.encode(UpperCAmelCase  ,  UpperCAmelCase				)[0].sample()
					onnx_export(
					    UpperCAmelCase  ,  model_args=(
					        torch.randn(1  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase				).to(device=UpperCAmelCase  ,  dtype=UpperCAmelCase				),
					        False,
					    )  ,  output_path=output_path / "vae_encoder" / "model.onnx"  ,  ordered_input_names=["sample", "return_dict"]  ,  output_names=["latent_sample"]  ,  dynamic_axes={
					        "sample": {0: "batch", 1: "channels", 2: "height", 3: "width"},
					    }  ,  opset=UpperCAmelCase  ,  )

					# VAE DECODER
					_snake_case       :					List[Any]				       =   pipeline.vae
					_snake_case       :					Any				       =   vae_decoder.config.latent_channels
					_snake_case       :					str				       =   vae_decoder.config.out_channels
					# forward only through the decoder part
					_snake_case       :					Optional[Any]				       =   vae_encoder.decode
					onnx_export(
					    UpperCAmelCase  ,  model_args=(
					        torch.randn(1  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase				).to(device=UpperCAmelCase  ,  dtype=UpperCAmelCase				),
					        False,
					    )  ,  output_path=output_path / "vae_decoder" / "model.onnx"  ,  ordered_input_names=["latent_sample", "return_dict"]  ,  output_names=["sample"]  ,  dynamic_axes={
					        "latent_sample": {0: "batch", 1: "channels", 2: "height", 3: "width"},
					    }  ,  opset=UpperCAmelCase  ,  )
					del pipeline.vae

					# SAFETY CHECKER
					if pipeline.safety_checker is not None:
										_snake_case       :					List[str]				       =   pipeline.safety_checker
										_snake_case       :					int				       =   safety_checker.config.vision_config.num_channels
										_snake_case       :					Dict				       =   safety_checker.config.vision_config.image_size
										_snake_case       :					Optional[Any]				       =   safety_checker.forward_onnx
										onnx_export(
										    pipeline.safety_checker  ,  model_args=(
										        torch.randn(
										            1  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  ).to(device=UpperCAmelCase  ,  dtype=UpperCAmelCase				),
										        torch.randn(1  ,  UpperCAmelCase  ,  UpperCAmelCase  ,  UpperCAmelCase				).to(device=UpperCAmelCase  ,  dtype=UpperCAmelCase				),
										    )  ,  output_path=output_path / "safety_checker" / "model.onnx"  ,  ordered_input_names=["clip_input", "images"]  ,  output_names=["out_images", "has_nsfw_concepts"]  ,  dynamic_axes={
										        "clip_input": {0: "batch", 1: "channels", 2: "height", 3: "width"},
										        "images": {0: "batch", 1: "height", 2: "width", 3: "channels"},
										    }  ,  opset=UpperCAmelCase  ,  )
										del pipeline.safety_checker
										_snake_case       :					Dict				       =   OnnxRuntimeModel.from_pretrained(output_path / "safety_checker"				)
										_snake_case       :					Tuple				       =   pipeline.feature_extractor
					else:
										_snake_case       :					str				       =   None
										_snake_case       :					List[str]				       =   None

					_snake_case       :					Union[str, Any]				       =   OnnxStableDiffusionPipeline(
					    vae_encoder=OnnxRuntimeModel.from_pretrained(output_path / "vae_encoder"				)  ,  vae_decoder=OnnxRuntimeModel.from_pretrained(output_path / "vae_decoder"				)  ,  text_encoder=OnnxRuntimeModel.from_pretrained(output_path / "text_encoder"				)  ,  tokenizer=pipeline.tokenizer  ,  unet=OnnxRuntimeModel.from_pretrained(output_path / "unet"				)  ,  scheduler=pipeline.scheduler  ,  safety_checker=UpperCAmelCase  ,  feature_extractor=UpperCAmelCase  ,  requires_safety_checker=safety_checker is not None  ,  )

					onnx_pipeline.save_pretrained(UpperCAmelCase				)
					print("ONNX pipeline saved to"  ,  UpperCAmelCase				)

					del pipeline
					del onnx_pipeline
					_snake_case       :					Any				       =   OnnxStableDiffusionPipeline.from_pretrained(UpperCAmelCase  ,  provider="CPUExecutionProvider"				)
					print("ONNX pipeline is loadable"				)


if __name__ == "__main__":
							__lowerCAmelCase :str     =    argparse.ArgumentParser()

							parser.add_argument(
							    '--model_path',
							    type=str,
							    required=True,
							    help='Path to the `diffusers` checkpoint to convert (either a local directory or on the Hub).',
							)

							parser.add_argument('--output_path', type=str, required=True, help='Path to the output model.')

							parser.add_argument(
							    '--opset',
							    default=14,
							    type=int,
							    help='The version of the ONNX operator set to use.',
							)
							parser.add_argument('--fp16', action='store_true', default=False, help='Export the models in `float16` mode')

							__lowerCAmelCase :Dict     =    parser.parse_args()

							convert_models(args.model_path, args.output_path, args.opset, args.fpaa)






def    A				(							UpperCAmelCase				):
					if n == 1 or not isinstance(UpperCAmelCase  ,  UpperCAmelCase				):
										return 0
					elif n == 2:
										return 1
					else:
										_snake_case       :					List[Any]				       =   [0, 1]
										for i in range(2  ,  n + 1				):
															sequence.append(sequence[i - 1] + sequence[i - 2]				)

										return sequence[n]







def    A				(							UpperCAmelCase				):
					_snake_case       :					Tuple				       =   0
					_snake_case       :					Optional[Any]				       =   2

					while digits < n:
										index += 1
										_snake_case       :					str				       =   len(str(fibonacci(UpperCAmelCase				)				)				)

					return index







def    A				(							UpperCAmelCase = 1_000				):
					return fibonacci_digits_index(UpperCAmelCase				)


if __name__ == "__main__":
							print(solution(int(str(input()).strip())))