






from __future__ import annotations

from collections import deque






class 						lowercase_   :






      '''simple docstring'''




      def __init__( self :		List[Any]					,   __UpperCAmelCase :		list[str]    )       ->Union[str, Any]:




       """simple docstring"""


       a						    = []
       self.adlist.append(
           {'''value''': '''''', '''next_states''': [], '''fail_state''': 0, '''output''': []}    )

       for keyword in keywords:
        self.add_keyword(__UpperCAmelCase    )
       self.set_fail_transitions()







      def  __lowerCAmelCase   ( self :		List[Any]					,   __UpperCAmelCase :		int					,   __UpperCAmelCase :		str    )       ->int | None:




       """simple docstring"""


       for state in self.adlist[current_state]["next_states"]:
        if char == self.adlist[state]["value"]:
         return state
       return None







      def  __lowerCAmelCase   ( self :		str					,   __UpperCAmelCase :		str    )       ->None:




       """simple docstring"""


       a						    = 0
       for character in keyword:
        a						    = self.find_next_state(__UpperCAmelCase					,   __UpperCAmelCase    )
        if next_state is None:
         self.adlist.append(
             {
                 '''value''': character,
                 '''next_states''': [],
                 '''fail_state''': 0,
                 '''output''': [],
             }    )
         self.adlist[current_state]["next_states"].append(len(self.adlist    ) - 1    )
         a						    = len(self.adlist    ) - 1
        else:
         a						    = next_state
       self.adlist[current_state]["output"].append(__UpperCAmelCase    )







      def  __lowerCAmelCase   ( self :		List[Any]    )       ->None:




       """simple docstring"""


       a						    = deque()
       for node in self.adlist[0]["next_states"]:
        q.append(__UpperCAmelCase    )
        a						    = 0
       while q:
        a						    = q.popleft()
        for child in self.adlist[r]["next_states"]:
         q.append(__UpperCAmelCase    )
         a						    = self.adlist[r]['''fail_state''']
         while (
             self.find_next_state(__UpperCAmelCase					,   self.adlist[child]['''value''']    ) is None
             and state != 0
         ):
          a						    = self.adlist[state]['''fail_state''']
         a						    = self.find_next_state(
             __UpperCAmelCase					,   self.adlist[child]['''value''']    )
         if self.adlist[child]["fail_state"] is None:
          a						    = 0
         a						    = (
             self.adlist[child]['''output''']
             + self.adlist[self.adlist[child]['''fail_state''']]['''output''']
         )







      def  __lowerCAmelCase   ( self :		Any					,   __UpperCAmelCase :		str    )       ->dict[str, list[int]]:




       """simple docstring"""


       a						    = {}  # returns a dict with keywords and list of its occurrences
       a						    = 0
       for i in range(len(__UpperCAmelCase    )    ):
        while (
            self.find_next_state(__UpperCAmelCase					,   string[i]    ) is None
            and current_state != 0
        ):
         a						    = self.adlist[current_state]['''fail_state''']
        a						    = self.find_next_state(__UpperCAmelCase					,   string[i]    )
        if next_state is None:
         a						    = 0
        else:
         a						    = next_state
         for key in self.adlist[current_state]["output"]:
          if key not in result:
           a						    = []
          result[key].append(i - len(__UpperCAmelCase    ) + 1    )
       return result


if __name__ == "__main__":
     import doctest

     doctest.testmod()










# We ignore warnings about stepping the scheduler since we step it ourselves during gradient accumulation

import warnings

from .state import AcceleratorState, GradientState


warnings.filterwarnings("ignore", category=UserWarning, module="torch.optim.lr_scheduler")






class 						lowercase_   :






      '''simple docstring'''




      def __init__( self :		Optional[int]					,   __UpperCAmelCase :		str					,   __UpperCAmelCase :		str					,   __UpperCAmelCase :		bool = True					,   __UpperCAmelCase :		bool = False    )       ->Tuple:




       """simple docstring"""


       a						    = scheduler
       a						    = optimizers if isinstance(__UpperCAmelCase					,   (list, tuple)    ) else [optimizers]
       a						    = split_batches
       a						    = step_with_optimizer
       a						    = GradientState()







      def  __lowerCAmelCase   ( self :		Tuple					,   *__UpperCAmelCase :		List[Any]					,   **__UpperCAmelCase :		Optional[Any]    )       ->int:




       """simple docstring"""


       if not self.step_with_optimizer:
        # No link between scheduler and optimizer -> just step
        self.scheduler.step(*__UpperCAmelCase					,   **__UpperCAmelCase    )
        return

       # Otherwise, first make sure the optimizer was stepped.
       if not self.gradient_state.sync_gradients:
        if self.gradient_state.adjust_scheduler:
         self.scheduler._step_count += 1
        return

       for opt in self.optimizers:
        if opt.step_was_skipped:
         return
       if self.split_batches:
        # Split batches -> the training dataloader batch size is not changed so one step per training step
        self.scheduler.step(*__UpperCAmelCase					,   **__UpperCAmelCase    )
       else:
        # Otherwise the training dataloader batch size was multiplied by `num_processes`, so we need to do
        # num_processes steps per training step
        a						    = AcceleratorState().num_processes
        for _ in range(__UpperCAmelCase    ):
         # Special case when using OneCycle and `drop_last` was not used
         if hasattr(self.scheduler					,   '''total_steps'''    ):
          if self.scheduler._step_count <= self.scheduler.total_steps:
           self.scheduler.step(*__UpperCAmelCase					,   **__UpperCAmelCase    )
         else:
          self.scheduler.step(*__UpperCAmelCase					,   **__UpperCAmelCase    )







      def  __lowerCAmelCase   ( self :		Optional[int]    )       ->List[str]:




       """simple docstring"""


       return self.scheduler.get_last_lr()







      def  __lowerCAmelCase   ( self :		Optional[Any]    )       ->Any:




       """simple docstring"""


       return self.scheduler.state_dict()







      def  __lowerCAmelCase   ( self :		Union[str, Any]					,   __UpperCAmelCase :		Any    )       ->Tuple:




       """simple docstring"""


       self.scheduler.load_state_dict(__UpperCAmelCase    )







      def  __lowerCAmelCase   ( self :		Dict    )       ->Optional[int]:




       """simple docstring"""


       return self.scheduler.get_lr()







      def  __lowerCAmelCase   ( self :		int					,   *__UpperCAmelCase :		List[str]					,   **__UpperCAmelCase :		Optional[Any]    )       ->List[str]:




       """simple docstring"""


       return self.scheduler.print_lr(*__UpperCAmelCase					,   **__UpperCAmelCase    )


