'''simple docstring'''

import inspect
import unittest

import torch
import torch.nn as nn

from accelerate.hooks import (
    AlignDevicesHook,
    ModelHook,
    SequentialHook,
    add_hook_to_module,
    attach_align_device_hook,
    remove_hook_from_module,
    remove_hook_from_submodules,
)
from accelerate.test_utils import require_multi_gpu



class 			UpperCAmelCase  (						nn.Module					):





       '''simple docstring'''



       def __init__(						self )  ->  Optional[Any]:
        super().__init__()
        lowercase__				:    int  =					nn.Linear(3	,   4 )
        lowercase__				:    List[str]  =					nn.BatchNormad(4 )
        lowercase__				:    str  =					nn.Linear(4	,   5 )


       def _lowerCAmelCase(						self	,   __lowerCAmelCase )  ->  Tuple:
        return self.lineara(self.batchnorm(self.lineara(__lowerCAmelCase ) ) )



class 			UpperCAmelCase  (						a__					):





       '''simple docstring'''



       def _lowerCAmelCase(						self	,   __lowerCAmelCase	,   *__lowerCAmelCase	,   **__lowerCAmelCase )  ->  List[str]:
        return (args[0] + 1,) + args[1:], kwargs



class 			UpperCAmelCase  (						a__					):





       '''simple docstring'''



       def _lowerCAmelCase(						self	,   __lowerCAmelCase	,   __lowerCAmelCase )  ->  Tuple:
        return output + 1



