


"""simple docstring"""






import pickle

import numpy as np
from matplotlib import pyplot as plt


class 			lowerCamelCase_		:





				"""simple docstring"""







				def __init__(						self       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__=0.2       ,		UpperCAmelCase__=0.2     ):
								SCREAMING_SNAKE_CASE__     							=				bp_numa
								SCREAMING_SNAKE_CASE__     							=				bp_numa
								SCREAMING_SNAKE_CASE__     							=				bp_numa
								SCREAMING_SNAKE_CASE__     							=				conva_get[:2]
								SCREAMING_SNAKE_CASE__     							=				conva_get[2]
								SCREAMING_SNAKE_CASE__     							=				size_pa
								SCREAMING_SNAKE_CASE__     							=				rate_w
								SCREAMING_SNAKE_CASE__     							=				rate_t
								SCREAMING_SNAKE_CASE__     							=				[
								    np.mat(-1 * np.random.rand(self.conva[0]       ,		self.conva[0]     ) + 0.5     )
								    for i in range(self.conva[1]     )
								]
								SCREAMING_SNAKE_CASE__     							=				np.mat(-1 * np.random.rand(self.num_bpa       ,		self.num_bpa     ) + 0.5     )
								SCREAMING_SNAKE_CASE__     							=				np.mat(-1 * np.random.rand(self.num_bpa       ,		self.num_bpa     ) + 0.5     )
								SCREAMING_SNAKE_CASE__     							=				-2 * np.random.rand(self.conva[1]     ) + 1
								SCREAMING_SNAKE_CASE__     							=				-2 * np.random.rand(self.num_bpa     ) + 1
								SCREAMING_SNAKE_CASE__     							=				-2 * np.random.rand(self.num_bpa     ) + 1



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__     ):
								# save model dict with pickle
								SCREAMING_SNAKE_CASE__     							=				{
								    "num_bp1": self.num_bpa,
								    "num_bp2": self.num_bpa,
								    "num_bp3": self.num_bpa,
								    "conv1": self.conva,
								    "step_conv1": self.step_conva,
								    "size_pooling1": self.size_poolinga,
								    "rate_weight": self.rate_weight,
								    "rate_thre": self.rate_thre,
								    "w_conv1": self.w_conva,
								    "wkj": self.wkj,
								    "vji": self.vji,
								    "thre_conv1": self.thre_conva,
								    "thre_bp2": self.thre_bpa,
								    "thre_bp3": self.thre_bpa,
								}
								with open(UpperCAmelCase__       ,		"wb"     ) as f:
												pickle.dump(UpperCAmelCase__       ,		UpperCAmelCase__     )

								print(f'''Model saved： {save_path}'''     )



				@classmethod
				def   lowerCAmelCase__		(						cls       ,		UpperCAmelCase__     ):
								# read saved model
								with open(UpperCAmelCase__       ,		"rb"     ) as f:
												SCREAMING_SNAKE_CASE__     							=				pickle.load(UpperCAmelCase__     )  # noqa: S301

								SCREAMING_SNAKE_CASE__     							=				model_dic.get("conv1"     )
								conv_get.append(model_dic.get("step_conv1"     )     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("size_pooling1"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("num_bp1"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("num_bp2"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("num_bp3"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("rate_weight"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("rate_thre"     )
								# create model instance
								SCREAMING_SNAKE_CASE__     							=				CNN(UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__     )
								# modify model parameter
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("w_conv1"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("wkj"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("vji"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("thre_conv1"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("thre_bp2"     )
								SCREAMING_SNAKE_CASE__     							=				model_dic.get("thre_bp3"     )
								return conv_ins



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__     ):
								return 1 / (1 + np.exp(-1 * x     ))



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__     ):
								return round(UpperCAmelCase__       ,		3     )



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__     ):
								# convolution process
								SCREAMING_SNAKE_CASE__     							=				convs[0]
								SCREAMING_SNAKE_CASE__     							=				convs[1]
								SCREAMING_SNAKE_CASE__     							=				np.shape(UpperCAmelCase__     )[0]
								# get the data slice of original image data, data_focus
								SCREAMING_SNAKE_CASE__     							=				[]
								for i_focus in range(0       ,		size_data - size_conv + 1       ,		UpperCAmelCase__     ):
												for j_focus in range(0       ,		size_data - size_conv + 1       ,		UpperCAmelCase__     ):
																SCREAMING_SNAKE_CASE__     							=				data[
																    i_focus : i_focus + size_conv, j_focus : j_focus + size_conv
																]
																data_focus.append(UpperCAmelCase__     )
        # calculate the feature map of every single kernel, and saved as list of matrix
								SCREAMING_SNAKE_CASE__     							=				[]
								SCREAMING_SNAKE_CASE__     							=				int((size_data - size_conv) / conv_step + 1     )
								for i_map in range(UpperCAmelCase__     ):
												SCREAMING_SNAKE_CASE__     							=				[]
												for i_focus in range(len(UpperCAmelCase__     )     ):
																SCREAMING_SNAKE_CASE__     							=				(
																    np.sum(np.multiply(data_focus[i_focus]       ,		w_convs[i_map]     )     )
																    - thre_convs[i_map]
																)
																featuremap.append(self.sig(UpperCAmelCase__     )     )
												SCREAMING_SNAKE_CASE__     							=				np.asmatrix(UpperCAmelCase__     ).reshape(
												    UpperCAmelCase__       ,		UpperCAmelCase__     )
												data_featuremap.append(UpperCAmelCase__     )

								# expanding the data slice to One dimenssion
								SCREAMING_SNAKE_CASE__     							=				[]
								for each_focus in data_focus:
												focusa_list.extend(self.Expand_Mat(UpperCAmelCase__     )     )
								SCREAMING_SNAKE_CASE__     							=				np.asarray(UpperCAmelCase__     )
								return focus_list, data_featuremap



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__="average_pool"     ):
								# pooling process
								SCREAMING_SNAKE_CASE__     							=				len(featuremaps[0]     )
								SCREAMING_SNAKE_CASE__     							=				int(size_map / size_pooling     )
								SCREAMING_SNAKE_CASE__     							=				[]
								for i_map in range(len(UpperCAmelCase__     )     ):
												SCREAMING_SNAKE_CASE__     							=				featuremaps[i_map]
												SCREAMING_SNAKE_CASE__     							=				[]
												for i_focus in range(0       ,		UpperCAmelCase__       ,		UpperCAmelCase__     ):
																for j_focus in range(0       ,		UpperCAmelCase__       ,		UpperCAmelCase__     ):
																				SCREAMING_SNAKE_CASE__     							=				feature_map[
																				    i_focus : i_focus + size_pooling,
																				    j_focus : j_focus + size_pooling,
																				]
																				if pooling_type == "average_pool":
																								# average pooling
																								map_pooled.append(np.average(UpperCAmelCase__     )     )
																				elif pooling_type == "max_pooling":
																								# max pooling
																								map_pooled.append(np.max(UpperCAmelCase__     )     )
												SCREAMING_SNAKE_CASE__     							=				np.asmatrix(UpperCAmelCase__     ).reshape(UpperCAmelCase__       ,		UpperCAmelCase__     )
												featuremap_pooled.append(UpperCAmelCase__     )
								return featuremap_pooled



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__     ):
								# expanding three dimension data to one dimension list
								SCREAMING_SNAKE_CASE__     							=				[]
								for i in range(len(UpperCAmelCase__     )     ):
												SCREAMING_SNAKE_CASE__     							=				np.shape(data[i]     )
												SCREAMING_SNAKE_CASE__     							=				data[i].reshape(1       ,		shapes[0] * shapes[1]     )
												SCREAMING_SNAKE_CASE__     							=				data_listed.getA().tolist()[0]
												data_expanded.extend(UpperCAmelCase__     )
								SCREAMING_SNAKE_CASE__     							=				np.asarray(UpperCAmelCase__     )
								return data_expanded



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__     ):
								# expanding matrix to one dimension list
								SCREAMING_SNAKE_CASE__     							=				np.asarray(UpperCAmelCase__     )
								SCREAMING_SNAKE_CASE__     							=				np.shape(UpperCAmelCase__     )
								SCREAMING_SNAKE_CASE__     							=				data_mat.reshape(1       ,		shapes[0] * shapes[1]     )
								return data_expanded



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__     ):
								SCREAMING_SNAKE_CASE__     							=				[]
								SCREAMING_SNAKE_CASE__     							=				0
								for i_map in range(UpperCAmelCase__     ):
												SCREAMING_SNAKE_CASE__     							=				np.ones((size_map, size_map)     )
												for i in range(0       ,		UpperCAmelCase__       ,		UpperCAmelCase__     ):
																for j in range(0       ,		UpperCAmelCase__       ,		UpperCAmelCase__     ):
																				SCREAMING_SNAKE_CASE__     							=				pd_pool[
																				    i_pool
																				]
																				SCREAMING_SNAKE_CASE__     							=				i_pool + 1
												SCREAMING_SNAKE_CASE__     							=				np.multiply(
												    UpperCAmelCase__       ,		np.multiply(out_map[i_map]       ,		(1 - out_map[i_map])     )     )
												pd_all.append(UpperCAmelCase__     )
								return pd_all



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__       ,		UpperCAmelCase__=bool     ):
								# model traning
								print("----------------------Start Training-------------------------"     )
								print((" - - Shape: Train_Data  ", np.shape(UpperCAmelCase__     ))     )
								print((" - - Shape: Teach_Data  ", np.shape(UpperCAmelCase__     ))     )
								SCREAMING_SNAKE_CASE__     							=				0
								SCREAMING_SNAKE_CASE__     							=				[]
								SCREAMING_SNAKE_CASE__     							=				1_0000
								while rp < n_repeat and mse >= error_accuracy:
												SCREAMING_SNAKE_CASE__     							=				0
												print(f'''-------------Learning Time {rp}--------------'''     )
												for p in range(len(UpperCAmelCase__     )     ):
																# print('------------Learning Image: %d--------------'%p)
																SCREAMING_SNAKE_CASE__     							=				np.asmatrix(datas_train[p]     )
																SCREAMING_SNAKE_CASE__     							=				np.asarray(datas_teach[p]     )
																SCREAMING_SNAKE_CASE__							,      SCREAMING_SNAKE_CASE__     							=				self.convolute(
																    UpperCAmelCase__       ,		self.conva       ,		self.w_conva       ,		self.thre_conva       ,		conv_step=self.step_conva       ,		)
																SCREAMING_SNAKE_CASE__     							=				self.pooling(UpperCAmelCase__       ,		self.size_poolinga     )
																SCREAMING_SNAKE_CASE__     							=				np.shape(UpperCAmelCase__     )
																SCREAMING_SNAKE_CASE__     							=				self._expand(UpperCAmelCase__     )
																SCREAMING_SNAKE_CASE__     							=				data_bp_input

																SCREAMING_SNAKE_CASE__     							=				np.dot(UpperCAmelCase__       ,		self.vji.T     ) - self.thre_bpa
																SCREAMING_SNAKE_CASE__     							=				self.sig(UpperCAmelCase__     )
																SCREAMING_SNAKE_CASE__     							=				np.dot(UpperCAmelCase__       ,		self.wkj.T     ) - self.thre_bpa
																SCREAMING_SNAKE_CASE__     							=				self.sig(UpperCAmelCase__     )

																# --------------Model Leaning ------------------------
																# calculate error and gradient---------------
																SCREAMING_SNAKE_CASE__     							=				np.multiply(
																    (data_teach - bp_outa)       ,		np.multiply(UpperCAmelCase__       ,		(1 - bp_outa)     )     )
																SCREAMING_SNAKE_CASE__     							=				np.multiply(
																    np.dot(UpperCAmelCase__       ,		self.wkj     )       ,		np.multiply(UpperCAmelCase__       ,		(1 - bp_outa)     )     )
																SCREAMING_SNAKE_CASE__     							=				np.dot(UpperCAmelCase__       ,		self.vji     )

																SCREAMING_SNAKE_CASE__     							=				pd_i_all / (self.size_poolinga * self.size_poolinga)
																SCREAMING_SNAKE_CASE__     							=				pd_conva_pooled.T.getA().tolist()
																SCREAMING_SNAKE_CASE__     							=				self._calculate_gradient_from_pool(
																    UpperCAmelCase__       ,		UpperCAmelCase__       ,		shape_featuremapa[0]       ,		shape_featuremapa[1]       ,		self.size_poolinga       ,		)
																# weight and threshold learning process---------
																# convolution layer
																for k_conv in range(self.conva[1]     ):
																				SCREAMING_SNAKE_CASE__     							=				self._expand_mat(pd_conva_all[k_conv]     )
																				SCREAMING_SNAKE_CASE__     							=				self.rate_weight * np.dot(UpperCAmelCase__       ,		UpperCAmelCase__     )

																				SCREAMING_SNAKE_CASE__     							=				self.w_conva[k_conv] + delta_w.reshape(
																				    (self.conva[0], self.conva[0])     )

																				SCREAMING_SNAKE_CASE__     							=				(
																				    self.thre_conva[k_conv]
																				    - np.sum(pd_conva_all[k_conv]     ) * self.rate_thre
																				)
																# all connected layer
																SCREAMING_SNAKE_CASE__     							=				self.wkj + pd_k_all.T * bp_outa * self.rate_weight
																SCREAMING_SNAKE_CASE__     							=				self.vji + pd_j_all.T * bp_outa * self.rate_weight
																SCREAMING_SNAKE_CASE__     							=				self.thre_bpa - pd_k_all * self.rate_thre
																SCREAMING_SNAKE_CASE__     							=				self.thre_bpa - pd_j_all * self.rate_thre
																# calculate the sum error of all single image
																SCREAMING_SNAKE_CASE__     							=				np.sum(abs(data_teach - bp_outa     )     )
																error_count += errors
																# print('   ----Teach      ',data_teach)
																# print('   ----BP_output  ',bp_out3)
												SCREAMING_SNAKE_CASE__     							=				rp + 1
												SCREAMING_SNAKE_CASE__     							=				error_count / patterns
												all_mse.append(UpperCAmelCase__     )

								def draw_error():
												SCREAMING_SNAKE_CASE__     							=				[error_accuracy for i in range(int(n_repeat * 1.2     )     )]
												plt.plot(UpperCAmelCase__       ,		"+-"     )
												plt.plot(UpperCAmelCase__       ,		"r--"     )
												plt.xlabel("Learning Times"     )
												plt.ylabel("All_mse"     )
												plt.grid(UpperCAmelCase__       ,		alpha=0.5     )
												plt.show()

								print("------------------Training Complished---------------------"     )
								print((" - - Training epoch: ", rp, f'''     - - Mse: {mse:.6f}''')     )
								if draw_e:
												draw_error()
								return mse



				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__     ):
								# model predict
								SCREAMING_SNAKE_CASE__     							=				[]
								print("-------------------Start Testing-------------------------"     )
								print((" - - Shape: Test_Data  ", np.shape(UpperCAmelCase__     ))     )
								for p in range(len(UpperCAmelCase__     )     ):
												SCREAMING_SNAKE_CASE__     							=				np.asmatrix(datas_test[p]     )
												SCREAMING_SNAKE_CASE__							,      SCREAMING_SNAKE_CASE__     							=				self.convolute(
												    UpperCAmelCase__       ,		self.conva       ,		self.w_conva       ,		self.thre_conva       ,		conv_step=self.step_conva       ,		)
												SCREAMING_SNAKE_CASE__     							=				self.pooling(UpperCAmelCase__       ,		self.size_poolinga     )
												SCREAMING_SNAKE_CASE__     							=				self._expand(UpperCAmelCase__     )

												SCREAMING_SNAKE_CASE__     							=				data_bp_input
												SCREAMING_SNAKE_CASE__     							=				bp_outa * self.vji.T - self.thre_bpa
												SCREAMING_SNAKE_CASE__     							=				self.sig(UpperCAmelCase__     )
												SCREAMING_SNAKE_CASE__     							=				bp_outa * self.wkj.T - self.thre_bpa
												SCREAMING_SNAKE_CASE__     							=				self.sig(UpperCAmelCase__     )
												produce_out.extend(bp_outa.getA().tolist()     )
								SCREAMING_SNAKE_CASE__     							=				[list(map(self.do_round       ,		UpperCAmelCase__     )     ) for each in produce_out]
								return np.asarray(UpperCAmelCase__     )






				def   lowerCAmelCase__		(						self       ,		UpperCAmelCase__     ):
								# return the data of image after convoluting process so we can check it out
								SCREAMING_SNAKE_CASE__     							=				np.asmatrix(UpperCAmelCase__     )
								SCREAMING_SNAKE_CASE__							,      SCREAMING_SNAKE_CASE__     							=				self.convolute(
								    UpperCAmelCase__       ,		self.conva       ,		self.w_conva       ,		self.thre_conva       ,		conv_step=self.step_conva       ,		)
								SCREAMING_SNAKE_CASE__     							=				self.pooling(UpperCAmelCase__       ,		self.size_poolinga     )

								return data_conveda, data_pooleda


if __name__ == "__main__":
	pass




"""simple docstring"""






from math import factorial


def __lowercase     (      lowerCamelCase_  :      int = 100  ):
				return sum(int(lowerCamelCase_  ) for x in str(factorial(lowerCamelCase_  )  )  )


if __name__ == "__main__":
	print(solution(int(input('Enter the Number: ').strip())))
