




'''simple docstring'''



import math
from collections import defaultdict
from typing import List, Optional, Tuple, Union

import numpy as np
import torch

from ..configuration_utils import ConfigMixin, register_to_config
from .scheduling_utils import KarrasDiffusionSchedulers, SchedulerMixin, SchedulerOutput




def   lowercase__(			__UpperCamelCase:					Dict      ,__UpperCamelCase:					int=0.9_9_9      ,__UpperCamelCase:					List[Any]="cosine"      ,):

      """simple docstring"""






      if alpha_transform_type == "cosine":

            def alpha_bar_fn(__UpperCamelCase:					Optional[int]    ):
                  return math.cos((t + 0.0_0_8) / 1.0_0_8 * math.pi / 2    ) ** 2

      elif alpha_transform_type == "exp":

            def alpha_bar_fn(__UpperCamelCase:					List[str]    ):
                  return math.exp(t * -1_2.0    )

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

      SCREAMING_SNAKE_CASE   :      Optional[int]    					=						[]
      for i in range(__UpperCamelCase    ):
            SCREAMING_SNAKE_CASE   :      Optional[Any]    					=						i / num_diffusion_timesteps
            SCREAMING_SNAKE_CASE   :      Tuple    					=						(i + 1) / num_diffusion_timesteps
            betas.append(min(1 - alpha_bar_fn(__UpperCamelCase    ) / alpha_bar_fn(__UpperCamelCase    )      ,__UpperCamelCase    )    )
      return torch.tensor(__UpperCamelCase      ,dtype=torch.floataa    )






