






import numpy
class  _UpperCAmelCase   :

				"""simple docstring"""




				def __init__(	self		:       Tuple,    lowerCamelCase		:       numpy.ndarray,    lowerCamelCase		:       numpy.ndarray    ):

								'''simple docstring'''
								lowercase__  					=     input_array

								# Random initial weights are assigned where first argument is the
								# number of nodes in previous layer and second argument is the
								# number of nodes in the next layer.

								# Random initial weights are assigned.
								# self.input_array.shape[1] is used to represent number of nodes in input layer.
								# First hidden layer consists of 4 nodes.
								lowercase__  					=     numpy.random.rand(
								    self.input_array.shape[1],    4    )

								# Random initial values for the first hidden layer.
								# First hidden layer has 4 nodes.
								# Second hidden layer has 3 nodes.
								lowercase__  					=     numpy.random.rand(
								    4,    3    )

								# Random initial values for the second hidden layer.
								# Second hidden layer has 3 nodes.
								# Output layer has 1 node.
								lowercase__  					=     numpy.random.rand(3,    1    )

								# Real output values provided.
								lowercase__  					=     output_array

								# Predicted output values by the neural network.
								# Predicted_output array initially consists of zeroes.
								lowercase__  					=     numpy.zeros(output_array.shape    )




				def 							lowercase__  (	self		:       List[str]    ):

								'''simple docstring'''
								lowercase__  					=     sigmoid(
								    numpy.dot(self.input_array,    self.input_layer_and_first_hidden_layer_weights    )    )

								# layer_between_first_hidden_layer_and_second_hidden_layer is the layer
								# connecting the first hidden set of nodes with the second hidden set of nodes.
								lowercase__  					=     sigmoid(
								    numpy.dot(
								        self.layer_between_input_and_first_hidden_layer,    self.first_hidden_layer_and_second_hidden_layer_weights,    )    )

								# layer_between_second_hidden_layer_and_output is the layer connecting
								# second hidden layer with the output node.
								lowercase__  					=     sigmoid(
								    numpy.dot(
								        self.layer_between_first_hidden_layer_and_second_hidden_layer,    self.second_hidden_layer_and_output_layer_weights,    )    )

								return self.layer_between_second_hidden_layer_and_output




				def 							lowercase__  (	self		:       Dict    ):

								'''simple docstring'''
								lowercase__  					=     numpy.dot(
								    self.layer_between_first_hidden_layer_and_second_hidden_layer.T,    2
								    * (self.output_array - self.predicted_output)
								    * sigmoid_derivative(self.predicted_output    ),    )
								lowercase__  					=     numpy.dot(
								    self.layer_between_input_and_first_hidden_layer.T,    numpy.dot(
								        2
								        * (self.output_array - self.predicted_output)
								        * sigmoid_derivative(self.predicted_output    ),    self.second_hidden_layer_and_output_layer_weights.T,    )
								    * sigmoid_derivative(
								        self.layer_between_first_hidden_layer_and_second_hidden_layer    ),    )
								lowercase__  					=     numpy.dot(
								    self.input_array.T,    numpy.dot(
								        numpy.dot(
								            2
								            * (self.output_array - self.predicted_output)
								            * sigmoid_derivative(self.predicted_output    ),    self.second_hidden_layer_and_output_layer_weights.T,    )
								        * sigmoid_derivative(
								            self.layer_between_first_hidden_layer_and_second_hidden_layer    ),    self.first_hidden_layer_and_second_hidden_layer_weights.T,    )
								    * sigmoid_derivative(self.layer_between_input_and_first_hidden_layer    ),    )

								self.input_layer_and_first_hidden_layer_weights += (
								    updated_input_layer_and_first_hidden_layer_weights
								)
								self.first_hidden_layer_and_second_hidden_layer_weights += (
								    updated_first_hidden_layer_and_second_hidden_layer_weights
								)
								self.second_hidden_layer_and_output_layer_weights += (
								    updated_second_hidden_layer_and_output_layer_weights
								)




				def 							lowercase__  (	self		:       Optional[Any],    lowerCamelCase		:       numpy.ndarray,    lowerCamelCase		:       int,    lowerCamelCase		:       bool    ):

								'''simple docstring'''
								for iteration in range(1,    iterations + 1    ):
												lowercase__  					=     self.feedforward()
												self.back_propagation()
												if give_loss:
																lowercase__  					=     numpy.mean(numpy.square(output - self.feedforward()    )    )
																print(F"""Iteration {iteration} Loss: {loss}"""    )




				def 							lowercase__  (	self		:       Optional[int],    lowerCamelCase		:       numpy.ndarray    ):

								'''simple docstring'''
								lowercase__  					=     input_arr

								lowercase__  					=     sigmoid(
								    numpy.dot(self.array,    self.input_layer_and_first_hidden_layer_weights    )    )

								lowercase__  					=     sigmoid(
								    numpy.dot(
								        self.layer_between_input_and_first_hidden_layer,    self.first_hidden_layer_and_second_hidden_layer_weights,    )    )

								lowercase__  					=     sigmoid(
								    numpy.dot(
								        self.layer_between_first_hidden_layer_and_second_hidden_layer,    self.second_hidden_layer_and_output_layer_weights,    )    )

								return int(self.layer_between_second_hidden_layer_and_output > 0.6    )






