




import numpy





class 	lowerCamelCase_							:


 '''simple docstring'''







 def __init__(							self  :		Tuple    ,    _lowerCAmelCase  :		numpy.ndarray    ,    _lowerCAmelCase  :		numpy.ndarray						):
       SCREAMING_SNAKE_CASE_     						=      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.
       SCREAMING_SNAKE_CASE_     						=      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.
       SCREAMING_SNAKE_CASE_     						=      numpy.random.rand(
           4    ,    3						)

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

       # Real output values provided.
       SCREAMING_SNAKE_CASE_     						=      output_array

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



 def 				lowerCAmelCase_  (							self  :		Union[str, Any]						):
       SCREAMING_SNAKE_CASE_     						=      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.
       SCREAMING_SNAKE_CASE_     						=      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.
       SCREAMING_SNAKE_CASE_     						=      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 				lowerCAmelCase_  (							self  :		str						):
       SCREAMING_SNAKE_CASE_     						=      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						)    ,    )
       SCREAMING_SNAKE_CASE_     						=      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						)    ,    )
       SCREAMING_SNAKE_CASE_     						=      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 				lowerCAmelCase_  (							self  :		int    ,    _lowerCAmelCase  :		numpy.ndarray    ,    _lowerCAmelCase  :		int    ,    _lowerCAmelCase  :		bool						):
       for iteration in range(1    ,    iterations + 1						):
             SCREAMING_SNAKE_CASE_     						=      self.feedforward()
             self.back_propagation()
             if give_loss:
                   SCREAMING_SNAKE_CASE_     						=      numpy.mean(numpy.square(output - self.feedforward()						)						)
                   print(F"Iteration {iteration} Loss: {loss}"						)




 def 				lowerCAmelCase_  (							self  :		Any    ,    _lowerCAmelCase  :		numpy.ndarray						):
       SCREAMING_SNAKE_CASE_     						=      input_arr

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

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

       SCREAMING_SNAKE_CASE_     						=      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  UpperCAmelCase_							(				__UpperCAmelCase						:     numpy.ndarray							) ->			numpy.ndarray:
      return 1 / (1 + numpy.exp(-value							))

def  UpperCAmelCase_							(				__UpperCAmelCase						:     numpy.ndarray							) ->			numpy.ndarray:
      return (value) * (1 - (value))

def  UpperCAmelCase_							(				) ->			int:
      SCREAMING_SNAKE_CASE_     						=      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.
      SCREAMING_SNAKE_CASE_     						=      numpy.array(([0], [1], [1], [0], [1], [0], [0], [1])      ,      dtype=numpy.floataa							)

      # Calling neural network class.
      SCREAMING_SNAKE_CASE_     						=      TwoHiddenLayerNeuralNetwork(
          input_array=__UpperCAmelCase      ,      output_array=__UpperCAmelCase							)

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

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


if __name__ == "__main__":
   example()





def  UpperCAmelCase_							(				__UpperCAmelCase						:     Optional[Any]      ,      __UpperCAmelCase						:     Union[str, Any]							) ->			List[str]:
      SCREAMING_SNAKE_CASE_     						=      0
      while b > 0:
            if b & 1:
                  res += a

            a += a
            b >>= 1

      return res

def  UpperCAmelCase_							(				__UpperCAmelCase						:     str      ,      __UpperCAmelCase						:     int      ,      __UpperCAmelCase						:     Tuple							) ->			int:
      SCREAMING_SNAKE_CASE_     						=      0
      while b > 0:
            if b & 1:
                  SCREAMING_SNAKE_CASE_     						=      ((res % c) + (a % c)) % c

            a += a
            b >>= 1

      return res