import numpy as np
from matplotlib import pyplot as plt






def    UpperCAmelCase__(						lowerCamelCase_  ):



			"""simple docstring"""





			return 1 / (1 + np.exp(-1 * x  ))

class 	_SCREAMING_SNAKE_CASE							:






		"""simple docstring"""







		def __init__(			self    :				List[Any]  ,					__SCREAMING_SNAKE_CASE    :				Union[str, Any]  ,					__SCREAMING_SNAKE_CASE    :				int=None  ,					__SCREAMING_SNAKE_CASE    :				Tuple=None  ,					__SCREAMING_SNAKE_CASE    :				Dict=False   ):






					"""simple docstring"""
					_snake_case              =      units
					_snake_case              =      None
					_snake_case              =      None
					_snake_case              =      activation
					if learning_rate is None:
								_snake_case              =      0.3
					_snake_case              =      learning_rate
					_snake_case              =      is_input_layer



		def 				_a				(			self    :				str  ,					__SCREAMING_SNAKE_CASE    :				List[str]   ):






					"""simple docstring"""
					_snake_case              =      np.asmatrix(np.random.normal(0  ,					0.5  ,					(self.units, back_units)   )   )
					_snake_case              =      np.asmatrix(np.random.normal(0  ,					0.5  ,					self.units   )   ).T
					if self.activation is None:
								_snake_case              =      sigmoid



		def 				_a				(			self    :				Optional[Any]   ):






					"""simple docstring"""
					# activation function may be sigmoid or linear
					if self.activation == sigmoid:
								_snake_case              =      np.dot(self.output  ,					(1 - self.output).T   )
								_snake_case              =      np.diag(np.diag(__SCREAMING_SNAKE_CASE   )   )
					else:
								_snake_case              =      1
					return gradient_activation



		def 				_a				(			self    :				Any  ,					__SCREAMING_SNAKE_CASE    :				int   ):






					"""simple docstring"""
					_snake_case              =      xdata
					if self.is_input_layer:
								# input layer
								_snake_case              =      xdata
								_snake_case              =      xdata
								return xdata
					else:
								_snake_case              =      np.dot(self.weight  ,					self.xdata   ) - self.bias
								_snake_case              =      self.activation(self.wx_plus_b   )
								return self.output







		def 				_a				(			self    :				Any  ,					__SCREAMING_SNAKE_CASE    :				Optional[Any]   ):






					"""simple docstring"""
					_snake_case              =      self.cal_gradient()  # i * i 维
					_snake_case              =      np.asmatrix(np.dot(gradient.T  ,					__SCREAMING_SNAKE_CASE   )   )

					_snake_case              =      np.asmatrix(self.xdata   )
					_snake_case              =      -1
					_snake_case              =      self.weight

					_snake_case              =      np.dot(gradient.T  ,					self._gradient_weight.T   )
					_snake_case              =      gradient * self._gradient_bias
					_snake_case              =      np.dot(__SCREAMING_SNAKE_CASE  ,					self._gradient_x   ).T
					# upgrade: the Negative gradient direction
					_snake_case              =      self.weight - self.learn_rate * self.gradient_weight
					_snake_case              =      self.bias - self.learn_rate * self.gradient_bias.T
					# updates the weights and bias according to learning rate (0.3 if undefined)
					return self.gradient

