"""simple docstring"""



# DISCLAIMER: This code is strongly influenced by https://github.com/pesser/pytorch_diffusion
# and https://github.com/hojonathanho/diffusion
import math
from dataclasses import dataclass
from typing import List, Optional, Tuple, Union

import numpy as np
import torch

from diffusers.configuration_utils import ConfigMixin, register_to_config
from diffusers.schedulers.scheduling_utils import SchedulerMixin
from diffusers.utils import BaseOutput, deprecate






@dataclass
# Copied from diffusers.schedulers.scheduling_ddpm.DDPMSchedulerOutput with DDPM->DDIM
class 				snake_case__     (   snake_case_   ):
 _snake_case   :			torch.FloatTensor
 _snake_case   :			Optional[torch.FloatTensor]           =		None



def 					_lowerCamelCase(					a ,  a=0.9_99 ,  a="cosine" ,  ):
       if alpha_transform_type == "cosine":

              def alpha_bar_fn(a							):
                     return math.cos((t + 0.0_08) / 1.0_08 * math.pi / 2							) ** 2

       elif alpha_transform_type == "exp":

              def alpha_bar_fn(a							):
                     return math.exp(t * -12.0							)

       else:
              raise ValueError(F"Unsupported alpha_tranform_type: {alpha_transform_type}"							)

       __a     				=  []
       for i in range(a							):
              __a     				=  i / num_diffusion_timesteps
              __a     				=  (i + 1) / num_diffusion_timesteps
              betas.append(min(1 - alpha_bar_fn(a							) / alpha_bar_fn(a							) ,  a							)							)
       return torch.tensor(a ,  dtype=torch.floataa							)






