from __future__ import annotations

from sys import maxsize
from typing import Generic, TypeVar

__lowerCamelCase	:					List[str]			  =					TypeVar("""T""")



def 		A_    (					_lowerCAmelCase					)						->			int:
 return (position - 1) // 2



def 		A_    (					_lowerCAmelCase					)						->			int:
 return (2 * position) + 1



def 		A_    (					_lowerCAmelCase					)						->			int:
 return (2 * position) + 2



class  A__       (	Generic[T]      ):





      def __init__(			self       ):
       '''simple docstring'''




       UpperCamelCase     : list[tuple[T, int]]	     =       []
       UpperCamelCase     : dict[T, int]	     =       {}
       UpperCamelCase     : int	     =       0





      def __len__(			self       ):
       '''simple docstring'''




       return self.elements





      def __repr__(			self       ):
       '''simple docstring'''




       return str(self.heap       )





      def 	__UpperCamelCase(			self       ):
       '''simple docstring'''




       return self.elements == 0





      def 	__UpperCamelCase(			self	,							A_	,							A_       ):
       '''simple docstring'''




       self.heap.append((elem, weight)       )
       UpperCamelCase     : List[str]	     =       self.elements
       self.elements += 1
       self._bubble_up(snake_case_       )





      def 	__UpperCamelCase(			self       ):
       '''simple docstring'''




       if self.elements > 1:
        self._swap_nodes(0	,							self.elements - 1       )
       UpperCamelCase     : Dict	     =       self.heap.pop()
       del self.position_map[elem]
       self.elements -= 1
       if self.elements > 0:
        UpperCamelCase     : Optional[Any]	     =       self.heap[0]
        self._bubble_down(snake_case_       )
       return elem





      def 	__UpperCamelCase(			self	,							A_	,							A_       ):
       '''simple docstring'''




       UpperCamelCase     : List[str]	     =       self.position_map[elem]
       UpperCamelCase     : List[Any]	     =       (elem, weight)
       if position > 0:
        UpperCamelCase     : str	     =       get_parent_position(snake_case_       )
        UpperCamelCase     : Tuple	     =       self.heap[parent_position]
        if parent_weight > weight:
         self._bubble_up(snake_case_       )
        else:
         self._bubble_down(snake_case_       )
       else:
        self._bubble_down(snake_case_       )





      def 	__UpperCamelCase(			self	,							A_       ):
       '''simple docstring'''




       UpperCamelCase     : Dict	     =       self.position_map[elem]
       if curr_pos == 0:
        return None
       UpperCamelCase     : Any	     =       get_parent_position(snake_case_       )
       UpperCamelCase     : Optional[Any]	     =       self.heap[curr_pos]
       UpperCamelCase     : List[str]	     =       self.heap[parent_position]
       if parent_weight > weight:
        self._swap_nodes(snake_case_	,							snake_case_       )
        return self._bubble_up(snake_case_       )
       return None





      def 	__UpperCamelCase(			self	,							A_       ):
       '''simple docstring'''




       UpperCamelCase     : Tuple	     =       self.position_map[elem]
       UpperCamelCase     : Optional[Any]	     =       self.heap[curr_pos]
       UpperCamelCase     : Union[str, Any]	     =       get_child_left_position(snake_case_       )
       UpperCamelCase     : Union[str, Any]	     =       get_child_right_position(snake_case_       )
       if child_left_position < self.elements and child_right_position < self.elements:
        UpperCamelCase     : List[str]	     =       self.heap[child_left_position]
        UpperCamelCase     : Any	     =       self.heap[child_right_position]
        if child_right_weight < child_left_weight and child_right_weight < weight:
         self._swap_nodes(snake_case_	,							snake_case_       )
         return self._bubble_down(snake_case_       )
       if child_left_position < self.elements:
        UpperCamelCase     : str	     =       self.heap[child_left_position]
        if child_left_weight < weight:
         self._swap_nodes(snake_case_	,							snake_case_       )
         return self._bubble_down(snake_case_       )
       else:
        return None
       if child_right_position < self.elements:
        UpperCamelCase     : Optional[Any]	     =       self.heap[child_right_position]
        if child_right_weight < weight:
         self._swap_nodes(snake_case_	,							snake_case_       )
         return self._bubble_down(snake_case_       )
       return None





      def 	__UpperCamelCase(			self	,							A_	,							A_       ):
       '''simple docstring'''




       UpperCamelCase     : Optional[Any]	     =       self.heap[nodea_pos][0]
       UpperCamelCase     : List[Any]	     =       self.heap[nodea_pos][0]
       UpperCamelCase     : Dict	     =       (
           self.heap[nodea_pos],
           self.heap[nodea_pos],
       )
       UpperCamelCase     : Dict	     =       nodea_pos
       UpperCamelCase     : List[str]	     =       nodea_pos



class  A__       (	Generic[T]      ):





      def __init__(			self       ):
       '''simple docstring'''




       UpperCamelCase     : dict[T, dict[T, int]]	     =       {}
       UpperCamelCase     : int	     =       0





      def __repr__(			self       ):
       '''simple docstring'''




       return str(self.connections       )





      def __len__(			self       ):
       '''simple docstring'''




       return self.nodes





      def 	__UpperCamelCase(			self	,							A_       ):
       '''simple docstring'''




       if node not in self.connections:
        UpperCamelCase     : Optional[Any]	     =       {}
        self.nodes += 1





      def 	__UpperCamelCase(			self	,							A_	,							A_	,							A_       ):
       '''simple docstring'''




       self.add_node(snake_case_       )
       self.add_node(snake_case_       )
       UpperCamelCase     : List[Any]	     =       weight
       UpperCamelCase     : Union[str, Any]	     =       weight



