


'''simple docstring'''







from manim import *


class 			__lowerCamelCase			(	a_	):
    """simple docstring"""


    def        A   (  self      :							Any):
           _A					:     Any     = Rectangle(height=0.5				,							width=0.5)
           _A					:     List[str]     = Rectangle(height=0.46				,							width=0.46).set_stroke(width=0)

           _A					:     List[str]     = Rectangle(height=0.25				,							width=0.25)

           _A					:     Optional[Any]     = [mem.copy() for i in range(6)]
           _A					:     Tuple     = [mem.copy() for i in range(6)]
           _A					:     Dict     = VGroup(*_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)
           _A					:     Optional[int]     = VGroup(*_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)
           _A					:     str     = VGroup(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)
           _A					:     Dict     = Text('CPU'				,							font_size=24)
           _A					:     List[str]     = Group(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0.5				,							aligned_edge=_SCREAMING_SNAKE_CASE)
           cpu.move_to([-2.5, -0.5, 0])
           self.add(_SCREAMING_SNAKE_CASE)

           _A					:     Union[str, Any]     = [mem.copy() for i in range(4)]
           _A					:     Tuple     = VGroup(*_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)
           _A					:     Union[str, Any]     = Text('GPU'				,							font_size=24)
           _A					:     Optional[int]     = Group(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0.5				,							aligned_edge=_SCREAMING_SNAKE_CASE)
           gpu.move_to([-1, -1, 0])
           self.add(_SCREAMING_SNAKE_CASE)

           _A					:     Tuple     = [mem.copy() for i in range(6)]
           _A					:     List[str]     = VGroup(*_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)

           _A					:     int     = Text('Model'				,							font_size=24)
           _A					:     List[str]     = Group(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0.5				,							aligned_edge=_SCREAMING_SNAKE_CASE)
           model.move_to([3, -1.0, 0])
           self.add(_SCREAMING_SNAKE_CASE)

           _A					:     Union[str, Any]     = []
           _A					:     str     = []

           for i, rect in enumerate(_SCREAMING_SNAKE_CASE):
                  _A					:     Tuple     = fill.copy().set_fill(_SCREAMING_SNAKE_CASE				,							opacity=0.8)
                  target.move_to(_SCREAMING_SNAKE_CASE)
                  model_arr.append(_SCREAMING_SNAKE_CASE)

                  _A					:     Optional[int]     = Rectangle(height=0.46				,							width=0.46).set_stroke(width=0.0).set_fill(_SCREAMING_SNAKE_CASE				,							opacity=0.8)
                  cpu_target.move_to(cpu_left_col_base[i])
                  model_cpu_arr.append(_SCREAMING_SNAKE_CASE)

           self.add(*_SCREAMING_SNAKE_CASE				,							*_SCREAMING_SNAKE_CASE)

           _A					:     int     = [meta_mem.copy() for i in range(6)]
           _A					:     List[str]     = [meta_mem.copy() for i in range(6)]
           _A					:     Tuple     = VGroup(*_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)
           _A					:     Optional[int]     = VGroup(*_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)
           _A					:     Union[str, Any]     = VGroup(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0)
           _A					:     Optional[int]     = Text('Disk'				,							font_size=24)
           _A					:     Tuple     = Group(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE).arrange(_SCREAMING_SNAKE_CASE				,							buff=0.5				,							aligned_edge=_SCREAMING_SNAKE_CASE)
           disk.move_to([-4, -1.25, 0])
           self.add(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE)

           _A					:     Union[str, Any]     = Square(side_length=2.2)
           key.move_to([-5, 2, 0])

           _A					:     Optional[int]     = MarkupText(
               F'<b>Key:</b>\n\n<span fgcolor=\'{YELLOW}\'>●</span> Empty Model'				,							font_size=18				,							)

           key_text.move_to([-5, 2.4, 0])

           self.add(_SCREAMING_SNAKE_CASE				,							_SCREAMING_SNAKE_CASE)

           _A					:     Dict     = MarkupText(
               F'<span fgcolor=\'{BLUE}\'>●</span> Checkpoint'				,							font_size=18				,							)

           blue_text.next_to(_SCREAMING_SNAKE_CASE				,							DOWN * 2.4				,							aligned_edge=key_text.get_left())
           self.add(_SCREAMING_SNAKE_CASE)

           _A					:     str     = MarkupText(
               F'Now watch as an input is passed through the model\nand how the memory is utilized and handled.'				,							font_size=24				,							)
           step_a.move_to([2, 2, 0])

           self.play(Write(_SCREAMING_SNAKE_CASE))

           _A					:     Tuple     = Square(0.3)
           input.set_fill(_SCREAMING_SNAKE_CASE				,							opacity=1.0)
           input.set_stroke(width=0.0)
           input.next_to(model_base[0]				,							_SCREAMING_SNAKE_CASE				,							buff=0.5)

           self.play(Write(_SCREAMING_SNAKE_CASE))

           input.generate_target()
           input.target.next_to(model_arr[0]				,							direction=_SCREAMING_SNAKE_CASE				,							buff=0.02)
           self.play(MoveToTarget(_SCREAMING_SNAKE_CASE))

           self.play(FadeOut(_SCREAMING_SNAKE_CASE))

           _A					:     str     = Arrow(start=_SCREAMING_SNAKE_CASE				,							end=_SCREAMING_SNAKE_CASE				,							color=_SCREAMING_SNAKE_CASE				,							buff=0.5)
           a.next_to(model_arr[0].get_left()				,							_SCREAMING_SNAKE_CASE				,							buff=0.2)

           model_cpu_arr[0].generate_target()
           model_cpu_arr[0].target.move_to(gpu_rect[0])

           _A					:     Tuple     = MarkupText(
               F'As the input reaches a layer, the hook triggers\nand weights are moved from the CPU\nto the GPU and back.'				,							font_size=24				,							)
           step_a.move_to([2, 2, 0])

           self.play(Write(_SCREAMING_SNAKE_CASE				,							run_time=3))

           _A					:     Optional[Any]     = {'''run_time''': 1, '''fade_in''': True, '''fade_out''': True, '''buff''': 0.02}

           self.play(
               Write(_SCREAMING_SNAKE_CASE)				,							Circumscribe(model_arr[0]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(model_cpu_arr[0]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(gpu_rect[0]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							)
           self.play(MoveToTarget(model_cpu_arr[0]))

           _A					:     int     = a.copy()
           for i in range(6):
                  a_c.next_to(model_arr[i].get_right() + 0.02				,							_SCREAMING_SNAKE_CASE				,							buff=0.2)

                  input.generate_target()
                  input.target.move_to(model_arr[i].get_right() + 0.02)

                  _A					:     Optional[int]     = AnimationGroup(
                      FadeOut(_SCREAMING_SNAKE_CASE				,							run_time=0.5)				,							MoveToTarget(_SCREAMING_SNAKE_CASE				,							run_time=0.5)				,							FadeIn(_SCREAMING_SNAKE_CASE				,							run_time=0.5)				,							lag_ratio=0.2)

                  self.play(_SCREAMING_SNAKE_CASE)

                  model_cpu_arr[i].generate_target()
                  model_cpu_arr[i].target.move_to(cpu_left_col_base[i])

                  if i < 5:
                         model_cpu_arr[i + 1].generate_target()
                         model_cpu_arr[i + 1].target.move_to(gpu_rect[0])
                         if i >= 1:
                                _A					:     List[Any]     = 0.7

                         self.play(
                             Circumscribe(model_arr[i]				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(cpu_left_col_base[i]				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(cpu_left_col_base[i + 1]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(gpu_rect[0]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(model_arr[i + 1]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							)
                         if i < 1:
                                self.play(
                                    MoveToTarget(model_cpu_arr[i])				,							MoveToTarget(model_cpu_arr[i + 1])				,							)
                         else:
                                self.play(
                                    MoveToTarget(model_cpu_arr[i]				,							run_time=0.7)				,							MoveToTarget(model_cpu_arr[i + 1]				,							run_time=0.7)				,							)
                  else:
                         model_cpu_arr[i].generate_target()
                         model_cpu_arr[i].target.move_to(cpu_left_col_base[-1])
                         input.generate_target()
                         input.target.next_to(model_arr[-1].get_right()				,							RIGHT + 0.02				,							buff=0.2)

                         self.play(
                             Circumscribe(model_arr[-1]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(cpu_left_col_base[-1]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							Circumscribe(gpu_rect[0]				,							color=_SCREAMING_SNAKE_CASE				,							**_SCREAMING_SNAKE_CASE)				,							)

                         self.play(MoveToTarget(model_cpu_arr[i]))

                  _A					:     Dict     = a_c
                  _A					:     int     = a_c.copy()

           input.generate_target()
           input.target.next_to(model_base[-1]				,							RIGHT + 0.02				,							buff=0.5)
           self.play(
               FadeOut(_SCREAMING_SNAKE_CASE)				,							FadeOut(_SCREAMING_SNAKE_CASE				,							run_time=0.5)				,							)

           _A					:     List[Any]     = MarkupText(F'Inference on a model too large for GPU memory\nis successfully completed.'				,							font_size=24)
           step_a.move_to([2, 2, 0])

           self.play(Write(_SCREAMING_SNAKE_CASE				,							run_time=3)				,							MoveToTarget(_SCREAMING_SNAKE_CASE))

           self.wait()










'''simple docstring'''







from __future__ import annotations


class 			__lowerCamelCase			:
    """simple docstring"""


    def __init__(  self      :							List[Any]				,							SCREAMING_SNAKE_CASE      :							list[list[int]]):
           _A					:     Dict     = TypeError(
               'Matrices must be formed from a list of zero or more lists containing at '
               'least one and the same number of values, each of which must be of type '
               'int or float.')
           if len(SCREAMING_SNAKE_CASE) != 0:
                  _A					:     str     = len(rows[0])
                  if cols == 0:
                         raise error
                  for row in rows:
                         if len(SCREAMING_SNAKE_CASE) != cols:
                                raise error
                         for value in row:
                                if not isinstance(SCREAMING_SNAKE_CASE				,							(int, float)):
                                       raise error
                  _A					:     str     = rows
           else:
                  _A					:     Tuple     = []


    def        A   (  self      :							Optional[Any]):
           return [[row[i] for row in self.rows] for i in range(len(self.rows[0]))]


    @property
    def        A   (  self      :							List[str]):
           return len(self.rows)


    @property
    def        A   (  self      :							Optional[int]):
           return len(self.rows[0])


    @property
    def        A   (  self      :							Optional[int]):
           return (self.num_rows, self.num_columns)


    @property
    def        A   (  self      :							Any):
           return self.order[0] == self.order[1]


    def        A   (  self      :							int):
           _A					:     Union[str, Any]     = [
               [0 if column_num != row_num else 1 for column_num in range(self.num_rows)]
               for row_num in range(self.num_rows)
           ]
           return Matrix(SCREAMING_SNAKE_CASE)


    def        A   (  self      :							List[Any]):
           if not self.is_square:
                  return 0
           if self.order == (0, 0):
                  return 1
           if self.order == (1, 1):
                  return int(self.rows[0][0])
           if self.order == (2, 2):
                  return int(
                      (self.rows[0][0] * self.rows[1][1])
                      - (self.rows[0][1] * self.rows[1][0]))
           else:
                  return sum(
                      self.rows[0][column] * self.cofactors().rows[0][column]
                      for column in range(self.num_columns))


    def        A   (  self      :							Tuple):
           return bool(self.determinant())


    def        A   (  self      :							int				,							SCREAMING_SNAKE_CASE      :							int				,							SCREAMING_SNAKE_CASE      :							int):
           _A					:     str     = [
               [
                   self.rows[other_row][other_column]
                   for other_column in range(self.num_columns)
                   if other_column != column
               ]
               for other_row in range(self.num_rows)
               if other_row != row
           ]
           return Matrix(SCREAMING_SNAKE_CASE).determinant()


    def        A   (  self      :							List[Any]				,							SCREAMING_SNAKE_CASE      :							int				,							SCREAMING_SNAKE_CASE      :							int):
           if (row + column) % 2 == 0:
                  return self.get_minor(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE)
           return -1 * self.get_minor(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE)


    def        A   (  self      :							Optional[int]):
           return Matrix(
               [
                   [self.get_minor(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE) for column in range(self.num_columns)]
                   for row in range(self.num_rows)
               ])


    def        A   (  self      :							Optional[int]):
           return Matrix(
               [
                   [
                       self.minors().rows[row][column]
                       if (row + column) % 2 == 0
                       else self.minors().rows[row][column] * -1
                       for column in range(self.minors().num_columns)
                   ]
                   for row in range(self.minors().num_rows)
               ])


    def        A   (  self      :							Tuple):
           _A					:     str     = [
               [self.cofactors().rows[column][row] for column in range(self.num_columns)]
               for row in range(self.num_rows)
           ]
           return Matrix(SCREAMING_SNAKE_CASE)


    def        A   (  self      :							Tuple):
           _A					:     str     = self.determinant()
           if not determinant:
                  raise TypeError('Only matrices with a non-zero determinant have an inverse')
           return self.adjugate() * (1 / determinant)


    def __repr__(  self      :							str):
           return str(self.rows)


    def __str__(  self      :							Optional[int]):
           if self.num_rows == 0:
                  return "[]"
           if self.num_rows == 1:
                  return "[[" + ". ".join(str(self.rows[0])) + "]]"
           return (
               "["
               + "\n ".join(
                   [
                       '[' + '. '.join([str(SCREAMING_SNAKE_CASE) for value in row]) + '.]'
                       for row in self.rows
                   ])
               + "]"
           )


    def        A   (  self      :							List[Any]				,							SCREAMING_SNAKE_CASE      :							list[int]				,							SCREAMING_SNAKE_CASE      :							int | None = None):
           _A					:     Tuple     = TypeError('Row must be a list containing all ints and/or floats')
           if not isinstance(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  raise type_error
           for value in row:
                  if not isinstance(SCREAMING_SNAKE_CASE				,							(int, float)):
                         raise type_error
           if len(SCREAMING_SNAKE_CASE) != self.num_columns:
                  raise ValueError(
                      'Row must be equal in length to the other rows in the matrix')
           if position is None:
                  self.rows.append(SCREAMING_SNAKE_CASE)
           else:
                  _A					:     List[str]     = self.rows[0:position] + [row] + self.rows[position:]


    def        A   (  self      :							List[Any]				,							SCREAMING_SNAKE_CASE      :							list[int]				,							SCREAMING_SNAKE_CASE      :							int | None = None):
           _A					:     int     = TypeError(
               'Column must be a list containing all ints and/or floats')
           if not isinstance(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  raise type_error
           for value in column:
                  if not isinstance(SCREAMING_SNAKE_CASE				,							(int, float)):
                         raise type_error
           if len(SCREAMING_SNAKE_CASE) != self.num_rows:
                  raise ValueError(
                      'Column must be equal in length to the other columns in the matrix')
           if position is None:
                  _A					:     str     = [self.rows[i] + [column[i]] for i in range(self.num_rows)]
           else:
                  _A					:     Dict     = [
                      self.rows[i][0:position] + [column[i]] + self.rows[i][position:]
                      for i in range(self.num_rows)
                  ]


    def __eq__(  self      :							List[str]				,							SCREAMING_SNAKE_CASE      :							object):
           if not isinstance(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  return NotImplemented
           return self.rows == other.rows


    def __ne__(  self      :							Any				,							SCREAMING_SNAKE_CASE      :							object):
           return not self == other


    def __neg__(  self      :							Optional[Any]):
           return self * -1


    def __add__(  self      :							Any				,							SCREAMING_SNAKE_CASE      :							Matrix):
           if self.order != other.order:
                  raise ValueError('Addition requires matrices of the same order')
           return Matrix(
               [
                   [self.rows[i][j] + other.rows[i][j] for j in range(self.num_columns)]
                   for i in range(self.num_rows)
               ])


    def __sub__(  self      :							List[str]				,							SCREAMING_SNAKE_CASE      :							Matrix):
           if self.order != other.order:
                  raise ValueError('Subtraction requires matrices of the same order')
           return Matrix(
               [
                   [self.rows[i][j] - other.rows[i][j] for j in range(self.num_columns)]
                   for i in range(self.num_rows)
               ])


    def __mul__(  self      :							Dict				,							SCREAMING_SNAKE_CASE      :							Matrix | int | float):
           if isinstance(SCREAMING_SNAKE_CASE				,							(int, float)):
                  return Matrix(
                      [[int(element * other) for element in row] for row in self.rows])
           elif isinstance(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  if self.num_columns != other.num_rows:
                         raise ValueError(
                             'The number of columns in the first matrix must '
                             'be equal to the number of rows in the second')
                  return Matrix(
                      [
                          [Matrix.dot_product(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE) for column in other.columns()]
                          for row in self.rows
                      ])
           else:
                  raise TypeError(
                      'A Matrix can only be multiplied by an int, float, or another matrix')


    def __pow__(  self      :							Any				,							SCREAMING_SNAKE_CASE      :							int):
           if not isinstance(SCREAMING_SNAKE_CASE				,							SCREAMING_SNAKE_CASE):
                  raise TypeError('A Matrix can only be raised to the power of an int')
           if not self.is_square:
                  raise ValueError('Only square matrices can be raised to a power')
           if other == 0:
                  return self.identity()
           if other < 0:
                  if self.is_invertable():
                         return self.inverse() ** (-other)
                  raise ValueError(
                      'Only invertable matrices can be raised to a negative power')
           _A					:     Union[str, Any]     = self
           for _ in range(other - 1):
                  result *= self
           return result


    @classmethod
    def        A   (  cls      :							List[str]				,							SCREAMING_SNAKE_CASE      :							list[int]				,							SCREAMING_SNAKE_CASE      :							list[int]):
           return sum(row[i] * column[i] for i in range(len(SCREAMING_SNAKE_CASE)))


if __name__ == "__main__":
   import doctest

   doctest.testmod()






