



import pickle

import numpy as np
from matplotlib import pyplot as plt



class 	lowerCamelCase__      :




		'''simple docstring'''



		def __init__(self		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase=0.2		,__lowerCamelCase=0.2			)					->      Any:

						"""simple docstring"""






						lowerCAmelCase__					:    str												=					bp_numa
						lowerCAmelCase__					:    str												=					bp_numa
						lowerCAmelCase__					:    Tuple												=					bp_numa
						lowerCAmelCase__					:    List[Any]												=					conva_get[:2]
						lowerCAmelCase__					:    Union[str, Any]												=					conva_get[2]
						lowerCAmelCase__					:    Optional[Any]												=					size_pa
						lowerCAmelCase__					:    Optional[Any]												=					rate_w
						lowerCAmelCase__					:    Any												=					rate_t
						lowerCAmelCase__					:    List[str]												=					[
						    np.mat(-1 * np.random.rand(self.conva[0]		,self.conva[0]			) + 0.5			)
						    for i in range(self.conva[1]			)
						]
						lowerCAmelCase__					:    List[Any]												=					np.mat(-1 * np.random.rand(self.num_bpa		,self.num_bpa			) + 0.5			)
						lowerCAmelCase__					:    List[str]												=					np.mat(-1 * np.random.rand(self.num_bpa		,self.num_bpa			) + 0.5			)
						lowerCAmelCase__					:    Any												=					-2 * np.random.rand(self.conva[1]			) + 1
						lowerCAmelCase__					:    Dict												=					-2 * np.random.rand(self.num_bpa			) + 1
						lowerCAmelCase__					:    str												=					-2 * np.random.rand(self.num_bpa			) + 1



		def 		lowerCAmelCase__				(self		,__lowerCamelCase			)					->      Tuple:

						"""simple docstring"""






						lowerCAmelCase__					:    Dict												=					{
						    '''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(__lowerCamelCase		,'''wb'''			) as f:
										pickle.dump(__lowerCamelCase		,__lowerCamelCase			)

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



		@classmethod
		def 		lowerCAmelCase__				(cls		,__lowerCamelCase			)					->      Dict:

						"""simple docstring"""






						with open(__lowerCamelCase		,'''rb'''			) as f:
										lowerCAmelCase__					:    int												=					pickle.load(__lowerCamelCase			)  # noqa: S301

						lowerCAmelCase__					:    List[Any]												=					model_dic.get('''conv1'''			)
						conv_get.append(model_dic.get('''step_conv1'''			)			)
						lowerCAmelCase__					:    str												=					model_dic.get('''size_pooling1'''			)
						lowerCAmelCase__					:    str												=					model_dic.get('''num_bp1'''			)
						lowerCAmelCase__					:    Tuple												=					model_dic.get('''num_bp2'''			)
						lowerCAmelCase__					:    Tuple												=					model_dic.get('''num_bp3'''			)
						lowerCAmelCase__					:    Any												=					model_dic.get('''rate_weight'''			)
						lowerCAmelCase__					:    str												=					model_dic.get('''rate_thre'''			)
						# create model instance
						lowerCAmelCase__					:    Tuple												=					CNN(__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase			)
						# modify model parameter
						lowerCAmelCase__					:    str												=					model_dic.get('''w_conv1'''			)
						lowerCAmelCase__					:    Union[str, Any]												=					model_dic.get('''wkj'''			)
						lowerCAmelCase__					:    List[str]												=					model_dic.get('''vji'''			)
						lowerCAmelCase__					:    Union[str, Any]												=					model_dic.get('''thre_conv1'''			)
						lowerCAmelCase__					:    Any												=					model_dic.get('''thre_bp2'''			)
						lowerCAmelCase__					:    List[str]												=					model_dic.get('''thre_bp3'''			)
						return conv_ins



		def 		lowerCAmelCase__				(self		,__lowerCamelCase			)					->      Dict:

						"""simple docstring"""






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



		def 		lowerCAmelCase__				(self		,__lowerCamelCase			)					->      List[Any]:

						"""simple docstring"""






						return round(__lowerCamelCase		,3			)



		def 		lowerCAmelCase__				(self		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase			)					->      Any:

						"""simple docstring"""






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

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



		def 		lowerCAmelCase__				(self		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase="average_pool"			)					->      Union[str, Any]:

						"""simple docstring"""






						lowerCAmelCase__					:    Tuple												=					len(featuremaps[0]			)
						lowerCAmelCase__					:    Any												=					int(size_map / size_pooling			)
						lowerCAmelCase__					:    Optional[int]												=					[]
						for i_map in range(len(__lowerCamelCase			)			):
										lowerCAmelCase__					:    Tuple												=					featuremaps[i_map]
										lowerCAmelCase__					:    int												=					[]
										for i_focus in range(0		,__lowerCamelCase		,__lowerCamelCase			):
														for j_focus in range(0		,__lowerCamelCase		,__lowerCamelCase			):
																		lowerCAmelCase__					:    int												=					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(__lowerCamelCase			)			)
																		elif pooling_type == "max_pooling":
																						# max pooling
																						map_pooled.append(np.max(__lowerCamelCase			)			)
										lowerCAmelCase__					:    Tuple												=					np.asmatrix(__lowerCamelCase			).reshape(__lowerCamelCase		,__lowerCamelCase			)
										featuremap_pooled.append(__lowerCamelCase			)
						return featuremap_pooled



		def 		lowerCAmelCase__				(self		,__lowerCamelCase			)					->      str:

						"""simple docstring"""






						lowerCAmelCase__					:    Optional[int]												=					[]
						for i in range(len(__lowerCamelCase			)			):
										lowerCAmelCase__					:    Any												=					np.shape(data[i]			)
										lowerCAmelCase__					:    Tuple												=					data[i].reshape(1		,shapes[0] * shapes[1]			)
										lowerCAmelCase__					:    Optional[Any]												=					data_listed.getA().tolist()[0]
										data_expanded.extend(__lowerCamelCase			)
						lowerCAmelCase__					:    List[str]												=					np.asarray(__lowerCamelCase			)
						return data_expanded



		def 		lowerCAmelCase__				(self		,__lowerCamelCase			)					->      List[Any]:

						"""simple docstring"""






						lowerCAmelCase__					:    str												=					np.asarray(__lowerCamelCase			)
						lowerCAmelCase__					:    Optional[Any]												=					np.shape(__lowerCamelCase			)
						lowerCAmelCase__					:    Any												=					data_mat.reshape(1		,shapes[0] * shapes[1]			)
						return data_expanded



		def 		lowerCAmelCase__				(self		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase			)					->      Optional[Any]:

						"""simple docstring"""






						lowerCAmelCase__					:    List[str]												=					[]
						lowerCAmelCase__					:    Optional[int]												=					0
						for i_map in range(__lowerCamelCase			):
										lowerCAmelCase__					:    Any												=					np.ones((size_map, size_map)			)
										for i in range(0		,__lowerCamelCase		,__lowerCamelCase			):
														for j in range(0		,__lowerCamelCase		,__lowerCamelCase			):
																		lowerCAmelCase__					:    int												=					pd_pool[
																		    i_pool
																		]
																		lowerCAmelCase__					:    Optional[Any]												=					i_pool + 1
										lowerCAmelCase__					:    Tuple												=					np.multiply(
										    __lowerCamelCase		,np.multiply(out_map[i_map]		,(1 - out_map[i_map])			)			)
										pd_all.append(__lowerCamelCase			)
						return pd_all



		def 		lowerCAmelCase__				(self		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase		,__lowerCamelCase=bool			)					->      int:

						"""simple docstring"""






						print('''----------------------Start Training-------------------------'''			)
						print((''' - - Shape: Train_Data  ''', np.shape(__lowerCamelCase			))			)
						print((''' - - Shape: Teach_Data  ''', np.shape(__lowerCamelCase			))			)
						lowerCAmelCase__					:    str												=					0
						lowerCAmelCase__					:    int												=					[]
						lowerCAmelCase__					:    str												=					1_00_00
						while rp < n_repeat and mse >= error_accuracy:
										lowerCAmelCase__					:    Any												=					0
										print(f"""-------------Learning Time {rp}--------------"""			)
										for p in range(len(__lowerCamelCase			)			):
														# print('------------Learning Image: %d--------------'%p)
														lowerCAmelCase__					:    Any												=					np.asmatrix(datas_train[p]			)
														lowerCAmelCase__					:    Dict												=					np.asarray(datas_teach[p]			)
														lowerCAmelCase__					:    List[Any]												=					self.convolute(
														    __lowerCamelCase		,self.conva		,self.w_conva		,self.thre_conva		,conv_step=self.step_conva		,)
														lowerCAmelCase__					:    Union[str, Any]												=					self.pooling(__lowerCamelCase		,self.size_poolinga			)
														lowerCAmelCase__					:    Tuple												=					np.shape(__lowerCamelCase			)
														lowerCAmelCase__					:    Tuple												=					self._expand(__lowerCamelCase			)
														lowerCAmelCase__					:    Optional[Any]												=					data_bp_input

														lowerCAmelCase__					:    Union[str, Any]												=					np.dot(__lowerCamelCase		,self.vji.T			) - self.thre_bpa
														lowerCAmelCase__					:    Optional[int]												=					self.sig(__lowerCamelCase			)
														lowerCAmelCase__					:    Dict												=					np.dot(__lowerCamelCase		,self.wkj.T			) - self.thre_bpa
														lowerCAmelCase__					:    List[Any]												=					self.sig(__lowerCamelCase			)

														# --------------Model Leaning ------------------------
														# calculate error and gradient---------------
														lowerCAmelCase__					:    Union[str, Any]												=					np.multiply(
														    (data_teach - bp_outa)		,np.multiply(__lowerCamelCase		,(1 - bp_outa)			)			)
														lowerCAmelCase__					:    List[Any]												=					np.multiply(
														    np.dot(__lowerCamelCase		,self.wkj			)		,np.multiply(__lowerCamelCase		,(1 - bp_outa)			)			)
														lowerCAmelCase__					:    Dict												=					np.dot(__lowerCamelCase		,self.vji			)

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

																		lowerCAmelCase__					:    Optional[int]												=					self.w_conva[k_conv] + delta_w.reshape(
																		    (self.conva[0], self.conva[0])			)

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

						def draw_error():
										lowerCAmelCase__					:    str												=					[error_accuracy for i in range(int(n_repeat * 1.2			)			)]
										plt.plot(__lowerCamelCase		,'''+-'''			)
										plt.plot(__lowerCamelCase		,'''r--'''			)
										plt.xlabel('''Learning Times'''			)
										plt.ylabel('''All_mse'''			)
										plt.grid(__lowerCamelCase		,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		,__lowerCamelCase			)					->      Tuple:

						"""simple docstring"""






						lowerCAmelCase__					:    Union[str, Any]												=					[]
						print('''-------------------Start Testing-------------------------'''			)
						print((''' - - Shape: Test_Data  ''', np.shape(__lowerCamelCase			))			)
						for p in range(len(__lowerCamelCase			)			):
										lowerCAmelCase__					:    Optional[Any]												=					np.asmatrix(datas_test[p]			)
										lowerCAmelCase__					:    Union[str, Any]												=					self.convolute(
										    __lowerCamelCase		,self.conva		,self.w_conva		,self.thre_conva		,conv_step=self.step_conva		,)
										lowerCAmelCase__					:    str												=					self.pooling(__lowerCamelCase		,self.size_poolinga			)
										lowerCAmelCase__					:    str												=					self._expand(__lowerCamelCase			)

										lowerCAmelCase__					:    Optional[int]												=					data_bp_input
										lowerCAmelCase__					:    Any												=					bp_outa * self.vji.T - self.thre_bpa
										lowerCAmelCase__					:    Tuple												=					self.sig(__lowerCamelCase			)
										lowerCAmelCase__					:    str												=					bp_outa * self.wkj.T - self.thre_bpa
										lowerCAmelCase__					:    Any												=					self.sig(__lowerCamelCase			)
										produce_out.extend(bp_outa.getA().tolist()			)
						lowerCAmelCase__					:    List[Any]												=					[list(map(self.do_round		,__lowerCamelCase			)			) for each in produce_out]
						return np.asarray(__lowerCamelCase			)



		def 		lowerCAmelCase__				(self		,__lowerCamelCase			)					->      List[Any]:

						"""simple docstring"""






						lowerCAmelCase__					:    Tuple												=					np.asmatrix(__lowerCamelCase			)
						lowerCAmelCase__					:    int												=					self.convolute(
						    __lowerCamelCase		,self.conva		,self.w_conva		,self.thre_conva		,conv_step=self.step_conva		,)
						lowerCAmelCase__					:    str												=					self.pooling(__lowerCamelCase		,self.size_poolinga			)

						return data_conveda, data_pooleda


if __name__ == "__main__":
							pass






def      lowerCAmelCase__		(   lowerCamelCase_		:		int = 1000):





				'''simple docstring'''

				lowerCAmelCase__						,		lowerCAmelCase__					:    int												=					1, 1
				lowerCAmelCase__					:    Any												=					2
				while True:
								lowerCAmelCase__					:    Optional[Any]												=					0
								lowerCAmelCase__					:    Any												=					fa + fa
								lowerCAmelCase__						,		lowerCAmelCase__					:    Optional[Any]												=					fa, f
								index += 1
								for _ in str(lowerCamelCase_):
												i += 1
								if i == n:
												break
				return index


if __name__ == "__main__":
							print(solution(int(str(input()).strip())))