def     a     (		lowerCamelCase_							):






				'''simple docstring'''
				return 1 / (1 + numpy.exp(-value							))






def     a     (		lowerCamelCase_							):






				'''simple docstring'''
				return (value) * (1 - (value))






def     a     (		):






				'''simple docstring'''
				lowercase__  					=     numpy.array(
				    (
				        [0, 0, 0],
				        [0, 0, 1],
				        [0, 1, 0],
				        [0, 1, 1],
				        [1, 0, 0],
				        [1, 0, 1],
				        [1, 1, 0],
				        [1, 1, 1],
				    )						,  dtype=numpy.floataa						,  )

				# True output values for the given input values.
				lowercase__  					=     numpy.array(([0], [1], [1], [0], [1], [0], [0], [1])						,  dtype=numpy.floataa							)

				# Calling neural network class.
				lowercase__  					=     TwoHiddenLayerNeuralNetwork(
				    input_array=lowerCamelCase_						,  output_array=lowerCamelCase_							)

				# Calling training function.
				# Set give_loss to True if you want to see loss in every iteration.
				neural_network.train(output=lowerCamelCase_						,  iterations=10						,  give_loss=lowerCamelCase_							)

				return neural_network.predict(numpy.array(([1, 1, 1])						,  dtype=numpy.floataa							)							)


if __name__ == "__main__":
							example()












def     a     (		lowerCamelCase_							):






				'''simple docstring'''
				lowercase__  					=     []
				for data in source_data:
								for i, el in enumerate(lowerCamelCase_							):
												if len(lowerCamelCase_							) < i + 1:
																data_lists.append([]							)
												data_lists[i].append(float(lowerCamelCase_							)							)
				return data_lists






def     a     (		lowerCamelCase_						,  lowerCamelCase_							):






				'''simple docstring'''
				lowercase__  					=     []
				for dlist, weight in zip(lowerCamelCase_						,  lowerCamelCase_							):
								lowercase__  					=     min(lowerCamelCase_							)
								lowercase__  					=     max(lowerCamelCase_							)

								lowercase__  					=     []
								# for weight 0 score is 1 - actual score
								if weight == 0:
												for item in dlist:
																try:
																				score.append(1 - ((item - mind) / (maxd - mind))							)
																except ZeroDivisionError:
																				score.append(1							)

								elif weight == 1:
												for item in dlist:
																try:
																				score.append((item - mind) / (maxd - mind)							)
																except ZeroDivisionError:
																				score.append(0							)

        # weight not 0 or 1
								else:
												lowercase__  					=     F"""Invalid weight of {weight:f} provided"""
												raise ValueError(lowerCamelCase_							)

								score_lists.append(lowerCamelCase_							)

				return score_lists






def     a     (		lowerCamelCase_							):






				'''simple docstring'''
				lowercase__  					=     [0 for i in range(len(score_lists[0]							)							)]

				for slist in score_lists:
								for j, ele in enumerate(lowerCamelCase_							):
												lowercase__  					=     final_scores[j] + ele

				return final_scores






def     a     (		lowerCamelCase_						,  lowerCamelCase_							):






				'''simple docstring'''
				lowercase__  					=     get_data(lowerCamelCase_							)
				lowercase__  					=     calculate_each_score(lowerCamelCase_						,  lowerCamelCase_							)
				lowercase__  					=     generate_final_scores(lowerCamelCase_							)

				# append scores to source data
				for i, ele in enumerate(lowerCamelCase_							):
								source_data[i].append(lowerCamelCase_							)

				return source_data




