"""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__ ):






							"""simple docstring"""





							return input_array.reshape((input_array.size, 1) )






def      UpperCAmelCase    (		UpperCamelCase__				,			UpperCamelCase__				,			UpperCamelCase__ ):






							"""simple docstring"""





							A__		   =							np.nan
							for i in range(_lowerCamelCase ):
														A__		   =							features[:, labels == i]
														A__		   =							data.mean(1 )
														# Centralize the data of class i
														A__		   =							data - column_reshape(_lowerCamelCase )
														if i > 0:
																					# If covariance_sum is not None
																					covariance_sum += np.dot(_lowerCamelCase				,			centered_data.T )
														else:
																					# If covariance_sum is np.nan (i.e. first loop)
																					A__		   =							np.dot(_lowerCamelCase				,			centered_data.T )

							return covariance_sum / features.shape[1]






def      UpperCAmelCase    (		UpperCamelCase__				,			UpperCamelCase__				,			UpperCamelCase__ ):






							"""simple docstring"""





							A__		   =							features.mean(1 )
							A__		   =							np.nan
							for i in range(_lowerCamelCase ):
														A__		   =							features[:, labels == i]
														A__		   =							data.shape[1]
														A__		   =							data.mean(1 )
														if i > 0:
																					# If covariance_sum is not None
																					covariance_sum += device_data * np.dot(
																					    column_reshape(_lowerCamelCase ) - column_reshape(_lowerCamelCase )				,			(column_reshape(_lowerCamelCase ) - column_reshape(_lowerCamelCase )).T				,			)
														else:
																					# If covariance_sum is np.nan (i.e. first loop)
																					A__		   =							device_data * np.dot(
																					    column_reshape(_lowerCamelCase ) - column_reshape(_lowerCamelCase )				,			(column_reshape(_lowerCamelCase ) - column_reshape(_lowerCamelCase )).T				,			)

							return covariance_sum / features.shape[1]






def      UpperCAmelCase    (		UpperCamelCase__				,			UpperCamelCase__ ):






							"""simple docstring"""





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

														return projected_data
							else:
														logging.basicConfig(level=logging.ERROR				,			format='%(message)s'				,			force=_lowerCamelCase )
														logging.error('Dataset empty' )
														raise AssertionError






def      UpperCAmelCase    (		UpperCamelCase__				,			UpperCamelCase__				,			UpperCamelCase__				,			UpperCamelCase__ ):






							"""simple docstring"""





							assert classes > dimensions

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

														return projected_data
							else:
														logging.basicConfig(level=logging.ERROR				,			format='%(message)s'				,			force=_lowerCamelCase )
														logging.error('Dataset empty' )
														raise AssertionError






def      UpperCAmelCase    (		):






							"""simple docstring"""





							A__		   =							np.array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]] )
							A__		   =							np.array([0, 0, 0, 1, 1] )
							A__		   =							2
							A__		   =							2

							# Assert that the function raises an AssertionError if dimensions > classes
							with pytest.raises(_lowerCamelCase ) as error_info:
														A__		   =							linear_discriminant_analysis(
														    _lowerCamelCase				,			_lowerCamelCase				,			_lowerCamelCase				,			_lowerCamelCase )
														if isinstance(_lowerCamelCase				,			np.ndarray ):
																					raise AssertionError(
																					    'Did not raise AssertionError for dimensions > classes' )
														assert error_info.type is AssertionError






def      UpperCAmelCase    (		):






							"""simple docstring"""





							A__		   =							np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]] )
							A__		   =							2
							A__		   =							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(_lowerCamelCase ) as error_info:
														A__		   =							principal_component_analysis(_lowerCamelCase				,			_lowerCamelCase )
														if not np.allclose(_lowerCamelCase				,			_lowerCamelCase ):
																					raise AssertionError
														assert error_info.type is AssertionError


if __name__ == "__main__":
				import doctest

				doctest.testmod()










'''simple docstring'''




def 				lowerCAmelCase_   (	_lowerCamelCase:   float       ,      _lowerCamelCase:   list[float]					):
		if discount_rate < 0:
				raise ValueError("""Discount rate cannot be negative"""					)
		if not cash_flows:
				raise ValueError("""Cash flows list cannot be empty"""					)
		__SCREAMING_SNAKE_CASE       :		List[str]           =		sum(
		    cash_flow / ((1 + discount_rate) ** i) for i, cash_flow in enumerate(_lowerCamelCase					)					)
		return round(_lowerCamelCase       ,      ndigits=2					)


if __name__ == "__main__":
						import doctest

						doctest.testmod()