class 							_a				(			SCREAMING_SNAKE_CASE ,      SCREAMING_SNAKE_CASE ):





       '''simple docstring'''






       A						:				str        =						[e.name for e in KarrasDiffusionSchedulers]
       A						:				Any        =						2







       @register_to_config
       def __init__(      self,							A = 1_000,							A = 0.0_00_85,							A = 0.0_12,							A = "linear",							A = None,							A = "epsilon",							A = "linspace",							A = 0,							):







             '''simple docstring'''







             if trained_betas is not None:
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						torch.tensor(A,							dtype=torch.floataa  )
             elif beta_schedule == "linear":
                   SCREAMING_SNAKE_CASE   :      Dict    					=						torch.linspace(A,							A,							A,							dtype=torch.floataa  )
             elif beta_schedule == "scaled_linear":
                   # this schedule is very specific to the latent diffusion model.
                   SCREAMING_SNAKE_CASE   :      Any    					=						(
                       torch.linspace(beta_start**0.5,							beta_end**0.5,							A,							dtype=torch.floataa  ) ** 2
                   )
             elif beta_schedule == "squaredcos_cap_v2":
                   # Glide cosine schedule
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						betas_for_alpha_bar(A  )
             else:
                   raise NotImplementedError(F"{beta_schedule} does is not implemented for {self.__class__}"  )

             SCREAMING_SNAKE_CASE   :      List[Any]    					=						1.0 - self.betas
             SCREAMING_SNAKE_CASE   :      Optional[Any]    					=						torch.cumprod(self.alphas,							dim=0  )

             #  set all values
             self.set_timesteps(A,							A,							A  )







       def        UpperCamelCase_							(      self,							A,							A=None  ):







             '''simple docstring'''







             if schedule_timesteps is None:
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						self.timesteps

             SCREAMING_SNAKE_CASE   :      Tuple    					=						(schedule_timesteps == timestep).nonzero()

             # The sigma index that is taken for the **very** first `step`
             # is always the second index (or the last index if there is only 1)
             # This way we can ensure we don't accidentally skip a sigma in
             # case we start in the middle of the denoising schedule (e.g. for image-to-image)
             if len(self._index_counter  ) == 0:
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						1 if len(A  ) > 1 else 0
             else:
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						timestep.cpu().item() if torch.is_tensor(A  ) else timestep
                   SCREAMING_SNAKE_CASE   :      List[Any]    					=						self._index_counter[timestep_int]

             return indices[pos].item()







       @property
       def        UpperCamelCase_							(      self  ):







             '''simple docstring'''







             if self.config.timestep_spacing in ["linspace", "trailing"]:
                   return self.sigmas.max()

             return (self.sigmas.max() ** 2 + 1) ** 0.5







       def        UpperCamelCase_							(      self,							A,							A,							):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      List[Any]    					=						self.index_for_timestep(A  )

             if self.state_in_first_order:
                   SCREAMING_SNAKE_CASE   :      List[Any]    					=						self.sigmas[step_index]
             else:
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						self.sigmas_interpol[step_index]

             SCREAMING_SNAKE_CASE   :      Any    					=						sample / ((sigma**2 + 1) ** 0.5)
             return sample







       def        UpperCamelCase_							(      self,							A,							A = None,							A = None,							):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      List[str]    					=						num_inference_steps

             SCREAMING_SNAKE_CASE   :      Dict    					=						num_train_timesteps or self.config.num_train_timesteps

             # "linspace", "leading", "trailing" corresponds to annotation of Table 2. of https://arxiv.org/abs/2305.08891
             if self.config.timestep_spacing == "linspace":
                   SCREAMING_SNAKE_CASE   :      Dict    					=						np.linspace(0,							num_train_timesteps - 1,							A,							dtype=A  )[::-1].copy()
             elif self.config.timestep_spacing == "leading":
                   SCREAMING_SNAKE_CASE   :      Tuple    					=						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
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						(np.arange(0,							A  ) * step_ratio).round()[::-1].copy().astype(A  )
                   timesteps += self.config.steps_offset
             elif self.config.timestep_spacing == "trailing":
                   SCREAMING_SNAKE_CASE   :      List[Any]    					=						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
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						(np.arange(A,							0,							-step_ratio  )).round().copy().astype(A  )
                   timesteps -= 1
             else:
                   raise ValueError(
                       F"{self.config.timestep_spacing} is not supported. Please make sure to choose one of 'linspace', 'leading' or 'trailing'."  )

             SCREAMING_SNAKE_CASE   :      Optional[int]    					=						np.array(((1 - self.alphas_cumprod) / self.alphas_cumprod) ** 0.5  )
             SCREAMING_SNAKE_CASE   :      Tuple    					=						torch.from_numpy(np.log(A  )  ).to(A  )

             SCREAMING_SNAKE_CASE   :      List[Any]    					=						np.interp(A,							np.arange(0,							len(A  )  ),							A  )
             SCREAMING_SNAKE_CASE   :      Tuple    					=						np.concatenate([sigmas, [0.0]]  ).astype(np.floataa  )
             SCREAMING_SNAKE_CASE   :      int    					=						torch.from_numpy(A  ).to(device=A  )

             # interpolate sigmas
             SCREAMING_SNAKE_CASE   :      str    					=						sigmas.log().lerp(sigmas.roll(1  ).log(),							0.5  ).exp()

             SCREAMING_SNAKE_CASE   :      int    					=						torch.cat([sigmas[:1], sigmas[1:].repeat_interleave(2  ), sigmas[-1:]]  )
             SCREAMING_SNAKE_CASE   :      List[Any]    					=						torch.cat(
                 [sigmas_interpol[:1], sigmas_interpol[1:].repeat_interleave(2  ), sigmas_interpol[-1:]]  )

             if str(A  ).startswith('mps'  ):
                   # mps does not support float64
                   SCREAMING_SNAKE_CASE   :      int    					=						torch.from_numpy(A  ).to(A,							dtype=torch.floataa  )
             else:
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						torch.from_numpy(A  ).to(A  )

             # interpolate timesteps
             SCREAMING_SNAKE_CASE   :      Tuple    					=						self.sigma_to_t(A  ).to(A,							dtype=timesteps.dtype  )
             SCREAMING_SNAKE_CASE   :      List[Any]    					=						torch.stack((timesteps_interpol[1:-1, None], timesteps[1:, None]),							dim=-1  ).flatten()

             SCREAMING_SNAKE_CASE   :      int    					=						torch.cat([timesteps[:1], interleaved_timesteps]  )

             SCREAMING_SNAKE_CASE   :      Any    					=						None

             # for exp beta schedules, such as the one for `pipeline_shap_e.py`
             # we need an index counter
             SCREAMING_SNAKE_CASE   :      Optional[int]    					=						defaultdict(A  )







       def        UpperCamelCase_							(      self,							A  ):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      Optional[int]    					=						sigma.log()

             # get distribution
             SCREAMING_SNAKE_CASE   :      Dict    					=						log_sigma - self.log_sigmas[:, None]

             # get sigmas range
             SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						dists.ge(0  ).cumsum(dim=0  ).argmax(dim=0  ).clamp(max=self.log_sigmas.shape[0] - 2  )
             SCREAMING_SNAKE_CASE   :      Dict    					=						low_idx + 1

             SCREAMING_SNAKE_CASE   :      List[str]    					=						self.log_sigmas[low_idx]
             SCREAMING_SNAKE_CASE   :      Tuple    					=						self.log_sigmas[high_idx]

             # interpolate sigmas
             SCREAMING_SNAKE_CASE   :      List[str]    					=						(low - log_sigma) / (low - high)
             SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						w.clamp(0,							1  )

             # transform interpolation to time range
             SCREAMING_SNAKE_CASE   :      Tuple    					=						(1 - w) * low_idx + w * high_idx
             SCREAMING_SNAKE_CASE   :      Tuple    					=						t.view(sigma.shape  )
             return t







       @property
       def        UpperCamelCase_							(      self  ):







             '''simple docstring'''







             return self.sample is None







       def        UpperCamelCase_							(      self,							A,							A,							A,							A = True,							):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      Optional[int]    					=						self.index_for_timestep(A  )

             # advance index counter by 1
             SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						timestep.cpu().item() if torch.is_tensor(A  ) else timestep
             self._index_counter[timestep_int] += 1

             if self.state_in_first_order:
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						self.sigmas[step_index]
                   SCREAMING_SNAKE_CASE   :      Tuple    					=						self.sigmas_interpol[step_index + 1]
                   SCREAMING_SNAKE_CASE   :      str    					=						self.sigmas[step_index + 1]
             else:
                   # 2nd order / KDPM2's method
                   SCREAMING_SNAKE_CASE   :      Dict    					=						self.sigmas[step_index - 1]
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						self.sigmas_interpol[step_index]
                   SCREAMING_SNAKE_CASE   :      List[Any]    					=						self.sigmas[step_index]

             # currently only gamma=0 is supported. This usually works best anyways.
             # We can support gamma in the future but then need to scale the timestep before
             # passing it to the model which requires a change in API
             SCREAMING_SNAKE_CASE   :      Optional[Any]    					=						0
             SCREAMING_SNAKE_CASE   :      Tuple    					=						sigma * (gamma + 1)  # Note: sigma_hat == sigma for now

             # 1. compute predicted original sample (x_0) from sigma-scaled predicted noise
             if self.config.prediction_type == "epsilon":
                   SCREAMING_SNAKE_CASE   :      str    					=						sigma_hat if self.state_in_first_order else sigma_interpol
                   SCREAMING_SNAKE_CASE   :      Tuple    					=						sample - sigma_input * model_output
             elif self.config.prediction_type == "v_prediction":
                   SCREAMING_SNAKE_CASE   :      Any    					=						sigma_hat if self.state_in_first_order else sigma_interpol
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						model_output * (-sigma_input / (sigma_input**2 + 1) ** 0.5) + (
                       sample / (sigma_input**2 + 1)
                   )
             elif self.config.prediction_type == "sample":
                   raise NotImplementedError('prediction_type not implemented yet: sample'  )
             else:
                   raise ValueError(
                       F"prediction_type given as {self.config.prediction_type} must be one of `epsilon`, or `v_prediction`"  )

             if self.state_in_first_order:
                   # 2. Convert to an ODE derivative for 1st order
                   SCREAMING_SNAKE_CASE   :      int    					=						(sample - pred_original_sample) / sigma_hat
                   # 3. delta timestep
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						sigma_interpol - sigma_hat

                   # store for 2nd order step
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						sample
             else:
                   # DPM-Solver-2
                   # 2. Convert to an ODE derivative for 2nd order
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						(sample - pred_original_sample) / sigma_interpol

                   # 3. delta timestep
                   SCREAMING_SNAKE_CASE   :      Any    					=						sigma_next - sigma_hat

                   SCREAMING_SNAKE_CASE   :      Tuple    					=						self.sample
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						None

             SCREAMING_SNAKE_CASE   :      List[Any]    					=						sample + derivative * dt

             if not return_dict:
                   return (prev_sample,)

             return SchedulerOutput(prev_sample=A  )







       def        UpperCamelCase_							(      self,							A,							A,							A,							):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      Optional[Any]    					=						self.sigmas.to(device=original_samples.device,							dtype=original_samples.dtype  )
             if original_samples.device.type == "mps" and torch.is_floating_point(A  ):
                   # mps does not support float64
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						self.timesteps.to(original_samples.device,							dtype=torch.floataa  )
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						timesteps.to(original_samples.device,							dtype=torch.floataa  )
             else:
                   SCREAMING_SNAKE_CASE   :      Optional[Any]    					=						self.timesteps.to(original_samples.device  )
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						timesteps.to(original_samples.device  )

             SCREAMING_SNAKE_CASE   :      List[str]    					=						[self.index_for_timestep(A,							A  ) for t in timesteps]

             SCREAMING_SNAKE_CASE   :      Tuple    					=						sigmas[step_indices].flatten()
             while len(sigma.shape  ) < len(original_samples.shape  ):
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						sigma.unsqueeze(-1  )

             SCREAMING_SNAKE_CASE   :      Optional[int]    					=						original_samples + noise * sigma
             return noisy_samples







       def __len__(      self  ):







             '''simple docstring'''







             return self.config.num_train_timesteps








