'''simple docstring'''






import numpy as np






def    __UpperCAmelCase			(  a_:       Optional[Any],					a_:       str,					a_:       Optional[Any] = 1e-1_2,					a_:       Dict = 100,					):
   assert np.shape(_lowerCAmelCase							)[0] == np.shape(_lowerCAmelCase							)[1]
   # Ensure proper dimensionality.
   assert np.shape(_lowerCAmelCase							)[0] == np.shape(_lowerCAmelCase							)[0]
   # Ensure inputs are either both complex or both real
   assert np.iscomplexobj(_lowerCAmelCase							) == np.iscomplexobj(_lowerCAmelCase							)
   _UpperCAmelCase							:	Optional[int]							=   np.iscomplexobj(_lowerCAmelCase							)
   if is_complex:
      # Ensure complex input_matrix is Hermitian
      assert np.array_equal(_lowerCAmelCase,					input_matrix.conj().T							)

   # Set convergence to False. Will define convergence when we exceed max_iterations
   # or when we have small changes from one iteration to next.

   _UpperCAmelCase							:	str							=   False
   _UpperCAmelCase							:	int							=   0
   _UpperCAmelCase							:	Optional[int]							=   0
   _UpperCAmelCase							:	Tuple							=   1e1_2

   while not convergence:
      # Multiple matrix by the vector.
      _UpperCAmelCase							:	Any							=   np.dot(_lowerCAmelCase,					_lowerCAmelCase							)
      # Normalize the resulting output vector.
      _UpperCAmelCase							:	List[str]							=   w / np.linalg.norm(_lowerCAmelCase							)
      # Find rayleigh quotient
      # (faster than usual b/c we know vector is normalized already)
      _UpperCAmelCase							:	List[str]							=   vector.conj().T if is_complex else vector.T
      _UpperCAmelCase							:	List[Any]							=   np.dot(_lowerCAmelCase,					np.dot(_lowerCAmelCase,					_lowerCAmelCase							)							)

      # Check convergence.
      _UpperCAmelCase							:	List[Any]							=   np.abs(lambda_ - lambda_previous							) / lambda_
      iterations += 1

      if error <= error_tol or iterations >= max_iterations:
         _UpperCAmelCase							:	str							=   True

      _UpperCAmelCase							:	Union[str, Any]							=   lambda_

   if is_complex:
      _UpperCAmelCase							:	Optional[Any]							=   np.real(lambda_							)

   return lambda_, vector






def    __UpperCAmelCase			(  ):
   _UpperCAmelCase							:	Any							=   np.array([[41, 4, 20], [4, 26, 30], [20, 30, 50]]							)
   _UpperCAmelCase							:	str							=   np.array([41, 4, 20]							)
   _UpperCAmelCase							:	Optional[Any]							=   real_input_matrix.astype(np.complexaaa							)
   _UpperCAmelCase							:	Dict							=   np.triu(1J * complex_input_matrix,					1							)
   complex_input_matrix += imag_matrix
   complex_input_matrix += -1 * imag_matrix.T
   _UpperCAmelCase							:	Optional[int]							=   np.array([41, 4, 20]							).astype(np.complexaaa							)

   for problem_type in ["real", "complex"]:
      if problem_type == "real":
         _UpperCAmelCase							:	int							=   real_input_matrix
         _UpperCAmelCase							:	Any							=   real_vector
      elif problem_type == "complex":
         _UpperCAmelCase							:	Union[str, Any]							=   complex_input_matrix
         _UpperCAmelCase							:	Tuple							=   complex_vector

      # Our implementation.
      _UpperCAmelCase							:	List[Any]							=   power_iteration(_lowerCAmelCase,					_lowerCAmelCase							)

      # Numpy implementation.

      # Get eigenvalues and eigenvectors using built-in numpy
      # eigh (eigh used for symmetric or hermetian matrices).
      _UpperCAmelCase							:	Optional[int]							=   np.linalg.eigh(_lowerCAmelCase							)
      # Last eigenvalue is the maximum one.
      _UpperCAmelCase							:	Tuple							=   eigen_values[-1]
      # Last column in this matrix is eigenvector corresponding to largest eigenvalue.
      _UpperCAmelCase							:	List[Any]							=   eigen_vectors[:, -1]

      # Check our implementation and numpy gives close answers.
      assert np.abs(eigen_value - eigen_value_max							) <= 1e-6
      # Take absolute values element wise of each eigenvector.
      # as they are only unique to a minus sign.
      assert np.linalg.norm(np.abs(_lowerCAmelCase							) - np.abs(_lowerCAmelCase							)							) <= 1e-6


if __name__ == "__main__":
     import doctest

     doctest.testmod()
     test_power_iteration()






class 					A__   :





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




       UpperCamelCase	:					Union[str, Any]       	=   set_counts
       UpperCamelCase	:					int       	=   max(A_   )
       UpperCamelCase	:					Optional[Any]       	=   len(A_   )
       UpperCamelCase	:					Union[str, Any]       	=   [1] * num_sets
       UpperCamelCase	:					Union[str, Any]       	=   list(range(A_   )   )





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




       UpperCamelCase	:					Any       	=   self.get_parent(A_   )
       UpperCamelCase	:					Optional[int]       	=   self.get_parent(A_   )

       if src_parent == dst_parent:
        return False

       if self.ranks[dst_parent] >= self.ranks[src_parent]:
        self.set_counts[dst_parent] += self.set_counts[src_parent]
        UpperCamelCase	:					int       	=   0
        UpperCamelCase	:					Dict       	=   dst_parent
        if self.ranks[dst_parent] == self.ranks[src_parent]:
         self.ranks[dst_parent] += 1
        UpperCamelCase	:					Optional[int]       	=   self.set_counts[dst_parent]
       else:
        self.set_counts[src_parent] += self.set_counts[dst_parent]
        UpperCamelCase	:					Any       	=   0
        UpperCamelCase	:					Optional[int]       	=   src_parent
        UpperCamelCase	:					int       	=   self.set_counts[src_parent]

       UpperCamelCase	:					Any       	=   max(self.max_set       ,							A_   )
       return True





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




       if self.parents[disj_set] == disj_set:
        return disj_set
       UpperCamelCase	:					Optional[int]       	=   self.get_parent(self.parents[disj_set]   )
       return self.parents[disj_set]