class 	_SCREAMING_SNAKE_CASE							:






		"""simple docstring"""







		def __init__(			self    :				Union[str, Any]   ):






					"""simple docstring"""
					_snake_case              =      []
					_snake_case              =      []
					_snake_case              =      plt.figure()
					_snake_case              =      self.fig_loss.add_subplot(1  ,					1  ,					1   )



		def 				_a				(			self    :				Dict  ,					__SCREAMING_SNAKE_CASE    :				Dict   ):






					"""simple docstring"""
					self.layers.append(__SCREAMING_SNAKE_CASE   )



		def 				_a				(			self    :				List[Any]   ):






					"""simple docstring"""
					for i, layer in enumerate(self.layers[:]   ):
								if i < 1:
											_snake_case              =      True
								else:
											layer.initializer(self.layers[i - 1].units   )



		def 				_a				(			self    :				int   ):






					"""simple docstring"""
					for i, layer in enumerate(self.layers[:]   ):
								print(F'------- layer {i} -------'   )
								print("weight.shape "  ,					np.shape(layer.weight   )   )
								print("bias.shape "  ,					np.shape(layer.bias   )   )



		def 				_a				(			self    :				Union[str, Any]  ,					__SCREAMING_SNAKE_CASE    :				str  ,					__SCREAMING_SNAKE_CASE    :				Optional[int]  ,					__SCREAMING_SNAKE_CASE    :				Dict  ,					__SCREAMING_SNAKE_CASE    :				Optional[int]   ):






					"""simple docstring"""
					_snake_case              =      train_round
					_snake_case              =      accuracy

					self.ax_loss.hlines(self.accuracy  ,					0  ,					self.train_round * 1.1   )

					_snake_case              =      np.shape(__SCREAMING_SNAKE_CASE   )
					for _ in range(__SCREAMING_SNAKE_CASE   ):
								_snake_case              =      0
								for row in range(x_shape[0]   ):
											_snake_case              =      np.asmatrix(xdata[row, :]   ).T
											_snake_case              =      np.asmatrix(ydata[row, :]   ).T

											# forward propagation
											for layer in self.layers:
														_snake_case              =      layer.forward_propagation(_xdata   )

											_snake_case       , _snake_case              =      self.cal_loss(_ydata  ,					_xdata   )
											_snake_case              =      all_loss + loss

											# back propagation: the input_layer does not upgrade
											for layer in self.layers[:0:-1]:
														_snake_case              =      layer.back_propagation(__SCREAMING_SNAKE_CASE   )

								_snake_case              =      all_loss / x_shape[0]
								self.train_mse.append(__SCREAMING_SNAKE_CASE   )

								self.plot_loss()

								if mse < self.accuracy:
											print("----达到精度----"   )
											return mse
					return None



		def 				_a				(			self    :				int  ,					__SCREAMING_SNAKE_CASE    :				List[Any]  ,					__SCREAMING_SNAKE_CASE    :				str   ):






					"""simple docstring"""
					_snake_case              =      np.sum(np.power((ydata - ydata_)  ,					2   )   )
					_snake_case              =      2 * (ydata_ - ydata)
					# vector (shape is the same as _ydata.shape)
					return self.loss, self.loss_gradient







		def 				_a				(			self    :				Dict   ):






					"""simple docstring"""
					if self.ax_loss.lines:
								self.ax_loss.lines.remove(self.ax_loss.lines[0]   )
					self.ax_loss.plot(self.train_mse  ,					"r-"   )
					plt.ion()
					plt.xlabel("step"   )
					plt.ylabel("loss"   )
					plt.show()
					plt.pause(0.1   )






def    UpperCAmelCase__(						):



			"""simple docstring"""





			_snake_case              =      np.random.randn(10							,	10  )
			_snake_case              =      np.asarray(
			    [
			        [0.8, 0.4],
			        [0.4, 0.3],
			        [0.3_4, 0.4_5],
			        [0.6_7, 0.3_2],
			        [0.8_8, 0.6_7],
			        [0.7_8, 0.7_7],
			        [0.5_5, 0.6_6],
			        [0.5_5, 0.4_3],
			        [0.5_4, 0.1],
			        [0.1, 0.5],
			    ]  )
			_snake_case              =      BPNN()
			for i in (10, 20, 30, 2):
						model.add_layer(DenseLayer(lowerCamelCase_  )  )
			model.build()
			model.summary()
			model.train(xdata=lowerCamelCase_							,	ydata=lowerCamelCase_							,	train_round=100							,	accuracy=0.0_1  )


if __name__ == "__main__":
			example()


from math import gcd






def    UpperCAmelCase__(						lowerCamelCase_ = 12000  ):



			"""simple docstring"""





			_snake_case              =      0
			for d in range(max_d + 1  ):
						for n in range(d // 3 + 1							,	(d + 1) // 2  ):
									if gcd(lowerCamelCase_							,	lowerCamelCase_  ) == 1:
												fractions_number += 1
			return fractions_number


if __name__ == "__main__":
			print(F"{solution() = }")