'''simple docstring'''



from typing import Any






class 							_a				:





       '''simple docstring'''






       def __init__(      self,							A  ):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      str    					=						data
             SCREAMING_SNAKE_CASE   :      Any    					=						None







       def __repr__(      self  ):







             '''simple docstring'''







             return F"Node({self.data})"






class 							_a				:





       '''simple docstring'''






       def __init__(      self  ):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      List[str]    					=						None







       def __iter__(      self  ):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      Optional[Any]    					=						self.head
             while node:
                   yield node.data
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						node.next







       def __len__(      self  ):







             '''simple docstring'''







             return sum(1 for _ in self  )







       def __repr__(      self  ):







             '''simple docstring'''







             return "->".join([str(A  ) for item in self]  )







       def __getitem__(      self,							A  ):







             '''simple docstring'''







             if not 0 <= index < len(self  ):
                   raise ValueError('list index out of range.'  )
             for i, node in enumerate(self  ):
                   if i == index:
                         return node
             return None







       def __setitem__(      self,							A,							A  ):







             '''simple docstring'''







             if not 0 <= index < len(self  ):
                   raise ValueError('list index out of range.'  )
             SCREAMING_SNAKE_CASE   :      Optional[Any]    					=						self.head
             for _ in range(A  ):
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						current.next
             SCREAMING_SNAKE_CASE   :      Any    					=						data







       def        UpperCamelCase_							(      self,							A  ):







             '''simple docstring'''







             self.insert_nth(len(self  ),							A  )







       def        UpperCamelCase_							(      self,							A  ):







             '''simple docstring'''







             self.insert_nth(0,							A  )







       def        UpperCamelCase_							(      self,							A,							A  ):







             '''simple docstring'''







             if not 0 <= index <= len(self  ):
                   raise IndexError('list index out of range'  )
             SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						Node(A  )
             if self.head is None:
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						new_node
             elif index == 0:
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						self.head  # link new_node to head
                   SCREAMING_SNAKE_CASE   :      Tuple    					=						new_node
             else:
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						self.head
                   for _ in range(index - 1  ):
                         SCREAMING_SNAKE_CASE   :      str    					=						temp.next
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						temp.next
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						new_node







       def        UpperCamelCase_							(      self  ):  # print every node data







             '''simple docstring'''







             print(self  )







       def        UpperCamelCase_							(      self  ):







             '''simple docstring'''







             return self.delete_nth(0  )







       def        UpperCamelCase_							(      self  ):  # delete from tail







             '''simple docstring'''







             return self.delete_nth(len(self  ) - 1  )







       def        UpperCamelCase_							(      self,							A = 0  ):







             '''simple docstring'''







             if not 0 <= index <= len(self  ) - 1:  # test if index is valid
                   raise IndexError('List index out of range.'  )
             SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						self.head  # default first node
             if index == 0:
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						self.head.next
             else:
                   SCREAMING_SNAKE_CASE   :      Union[str, Any]    					=						self.head
                   for _ in range(index - 1  ):
                         SCREAMING_SNAKE_CASE   :      Any    					=						temp.next
                   SCREAMING_SNAKE_CASE   :      List[str]    					=						temp.next
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						temp.next.next
             return delete_node.data







       def        UpperCamelCase_							(      self  ):







             '''simple docstring'''







             return self.head is None







       def        UpperCamelCase_							(      self  ):







             '''simple docstring'''







             SCREAMING_SNAKE_CASE   :      int    					=						None
             SCREAMING_SNAKE_CASE   :      Any    					=						self.head

             while current:
                   # Store the current node's next node.
                   SCREAMING_SNAKE_CASE   :      Optional[int]    					=						current.next
                   # Make the current node's next point backwards
                   SCREAMING_SNAKE_CASE   :      int    					=						prev
                   # Make the previous node be the current node
                   SCREAMING_SNAKE_CASE   :      int    					=						current
                   # Make the current node the next node (to progress iteration)
                   SCREAMING_SNAKE_CASE   :      List[Any]    					=						next_node
             # Return prev in order to put the head at the end
             SCREAMING_SNAKE_CASE   :      List[Any]    					=						prev