def 		A_    (					_lowerCAmelCase							,       )						->			tuple[dict[T, int], dict[T, T | None]]:
 UpperCamelCase     : dict[T, int]	     =       {node: maxsize for node in graph.connections}
 UpperCamelCase     : dict[T, T | None]	     =       {node: None for node in graph.connections}

 UpperCamelCase     : MinPriorityQueue[T]	     =       MinPriorityQueue()
 for node, weight in dist.items():
  priority_queue.push(_lowerCAmelCase							,       _lowerCAmelCase					)

 if priority_queue.is_empty():
  return dist, parent

 # initialization
 UpperCamelCase     : Union[str, Any]	     =       priority_queue.extract_min()
 UpperCamelCase     : str	     =       0
 for neighbour in graph.connections[node]:
  if dist[neighbour] > dist[node] + graph.connections[node][neighbour]:
   UpperCamelCase     : List[Any]	     =       dist[node] + graph.connections[node][neighbour]
   priority_queue.update_key(_lowerCAmelCase							,       dist[neighbour]					)
   UpperCamelCase     : Optional[int]	     =       node

    # running prim's algorithm
 while not priority_queue.is_empty():
  UpperCamelCase     : Optional[int]	     =       priority_queue.extract_min()
  for neighbour in graph.connections[node]:
   if dist[neighbour] > dist[node] + graph.connections[node][neighbour]:
    UpperCamelCase     : List[Any]	     =       dist[node] + graph.connections[node][neighbour]
    priority_queue.update_key(_lowerCAmelCase							,       dist[neighbour]					)
    UpperCamelCase     : Dict	     =       node
 return dist, parent







from __future__ import annotations

import numpy as np
from numpy import floataa
from numpy.typing import NDArray



def 		A_    (					_lowerCAmelCase							,       _lowerCAmelCase							,       _lowerCAmelCase							,       _lowerCAmelCase							,       )						->			list[float]:
 UpperCamelCase     ,   UpperCamelCase     : List[Any]	     =       coefficient_matrix.shape
 UpperCamelCase     ,   UpperCamelCase     : Optional[int]	     =       constant_matrix.shape

 if rowsa != colsa:
  UpperCamelCase     : List[Any]	     =       F"""Coefficient matrix dimensions must be nxn but received {rowsa}x{colsa}"""
  raise ValueError(_lowerCAmelCase					)

 if colsa != 1:
  UpperCamelCase     : Any	     =       F"""Constant matrix must be nx1 but received {rowsa}x{colsa}"""
  raise ValueError(_lowerCAmelCase					)

 if rowsa != rowsa:
  UpperCamelCase     : Tuple	     =       (
      "Coefficient and constant matrices dimensions must be nxn and nx1 but "
      F"""received {rowsa}x{colsa} and {rowsa}x{colsa}"""
  )
  raise ValueError(_lowerCAmelCase					)

 if len(_lowerCAmelCase					) != rowsa:
  UpperCamelCase     : Any	     =       (
      "Number of initial values must be equal to number of rows in coefficient "
      F"""matrix but received {len(_lowerCAmelCase					)} and {rowsa}"""
  )
  raise ValueError(_lowerCAmelCase					)

 if iterations <= 0:
  raise ValueError("Iterations must be at least 1"					)

 UpperCamelCase     : NDArray[floataa]	     =       np.concatenate(
     (coefficient_matrix, constant_matrix)							,       axis=1					)

 UpperCamelCase     ,   UpperCamelCase     : str	     =       table.shape

 strictly_diagonally_dominant(_lowerCAmelCase					)

 # Iterates the whole matrix for given number of times
 for _ in range(_lowerCAmelCase					):
  UpperCamelCase     : Optional[Any]	     =       []
  for row in range(_lowerCAmelCase					):
   UpperCamelCase     : Optional[int]	     =       0
   for col in range(_lowerCAmelCase					):
    if col == row:
     UpperCamelCase     : Union[str, Any]	     =       table[row][col]
    elif col == cols - 1:
     UpperCamelCase     : List[Any]	     =       table[row][col]
    else:
     temp += (-1) * table[row][col] * init_val[col]
   UpperCamelCase     : Dict	     =       (temp + val) / denom
   new_val.append(_lowerCAmelCase					)
  UpperCamelCase     : List[str]	     =       new_val

 return [float(_lowerCAmelCase					) for i in new_val]



def 		A_    (					_lowerCAmelCase					)						->			bool:
 UpperCamelCase     ,   UpperCamelCase     : Dict	     =       table.shape

 UpperCamelCase     : List[Any]	     =       True

 for i in range(0							,       _lowerCAmelCase					):
  UpperCamelCase     : Union[str, Any]	     =       0
  for j in range(0							,       cols - 1					):
   if i == j:
    continue
   else:
    total += table[i][j]

  if table[i][i] <= total:
   raise ValueError("Coefficient matrix is not strictly diagonally dominant"					)

 return is_diagonally_dominant


# Test Cases
if __name__ == "__main__":
    import doctest

    doctest.testmod()