class 				snake_case__     (   snake_case_,		snake_case_   ):
 _snake_case   :			str           =		1


 @register_to_config
 def __init__(				self  ,						lowerCamelCase = 1000  ,						lowerCamelCase = 0.0001  ,						lowerCamelCase = 0.02  ,						lowerCamelCase = "linear"  ,						lowerCamelCase = None  ,						lowerCamelCase = True  ,						lowerCamelCase = True  ,						lowerCamelCase = 0  ,						lowerCamelCase = "epsilon"  ,						lowerCamelCase = 1.0  ,						**lowerCamelCase  ,						):
        if kwargs.get("set_alpha_to_one"  ,						lowerCamelCase		) is not None:
               __a     				=  (
                   "The `set_alpha_to_one` argument is deprecated. Please use `set_alpha_to_zero` instead."
               )
               deprecate("set_alpha_to_one"  ,						"1.0.0"  ,						lowerCamelCase  ,						standard_warn=lowerCamelCase		)
               __a     				=  kwargs["set_alpha_to_one"]
        if trained_betas is not None:
               __a     				=  torch.tensor(lowerCamelCase  ,						dtype=torch.floataa		)
        elif beta_schedule == "linear":
               __a     				=  torch.linspace(lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase  ,						dtype=torch.floataa		)
        elif beta_schedule == "scaled_linear":
               # this schedule is very specific to the latent diffusion model.
               __a     				=  (
                   torch.linspace(beta_start**0.5  ,						beta_end**0.5  ,						lowerCamelCase  ,						dtype=torch.floataa		) ** 2
               )
        elif beta_schedule == "squaredcos_cap_v2":
               # Glide cosine schedule
               __a     				=  betas_for_alpha_bar(lowerCamelCase		)
        else:
               raise NotImplementedError(F"{beta_schedule} does is not implemented for {self.__class__}"		)

        __a     				=  1.0 - self.betas
        __a     				=  torch.cumprod(self.alphas  ,						dim=0		)

        # At every step in inverted ddim, we are looking into the next alphas_cumprod
        # For the final step, there is no next alphas_cumprod, and the index is out of bounds
        # `set_alpha_to_zero` decides whether we set this parameter simply to zero
        # in this case, self.step() just output the predicted noise
        # or whether we use the final alpha of the "non-previous" one.
        __a     				=  torch.tensor(0.0		) if set_alpha_to_zero else self.alphas_cumprod[-1]

        # standard deviation of the initial noise distribution
        __a     				=  1.0

        # setable values
        __a     				=  None
        __a     				=  torch.from_numpy(np.arange(0  ,						lowerCamelCase		).copy().astype(np.intaa		)		)


 def 		a__ (				self  ,						lowerCamelCase  ,						lowerCamelCase = None		):
        return sample


 def 		a__ (				self  ,						lowerCamelCase  ,						lowerCamelCase = None		):

        if num_inference_steps > self.config.num_train_timesteps:
               raise ValueError(
                   F"`num_inference_steps`: {num_inference_steps} cannot be larger than `self.config.train_timesteps`:"
                   F" {self.config.num_train_timesteps} as the unet model trained with this scheduler can only handle"
                   F" maximal {self.config.num_train_timesteps} timesteps."		)

        __a     				=  num_inference_steps
        __a     				=  self.config.num_train_timesteps // self.num_inference_steps
        # creates integer timesteps by multiplying by ratio
        # casting to int to avoid issues when num_inference_step is power of 3
        __a     				=  (np.arange(0  ,						lowerCamelCase		) * step_ratio).round().copy().astype(np.intaa		)
        __a     				=  torch.from_numpy(lowerCamelCase		).to(lowerCamelCase		)
        self.timesteps += self.config.steps_offset


 def 		a__ (				self  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase  ,						lowerCamelCase = 0.0  ,						lowerCamelCase = False  ,						lowerCamelCase = None  ,						lowerCamelCase = True  ,						):
        # 1. get previous step value (=t+1)
        __a     				=  timestep + self.config.num_train_timesteps // self.num_inference_steps

        # 2. compute alphas, betas
        # change original implementation to exactly match noise levels for analogous forward process
        __a     				=  self.alphas_cumprod[timestep]
        __a     				=  (
            self.alphas_cumprod[prev_timestep]
            if prev_timestep < self.config.num_train_timesteps
            else self.final_alpha_cumprod
        )

        __a     				=  1 - alpha_prod_t

        # 3. compute predicted original sample from predicted noise also called
        # "predicted x_0" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf
        if self.config.prediction_type == "epsilon":
               __a     				=  (sample - beta_prod_t ** 0.5 * model_output) / alpha_prod_t ** 0.5
               __a     				=  model_output
        elif self.config.prediction_type == "sample":
               __a     				=  model_output
               __a     				=  (sample - alpha_prod_t ** 0.5 * pred_original_sample) / beta_prod_t ** 0.5
        elif self.config.prediction_type == "v_prediction":
               __a     				=  (alpha_prod_t**0.5) * sample - (beta_prod_t**0.5) * model_output
               __a     				=  (alpha_prod_t**0.5) * model_output + (beta_prod_t**0.5) * sample
        else:
               raise ValueError(
                   F"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, `sample`, or"
                   " `v_prediction`"		)

        # 4. Clip or threshold "predicted x_0"
        if self.config.clip_sample:
               __a     				=  pred_original_sample.clamp(
                   -self.config.clip_sample_range  ,						self.config.clip_sample_range		)

        # 5. compute "direction pointing to x_t" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf
        __a     				=  (1 - alpha_prod_t_prev) ** 0.5 * pred_epsilon

        # 6. compute x_t without "random noise" of formula (12) from https://arxiv.org/pdf/2010.02502.pdf
        __a     				=  alpha_prod_t_prev ** 0.5 * pred_original_sample + pred_sample_direction

        if not return_dict:
               return (prev_sample, pred_original_sample)
        return DDIMSchedulerOutput(prev_sample=lowerCamelCase  ,						pred_original_sample=lowerCamelCase		)






 def __len__(				self		):
        return self.config.num_train_timesteps

"""simple docstring"""



import os



def 					_lowerCamelCase(					):
       with open(os.path.dirname(a							) + "/grid.txt"							) as f:
              __a     				=  []  # noqa: E741
              for _ in range(2_0							):
                     l.append([int(a							) for x in f.readline().split()]							)

              __a     				=  0

              # right
              for i in range(2_0							):
                     for j in range(1_7							):
                            __a     				=  l[i][j] * l[i][j + 1] * l[i][j + 2] * l[i][j + 3]
                            if temp > maximum:
                                   __a     				=  temp

        # down
              for i in range(1_7							):
                     for j in range(2_0							):
                            __a     				=  l[i][j] * l[i + 1][j] * l[i + 2][j] * l[i + 3][j]
                            if temp > maximum:
                                   __a     				=  temp

        # diagonal 1
              for i in range(1_7							):
                     for j in range(1_7							):
                            __a     				=  l[i][j] * l[i + 1][j + 1] * l[i + 2][j + 2] * l[i + 3][j + 3]
                            if temp > maximum:
                                   __a     				=  temp

        # diagonal 2
              for i in range(1_7							):
                     for j in range(3 ,  2_0							):
                            __a     				=  l[i][j] * l[i + 1][j - 1] * l[i + 2][j - 2] * l[i + 3][j - 3]
                            if temp > maximum:
                                   __a     				=  temp
              return maximum


if __name__ == "__main__":
   print(solution())