def   lowercase__(			):

      """simple docstring"""






      SCREAMING_SNAKE_CASE   :      Dict    					=						LinkedList()
      assert linked_list.is_empty() is True
      assert str(__UpperCamelCase    ) == ""

      try:
            linked_list.delete_head()
            raise AssertionError  # This should not happen.
      except IndexError:
            assert True  # This should happen.

      try:
            linked_list.delete_tail()
            raise AssertionError  # This should not happen.
      except IndexError:
            assert True  # This should happen.

      for i in range(10    ):
            assert len(__UpperCamelCase    ) == i
            linked_list.insert_nth(__UpperCamelCase      ,i + 1    )
      assert str(__UpperCamelCase    ) == "->".join(str(__UpperCamelCase    ) for i in range(1      ,11    )    )

      linked_list.insert_head(0    )
      linked_list.insert_tail(11    )
      assert str(__UpperCamelCase    ) == "->".join(str(__UpperCamelCase    ) for i in range(0      ,12    )    )

      assert linked_list.delete_head() == 0
      assert linked_list.delete_nth(9    ) == 10
      assert linked_list.delete_tail() == 11
      assert len(__UpperCamelCase    ) == 9
      assert str(__UpperCamelCase    ) == "->".join(str(__UpperCamelCase    ) for i in range(1      ,10    )    )

      assert all(linked_list[i] == i + 1 for i in range(0      ,9    )    ) is True

      for i in range(0      ,9    ):
            SCREAMING_SNAKE_CASE   :      Any    					=						-i
      assert all(linked_list[i] == -i for i in range(0      ,9    )    ) is True

      linked_list.reverse()
      assert str(__UpperCamelCase    ) == "->".join(str(__UpperCamelCase    ) for i in range(-8      ,1    )    )