class 			UpperCAmelCase  (						unittest.TestCase					):





       '''simple docstring'''



       def _lowerCAmelCase(						self )  ->  Dict:
        lowercase__				:    List[str]  =					ModelForTest()
        lowercase__				:    str  =					ModelHook()

        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )
        self.assertEqual(test_model._hf_hook	,   __lowerCAmelCase )
        self.assertTrue(hasattr(__lowerCAmelCase	,   '''_old_forward''' ) )

        # Check adding the hook did not change the name or the signature
        self.assertEqual(test_model.forward.__name__	,   '''forward''' )
        self.assertListEqual(list(inspect.signature(test_model.forward ).parameters )	,   ['''x'''] )

        remove_hook_from_module(__lowerCAmelCase )
        self.assertFalse(hasattr(__lowerCAmelCase	,   '''_hf_hook''' ) )
        self.assertFalse(hasattr(__lowerCAmelCase	,   '''_old_forward''' ) )

       def _lowerCAmelCase(						self )  ->  Union[str, Any]:
        lowercase__				:    Optional[Any]  =					ModelForTest()
        lowercase__				:    List[str]  =					ModelHook()

        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase	,   append=__lowerCAmelCase )

        self.assertEqual(isinstance(test_model._hf_hook	,   __lowerCAmelCase )	,   __lowerCAmelCase )
        self.assertEqual(len(test_model._hf_hook.hooks )	,   2 )
        self.assertTrue(hasattr(__lowerCAmelCase	,   '''_old_forward''' ) )

        # Check adding the hook did not change the name or the signature
        self.assertEqual(test_model.forward.__name__	,   '''forward''' )
        self.assertListEqual(list(inspect.signature(test_model.forward ).parameters )	,   ['''x'''] )

        remove_hook_from_module(__lowerCAmelCase )
        self.assertFalse(hasattr(__lowerCAmelCase	,   '''_hf_hook''' ) )
        self.assertFalse(hasattr(__lowerCAmelCase	,   '''_old_forward''' ) )

       def _lowerCAmelCase(						self )  ->  List[str]:
        lowercase__				:    List[str]  =					ModelForTest()
        lowercase__				:    str  =					torch.randn(2	,   3 )
        lowercase__				:    Union[str, Any]  =					test_model(x + 1 )
        lowercase__				:    Optional[Any]  =					test_model(x + 2 )

        lowercase__				:    str  =					PreForwardHook()
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )
        lowercase__				:    List[Any]  =					test_model(__lowerCAmelCase )
        self.assertTrue(torch.allclose(__lowerCAmelCase	,   __lowerCAmelCase	,   atol=1E-5 ) )

        # Attaching a hook to a model when it already has one replaces, does not chain
        lowercase__				:    int  =					PreForwardHook()
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )
        lowercase__				:    Optional[int]  =					test_model(__lowerCAmelCase )
        self.assertTrue(torch.allclose(__lowerCAmelCase	,   __lowerCAmelCase	,   atol=1E-5 ) )

        # You need to use the sequential hook to chain two or more hooks
        lowercase__				:    List[Any]  =					SequentialHook(PreForwardHook()	,   PreForwardHook() )
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )

        lowercase__				:    Dict  =					test_model(__lowerCAmelCase )
        assert torch.allclose(__lowerCAmelCase	,   __lowerCAmelCase	,   atol=1E-5 )

       def _lowerCAmelCase(						self )  ->  Optional[int]:
        lowercase__				:    Union[str, Any]  =					ModelForTest()
        lowercase__				:    List[Any]  =					torch.randn(2	,   3 )
        lowercase__				:    List[str]  =					test_model(__lowerCAmelCase )

        lowercase__				:    Optional[int]  =					PostForwardHook()
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )
        lowercase__				:    List[Any]  =					test_model(__lowerCAmelCase )
        self.assertTrue(torch.allclose(__lowerCAmelCase	,   output + 1	,   atol=1E-5 ) )

        # Attaching a hook to a model when it already has one replaces, does not chain
        lowercase__				:    int  =					PostForwardHook()
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )
        lowercase__				:    Optional[int]  =					test_model(__lowerCAmelCase )
        self.assertTrue(torch.allclose(__lowerCAmelCase	,   output + 1	,   atol=1E-5 ) )

        # You need to use the sequential hook to chain two or more hooks
        lowercase__				:    Tuple  =					SequentialHook(PostForwardHook()	,   PostForwardHook() )
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )

        lowercase__				:    List[Any]  =					test_model(__lowerCAmelCase )
        assert torch.allclose(__lowerCAmelCase	,   output + 2	,   atol=1E-5 )

       def _lowerCAmelCase(						self )  ->  Tuple:
        lowercase__				:    Optional[int]  =					ModelForTest()
        lowercase__				:    int  =					torch.randn(2	,   3 )
        lowercase__				:    Any  =					test_model(__lowerCAmelCase )

        lowercase__				:    Tuple  =					PostForwardHook()
        add_hook_to_module(__lowerCAmelCase	,   __lowerCAmelCase )
        lowercase__				:    int  =					test_model(__lowerCAmelCase )
        self.assertTrue(torch.allclose(__lowerCAmelCase	,   output + 1 ) )
        self.assertTrue(outputa.requires_grad )

        lowercase__				:    str  =					True
        lowercase__				:    List[str]  =					test_model(__lowerCAmelCase )
        self.assertFalse(outputa.requires_grad )

       @require_multi_gpu
       def _lowerCAmelCase(						self )  ->  int:
        lowercase__				:    List[str]  =					ModelForTest()
        # Everything is on CPU
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

        # This will move each submodule on different devices
        add_hook_to_module(model.lineara	,   AlignDevicesHook(execution_device=0 ) )
        add_hook_to_module(model.batchnorm	,   AlignDevicesHook(execution_device=0 ) )
        add_hook_to_module(model.lineara	,   AlignDevicesHook(execution_device=1 ) )

        self.assertEqual(model.lineara.weight.device	,   torch.device(0 ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device(0 ) )
        self.assertEqual(model.batchnorm.running_mean.device	,   torch.device(0 ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device(1 ) )

        # We can still make a forward pass. The input does not need to be on any particular device
        lowercase__				:    Optional[Any]  =					torch.randn(2	,   3 )
        lowercase__				:    int  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   torch.device(1 ) )

        # We can add a general hook to put back output on same device as input.
        add_hook_to_module(__lowerCAmelCase	,   AlignDevicesHook(io_same_device=__lowerCAmelCase ) )
        lowercase__				:    Optional[Any]  =					torch.randn(2	,   3 ).to(0 )
        lowercase__				:    int  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   torch.device(0 ) )

       def _lowerCAmelCase(						self )  ->  int:
        lowercase__				:    str  =					ModelForTest()

        # Everything is on CPU
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

        # This will move each submodule on different devices
        lowercase__				:    Any  =					{'''execution_device''': 0 if torch.cuda.is_available() else '''cpu''', '''offload''': True}

        add_hook_to_module(model.lineara	,   AlignDevicesHook(**__lowerCAmelCase ) )
        add_hook_to_module(model.batchnorm	,   AlignDevicesHook(**__lowerCAmelCase ) )
        add_hook_to_module(model.lineara	,   AlignDevicesHook(**__lowerCAmelCase ) )

        # Parameters have been offloaded, so on the meta device
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        # Buffers are not included in the offload by default, so are on the execution device
        lowercase__				:    Any  =					torch.device(hook_kwargs['''execution_device'''] )
        self.assertEqual(model.batchnorm.running_mean.device	,   __lowerCAmelCase )

        lowercase__				:    str  =					torch.randn(2	,   3 )
        lowercase__				:    Any  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   __lowerCAmelCase )

        # Removing hooks loads back the weights in the model.
        remove_hook_from_module(model.lineara )
        remove_hook_from_module(model.batchnorm )
        remove_hook_from_module(model.lineara )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

        # Now test with buffers included in the offload
        lowercase__				:    Union[str, Any]  =					{
            '''execution_device''': 0 if torch.cuda.is_available() else '''cpu''',
            '''offload''': True,
            '''offload_buffers''': True,
        }

        add_hook_to_module(model.lineara	,   AlignDevicesHook(**__lowerCAmelCase ) )
        add_hook_to_module(model.batchnorm	,   AlignDevicesHook(**__lowerCAmelCase ) )
        add_hook_to_module(model.lineara	,   AlignDevicesHook(**__lowerCAmelCase ) )

        # Parameters have been offloaded, so on the meta device, buffers included
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.running_mean.device	,   torch.device('''meta''' ) )

        lowercase__				:    str  =					torch.randn(2	,   3 )
        lowercase__				:    Union[str, Any]  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   __lowerCAmelCase )

        # Removing hooks loads back the weights in the model.
        remove_hook_from_module(model.lineara )
        remove_hook_from_module(model.batchnorm )
        remove_hook_from_module(model.lineara )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

       def _lowerCAmelCase(						self )  ->  int:
        lowercase__				:    Union[str, Any]  =					ModelForTest()

        # Everything is on CPU
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

        # This will move each submodule on different devices
        lowercase__				:    int  =					0 if torch.cuda.is_available() else '''cpu'''
        attach_align_device_hook(__lowerCAmelCase	,   execution_device=__lowerCAmelCase	,   offload=__lowerCAmelCase )

        # Parameters have been offloaded, so on the meta device
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        # Buffers are not included in the offload by default, so are on the execution device
        lowercase__				:    Dict  =					torch.device(__lowerCAmelCase )
        self.assertEqual(model.batchnorm.running_mean.device	,   __lowerCAmelCase )

        lowercase__				:    Any  =					torch.randn(2	,   3 )
        lowercase__				:    Union[str, Any]  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   __lowerCAmelCase )

        # Removing hooks loads back the weights in the model.
        remove_hook_from_submodules(__lowerCAmelCase )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

        # Now test with buffers included in the offload
        attach_align_device_hook(__lowerCAmelCase	,   execution_device=__lowerCAmelCase	,   offload=__lowerCAmelCase	,   offload_buffers=__lowerCAmelCase )

        # Parameters have been offloaded, so on the meta device, buffers included
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.running_mean.device	,   torch.device('''meta''' ) )

        lowercase__				:    Any  =					torch.randn(2	,   3 )
        lowercase__				:    Any  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   __lowerCAmelCase )

        # Removing hooks loads back the weights in the model.
        remove_hook_from_submodules(__lowerCAmelCase )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )


       def _lowerCAmelCase(						self )  ->  int:
        lowercase__				:    Optional[int]  =					ModelForTest()

        # Everything is on CPU
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

        # This will move each submodule on different devices
        lowercase__				:    Dict  =					0 if torch.cuda.is_available() else '''cpu'''
        attach_align_device_hook(
            __lowerCAmelCase	,   execution_device=__lowerCAmelCase	,   offload=__lowerCAmelCase	,   weights_map=model.state_dict() )

        # Parameters have been offloaded, so on the meta device
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        # Buffers are not included in the offload by default, so are on the execution device
        lowercase__				:    Optional[int]  =					torch.device(__lowerCAmelCase )
        self.assertEqual(model.batchnorm.running_mean.device	,   __lowerCAmelCase )

        lowercase__				:    List[Any]  =					torch.randn(2	,   3 )
        lowercase__				:    Tuple  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   __lowerCAmelCase )

        # Removing hooks loads back the weights in the model.
        remove_hook_from_submodules(__lowerCAmelCase )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )

        # Now test with buffers included in the offload
        attach_align_device_hook(
            __lowerCAmelCase	,   execution_device=__lowerCAmelCase	,   offload=__lowerCAmelCase	,   weights_map=model.state_dict()	,   offload_buffers=__lowerCAmelCase	,   )

        # Parameters have been offloaded, so on the meta device, buffers included
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''meta''' ) )
        self.assertEqual(model.batchnorm.running_mean.device	,   torch.device('''meta''' ) )

        lowercase__				:    Dict  =					torch.randn(2	,   3 )
        lowercase__				:    Tuple  =					model(__lowerCAmelCase )
        self.assertEqual(output.device	,   __lowerCAmelCase )

        # Removing hooks loads back the weights in the model.
        remove_hook_from_submodules(__lowerCAmelCase )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.batchnorm.weight.device	,   torch.device('''cpu''' ) )
        self.assertEqual(model.lineara.weight.device	,   torch.device('''cpu''' ) )


'''simple docstring'''

import logging

import numpy as np
import pytest
from scipy.linalg import eigh

logging.basicConfig(level=logging.INFO, format="""%(message)s""")
def 			__UpperCamelCase       (   UpperCAmelCase     ):
 return input_array.reshape((input_array.size, 1)     )
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     ):
 lowercase__				:    Dict  =					np.nan
 for i in range(UpperCAmelCase     ):
  lowercase__				:    Optional[Any]  =					features[:, labels == i]
  lowercase__				:    Optional[Any]  =					data.mean(1     )
  # Centralize the data of class i
  lowercase__				:    Dict  =					data - column_reshape(UpperCAmelCase     )
  if i > 0:
   # If covariance_sum is not None
   covariance_sum += np.dot(UpperCAmelCase		,     centered_data.T     )
  else:
   # If covariance_sum is np.nan (i.e. first loop)
   lowercase__				:    List[str]  =					np.dot(UpperCAmelCase		,     centered_data.T     )

 return covariance_sum / features.shape[1]
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     ):
 lowercase__				:    Tuple  =					features.mean(1     )
 lowercase__				:    Dict  =					np.nan
 for i in range(UpperCAmelCase     ):
  lowercase__				:    List[str]  =					features[:, labels == i]
  lowercase__				:    int  =					data.shape[1]
  lowercase__				:    Optional[int]  =					data.mean(1     )
  if i > 0:
   # If covariance_sum is not None
   covariance_sum += device_data * np.dot(
       column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )		,     (column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )).T		,     )
  else:
   # If covariance_sum is np.nan (i.e. first loop)
   lowercase__				:    Optional[int]  =					device_data * np.dot(
       column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )		,     (column_reshape(UpperCAmelCase     ) - column_reshape(UpperCAmelCase     )).T		,     )

 return covariance_sum / features.shape[1]
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase     ):

 # Check if the features have been loaded
 if features.any():
  lowercase__				:    Optional[Any]  =					features.mean(1     )
  # Center the dataset
  lowercase__				:    List[str]  =					features - np.reshape(UpperCAmelCase		,     (data_mean.size, 1)     )
  lowercase__				:    Optional[Any]  =					np.dot(UpperCAmelCase		,     centered_data.T     ) / features.shape[1]
  lowercase__ ,							lowercase__				:    Tuple  =					np.linalg.eigh(UpperCAmelCase     )
  # Take all the columns in the reverse order (-1), and then takes only the first
  lowercase__				:    str  =					eigenvectors[:, ::-1][:, 0:dimensions]
  # Project the database on the new space
  lowercase__				:    Tuple  =					np.dot(filtered_eigenvectors.T		,     UpperCAmelCase     )
  logging.info('''Principal Component Analysis computed'''     )

  return projected_data
 else:
  logging.basicConfig(level=logging.ERROR		,     format='''%(message)s'''		,     force=UpperCAmelCase     )
  logging.error('''Dataset empty'''     )
  raise AssertionError
def 			__UpperCamelCase       (   UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     ):
 assert classes > dimensions

 # Check if features have been already loaded
 if features.any:
  lowercase__ ,							lowercase__				:    Any  =					eigh(
      covariance_between_classes(UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     )		,     covariance_within_classes(UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     )		,     )
  lowercase__				:    Optional[int]  =					eigenvectors[:, ::-1][:, :dimensions]
  lowercase__ ,							lowercase__ ,							lowercase__				:    Optional[int]  =					np.linalg.svd(UpperCAmelCase     )
  lowercase__				:    List[str]  =					svd_matrix[:, 0:dimensions]
  lowercase__				:    str  =					np.dot(filtered_svd_matrix.T		,     UpperCAmelCase     )
  logging.info('''Linear Discriminant Analysis computed'''     )

  return projected_data
 else:
  logging.basicConfig(level=logging.ERROR		,     format='''%(message)s'''		,     force=UpperCAmelCase     )
  logging.error('''Dataset empty'''     )
  raise AssertionError
def 			__UpperCamelCase       (   ):
 # Create dummy dataset with 2 classes and 3 features
 lowercase__				:    List[str]  =					np.array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]     )
 lowercase__				:    Optional[Any]  =					np.array([0, 0, 0, 1, 1]     )
 lowercase__				:    str  =					2
 lowercase__				:    Dict  =					2

 # Assert that the function raises an AssertionError if dimensions > classes
 with pytest.raises(UpperCAmelCase     ) as error_info:
  lowercase__				:    int  =					linear_discriminant_analysis(
      UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase		,     UpperCAmelCase     )
  if isinstance(UpperCAmelCase		,     np.ndarray     ):
   raise AssertionError(
       '''Did not raise AssertionError for dimensions > classes'''     )
  assert error_info.type is AssertionError
def 			__UpperCamelCase       (   ):
 lowercase__				:    Optional[int]  =					np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]     )
 lowercase__				:    int  =					2
 lowercase__				:    Any  =					np.array([[6.9_2_8_2_0_3_2_3, 8.6_6_0_2_5_4_0_4, 1_0.3_9_2_3_0_4_8_5], [3.0, 3.0, 3.0]]     )

 with pytest.raises(UpperCAmelCase     ) as error_info:
  lowercase__				:    Dict  =					principal_component_analysis(UpperCAmelCase		,     UpperCAmelCase     )
  if not np.allclose(UpperCAmelCase		,     UpperCAmelCase     ):
   raise AssertionError
  assert error_info.type is AssertionError


if __name__ == "__main__":
  import doctest

  doctest.testmod()