def   lowercase__(			):

      """simple docstring"""






      SCREAMING_SNAKE_CASE   :      List[str]    					=						[
          -9,
          1_00,
          Node(77_34_51_12    ),
          'dlrow olleH',
          7,
          55_55,
          0,
          -1_9_2.5_5_5_5_5,
          'Hello, world!',
          7_7.9,
          Node(10    ),
          None,
          None,
          1_2.2_0,
      ]
      SCREAMING_SNAKE_CASE   :      Optional[int]    					=						LinkedList()

      for i in test_input:
            linked_list.insert_tail(__UpperCamelCase    )

      # Check if it's empty or not
      assert linked_list.is_empty() is False
      assert (
          str(__UpperCamelCase    ) == "-9->100->Node(77345112)->dlrow olleH->7->5555->0->"
          "-192.55555->Hello, world!->77.9->Node(10)->None->None->12.2"
      )

      # Delete the head
      SCREAMING_SNAKE_CASE   :      str    					=						linked_list.delete_head()
      assert result == -9
      assert (
          str(__UpperCamelCase    ) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
          "Hello, world!->77.9->Node(10)->None->None->12.2"
      )

      # Delete the tail
      SCREAMING_SNAKE_CASE   :      Dict    					=						linked_list.delete_tail()
      assert result == 1_2.2
      assert (
          str(__UpperCamelCase    ) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
          "Hello, world!->77.9->Node(10)->None->None"
      )

      # Delete a node in specific location in linked list
      SCREAMING_SNAKE_CASE   :      str    					=						linked_list.delete_nth(10    )
      assert result is None
      assert (
          str(__UpperCamelCase    ) == "100->Node(77345112)->dlrow olleH->7->5555->0->-192.55555->"
          "Hello, world!->77.9->Node(10)->None"
      )

      # Add a Node instance to its head
      linked_list.insert_head(Node('Hello again, world!'    )    )
      assert (
          str(__UpperCamelCase    )
          == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->"
          "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None"
      )

      # Add None to its tail
      linked_list.insert_tail(__UpperCamelCase    )
      assert (
          str(__UpperCamelCase    )
          == "Node(Hello again, world!)->100->Node(77345112)->dlrow olleH->"
          "7->5555->0->-192.55555->Hello, world!->77.9->Node(10)->None->None"
      )

      # Reverse the linked list
      linked_list.reverse()
      assert (
          str(__UpperCamelCase    )
          == "None->None->Node(10)->77.9->Hello, world!->-192.55555->0->5555->"
          "7->dlrow olleH->Node(77345112)->100->Node(Hello again, world!)"
      )




def   lowercase__(			):

      """simple docstring"""






      from doctest import testmod

      testmod()

      SCREAMING_SNAKE_CASE   :      Dict    					=						LinkedList()
      linked_list.insert_head(input('Inserting 1st at head '    ).strip()    )
      linked_list.insert_head(input('Inserting 2nd at head '    ).strip()    )
      print('\nPrint list:'    )
      linked_list.print_list()
      linked_list.insert_tail(input('\nInserting 1st at tail '    ).strip()    )
      linked_list.insert_tail(input('Inserting 2nd at tail '    ).strip()    )
      print('\nPrint list:'    )
      linked_list.print_list()
      print('\nDelete head'    )
      linked_list.delete_head()
      print('Delete tail'    )
      linked_list.delete_tail()
      print('\nPrint list:'    )
      linked_list.print_list()
      print('\nReverse linked list'    )
      linked_list.reverse()
      print('\nPrint list:'    )
      linked_list.print_list()
      print('\nString representation of linked list:'    )
      print(__UpperCamelCase    )
      print('\nReading/changing Node data using indexing:'    )
      print(f"Element at Position 1: {linked_list[1]}"    )
      SCREAMING_SNAKE_CASE   :      str    					=						input('Enter New Value: '    ).strip()
      print('New list:'    )
      print(__UpperCamelCase    )
      print(f"length of linked_list is : {len(__UpperCamelCase    )}"    )


if __name__ == "__main__":
      main()


