HS.py 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718
  1. from __future__ import division#让/恢复为除法
  2. import pandas
  3. import tkinter,tkinter.messagebox
  4. from tkinter.filedialog import asksaveasfile
  5. import tkinter.messagebox
  6. import sympy
  7. def Bool(n,p=False):
  8. f = ['0','n','no','NO','NOT','No','Not','不']
  9. t = ['y', 'yes', 'Yes','YES', '不']
  10. if p:
  11. t.append('')
  12. else:
  13. f.append('')
  14. try:
  15. _n = str(n)
  16. if _n in f:
  17. return False
  18. elif _n in t:
  19. return True
  20. except:
  21. pass
  22. return bool(n)
  23. class HS_CSV:
  24. def __init__(self,HS,name,view):
  25. if len(HS[0]) != len(HS[1]):raise Exception#个数不相等报错
  26. print(HS)
  27. #筛查可以数字化的结果
  28. _x = []
  29. _y = []
  30. for i in range(len(HS[0])):#检查
  31. try:
  32. a_x = float(HS[0][i])
  33. a_y = float(HS[1][i])
  34. _x.append(a_x)
  35. _y.append(a_y)
  36. except:
  37. pass
  38. print(_x)
  39. print(_y)
  40. Iter_X = _x
  41. Iter_X = sorted(list(set(Iter_X)))#排序并且去除重复
  42. #筛查重复
  43. x = []
  44. y = []
  45. for n_x in Iter_X:
  46. try:
  47. y.append(_y[_x.index(n_x)])
  48. x.append(n_x)
  49. except:
  50. pass
  51. print(x)
  52. print(y)
  53. #函数基本信息
  54. self.Func_Name = name#这个是函数名字
  55. self.View = view#绘制样式
  56. #函数基本数据,相当于Lambda的Cul
  57. self.__x = x
  58. self.__y = y
  59. self.__ya = y
  60. self.__xy = []
  61. self.__fx = []
  62. self.__fy = []
  63. for i in range(len(self.__x)):
  64. self.__xy.append(f'x:{self.__x[i]},y:{self.__y[i]}')
  65. self.__xyCSV = pandas.DataFrame((self.__x,self.__y),index=('x','y'))
  66. #函数记忆数据
  67. self.Memore_x = []
  68. self.Memore_y = []
  69. self.__MemoryAnswer = []
  70. self.YC = False
  71. self.Best_R = None
  72. self.HaveDone = False
  73. self.max_y = None
  74. self.max_x = []
  75. self.min_y = None
  76. self.min_x = []
  77. def __call__(self,x):
  78. return self.__y[self.__x.index(x)]
  79. def __str__(self):
  80. return f'{self.Func_Name}'
  81. def __Best_value(self): # 计算最值和极值点
  82. if not self.HaveDone: self.Cul() # 检查Cul的计算
  83. y = self.__y + self.Memore_y
  84. x = self.__x + self.Memore_x
  85. max_y = max(y)
  86. min_y = min(y)
  87. max_x = Find(x.copy(),y.copy(),max_y)
  88. self.max_y = max_y
  89. self.max_x = max_x
  90. min_x = Find(x.copy(),y.copy(),min_y)
  91. self.min_y = min_y
  92. self.min_x = min_x
  93. return self.max_x, self.max_y, self.min_x, self.min_y
  94. def Cul(self):
  95. if self.HaveDone:return self.__x,self.__y,self.Func_Name,self.View
  96. self.__fx = [[]]
  97. self.__fy = [[]]
  98. o_y = None
  99. p = None#单调性 0-增,1-减
  100. _p = 1
  101. try:
  102. for a_x in self.__x:
  103. c = 0
  104. p2 = 1
  105. try:
  106. y = self(a_x)
  107. if o_y != None and o_y > y:
  108. _p = 1
  109. elif o_y != None and o_y < y:
  110. _p = 0
  111. elif o_y != None and o_y == y:
  112. try:
  113. z_x = round(a_x - 0.5 * self.kd)
  114. z_y = self(z_x)
  115. if z_y == o_y == y: # 真实平衡
  116. p2 = 2
  117. elif abs(z_y - o_y) >= 10 * self.kd or abs(z_y - y) >= 10 * self.kd:
  118. p2 = 3
  119. c += 5
  120. except:
  121. p2 = 4
  122. c += 9
  123. _p = 2
  124. if o_y != None and p != _p:
  125. if (o_y * y) < 0:
  126. c += 5
  127. elif abs(o_y - y) >= (10 * self.kd):
  128. c += 5
  129. if c >= 5 and (_p != 2 or p2 != 2):
  130. reason.append(c)
  131. self.__fx.append([])
  132. self.__fy.append([])
  133. p = _p
  134. self.__fx[-1].append(a_x)
  135. self.__fy[-1].append(y)
  136. o_y = y
  137. except:
  138. pass
  139. except (TypeError, IndexError, ValueError):
  140. pass
  141. newfx = []
  142. newfy = []
  143. must = False
  144. for i in range(len(self.__fx)): # 去除只有单个的组群
  145. if len(self.__fx[i]) == 1: # 检测到有单个群组
  146. q_r = reason[i] # 前原因
  147. b_r = reason[i] # 后原因
  148. if q_r < b_r: # 前原因小于后原因,连接到前面
  149. try:
  150. newfx[-1] += self.__fx[i]
  151. newfy[-1] += self.__fy[i]
  152. except: # 按道理不应该出现这个情况
  153. newfx.append(self.__fx[i])
  154. newfy.append(self.__fy[i])
  155. else:
  156. newfx.append(self.__fx[i])
  157. newfy.append(self.__fy[i])
  158. must = True
  159. else:
  160. if not must:
  161. newfx.append(self.__fx[i])
  162. newfy.append(self.__fy[i])
  163. else:
  164. newfx[-1] += self.__fx[i]
  165. newfy[-1] += self.__fy[i]
  166. must = False
  167. self.__fx = newfx
  168. self.__fy = newfy
  169. self.HaveDone = True
  170. self.__xyCSV = pandas.DataFrame((self.__x,self.__y),index=('x','y'))
  171. self.__Best_value()
  172. return self.__x,self.__y,self.Func_Name,self.View
  173. def Iterative_method_Of_Huan(self, y_in, *args,**kwargs):#保持和下一个对象相同参数
  174. r = self.Cul_dichotomy(y_in)
  175. return r[0],r[0][0]#
  176. def Cul_dichotomy(self, y_in, *args,**kwargs):#保持和下一个对象相同参数
  177. y = sorted(self.__y.copy())
  178. o_y = None#o_y是比较小的,i是比较大的
  179. q = None
  180. for i in y:
  181. try:
  182. if (o_y < y_in and i > y_in) and (abs(((i + o_y)/2) - y_in) < 0.1):
  183. q = [o_y,i]
  184. break
  185. except:
  186. pass
  187. o_y = i
  188. if q == None:
  189. for i in y:
  190. try:
  191. if abs(((i + o_y) / 2) - y_in) < 0.1:
  192. q = [o_y, i]
  193. break
  194. except:
  195. pass
  196. o_y = i
  197. if q == None:return [],[]
  198. X_o_y = Find(self.__x.copy(),self.__y.copy(),q[0])
  199. X_y = Find(self.__x.copy(),self.__y.copy(),q[1])
  200. l = min([len(X_y),len(X_o_y)])
  201. answer = []
  202. X_out = []
  203. for i in range(l):
  204. print(X_y[i],X_o_y[i])
  205. r = (X_y[i] + X_o_y[i])/2
  206. print(r)
  207. self.Memore_x.append(r)
  208. self.Memore_y.append(y_in)
  209. X_out.append(r)
  210. answer.append(f'y={y_in} -> x={r}')
  211. self.__MemoryAnswer += answer
  212. return answer,X_out
  213. def __Parity(self,ro=False):
  214. if not self.HaveDone: self.Cul() # 检查Cul的计算
  215. y = self.__y.copy()
  216. x = self.__x.copy()
  217. a = sorted(x)[0]
  218. b = sorted(x)[1]
  219. a = -min([abs(a),abs(b)])
  220. b = -a
  221. flat = None#0-偶函数,1-奇函数
  222. for i in range(len(x)):
  223. _x = x[i]#正项x
  224. if _x < a or _x > b:continue#x不在区间内
  225. try:
  226. _y = self(_x)
  227. o_y = self(-_x)
  228. if o_y == _y == 0:
  229. continue
  230. elif o_y == _y:
  231. if flat == None:
  232. flat = 0
  233. elif flat == 1:
  234. raise Exception
  235. elif o_y == -_y:
  236. if flat == None:
  237. flat = 1
  238. elif flat == 0:
  239. raise Exception
  240. else:
  241. raise Exception
  242. except:
  243. flat = None
  244. break
  245. return flat,[a,b]
  246. def __Monotonic(self):
  247. if not self.HaveDone: self.Cul() # 运行Cul计算
  248. fy = self.__fy.copy()
  249. fx = self.__fx.copy()
  250. Increase_interval = []#增区间
  251. Minus_interval = []#减区间
  252. Interval = []#不增不减
  253. for i in range(len(fx)):
  254. x = fx[i]
  255. y = fx[i]
  256. o_x = None
  257. o_y = None
  258. start_x = None
  259. flat = None#当前研究反围:0-增区间,1-减区间,2-不增不减
  260. for i in range(len(x)):
  261. _x = x[i]#正项x
  262. _y = y[i]#正项y
  263. if start_x == None:
  264. start_x = _x
  265. else:
  266. if o_y > _y:#减区间
  267. if flat == None or flat == 1:#减区间
  268. pass
  269. elif flat == 0:#增区间
  270. Increase_interval.append((start_x,o_x))
  271. start_x = o_x
  272. elif flat == 2:
  273. Interval.append((start_x, o_x))
  274. start_x = o_x
  275. flat = 1
  276. elif o_y < _y:#增区间
  277. if flat == None or flat == 0: # 增区间
  278. pass
  279. elif flat == 1: # 减区间
  280. Minus_interval.append((start_x, o_x))
  281. start_x = o_x
  282. elif flat == 2:
  283. Interval.append((start_x, o_x))
  284. start_x = o_x
  285. flat = 0
  286. else:#水平区间
  287. if flat == None or flat == 2:
  288. pass
  289. elif flat == 1: # 减区间
  290. Minus_interval.append((start_x, o_x))
  291. start_x = o_x
  292. elif flat == 0: # 增区间
  293. Increase_interval.append((start_x, o_x))
  294. start_x = o_x
  295. flat = 2
  296. o_x = _x
  297. o_y = _y
  298. if flat == 2:
  299. Interval.append((start_x, o_x))
  300. elif flat == 1: # 减区间
  301. Minus_interval.append((start_x, o_x))
  302. elif flat == 0: # 增区间
  303. Increase_interval.append((start_x, o_x))
  304. return Increase_interval,Minus_interval,Interval
  305. def Nature(self,addNews=lambda x:x):
  306. answer = []
  307. P = self.__Parity()
  308. M = self.__Monotonic()
  309. ZQ = self.Periodic(addNews)[0]
  310. DCZ = self.Symmetry_axis(addNews)[0]
  311. DCZX = self.Center_of_symmetry(addNews)[0]
  312. if P[0] == 1:
  313. answer.append(f'奇函数 区间:[{P[1][0]},{P[1][0]}]')
  314. elif P[0] == 0:
  315. answer.append(f'偶函数 区间:[{P[1][0]},{P[1][0]}]')
  316. for i in M[0]:
  317. answer.append(f'增区间:[{i[0]},{i[1]}]')
  318. for i in M[1]:
  319. answer.append(f'减区间:[{i[0]},{i[1]}]')
  320. for i in M[2]:
  321. answer.append(f'水平区间:[{i[0]},{i[1]}]')
  322. if ZQ != None:
  323. answer.append(f'最小正周期:{ZQ}')
  324. if DCZ != None:
  325. answer.append(f'对称轴:x={DCZ}')
  326. if DCZX != None:
  327. answer.append(f'对称中心:{DCZX}')
  328. return answer
  329. def YC_On_Off(self):
  330. if self.YC:
  331. if tkinter.messagebox.askokcancel('提示', f'是否显示{self}的记忆数据?'):
  332. # addNews('记忆显示完毕')
  333. self.YC = False
  334. else:
  335. if tkinter.messagebox.askokcancel('提示', f'是否隐藏{self}的记忆数据?'):
  336. # addNews('记忆隐藏完毕')
  337. self.YC = True
  338. def Out(self):
  339. if not self.HaveDone: self.Cul() # 检查Cul的计算
  340. if tkinter.messagebox.askokcancel('提示', f'是否确认导出函数:\n{str(self)}'):
  341. try:
  342. Dic = tkinter.filedialog.asksaveasfilename(title='选择导出位置', filetypes=[("CSV", ".csv")]) + '.csv'
  343. if Dic == '.csv':raise Exception
  344. self.__xyCSV.to_csv(Dic)
  345. return True
  346. except:
  347. pass
  348. return False
  349. def returnList(self):
  350. # 最值和极值点设计
  351. # if not self.HaveDone: self.Cul() # 检查Cul的计算
  352. a = []
  353. for i in self.min_x:
  354. a.append(f'极值点:{i}>最小值{self.min_y}')
  355. for i in self.max_x:
  356. a.append(f'极值点:{i}>最大值{self.max_y}')
  357. return a + self.__MemoryAnswer +self.__xy
  358. def Best_value(self):
  359. if not self.HaveDone: self.Cul() # 检查Cul的计算
  360. return self.max_x, self.max_y, self.min_x, self.min_y
  361. def getMemory(self):
  362. if self.YC: return [], []
  363. return self.Memore_x, self.Memore_y
  364. def Clear_Memory(self):
  365. self.Memore_x = []
  366. self.Memore_y = []
  367. self.__MemoryAnswer = []
  368. def Draw_Cul(self):
  369. if not self.HaveDone:self.Cul()
  370. return self.__fx,self.__fy,self.Func_Name,self.View
  371. def Cul_Y(self,x_in):
  372. answer = []
  373. for i in x_in:
  374. try:
  375. i = float(i)
  376. y = self(i)
  377. answer.append(f'x={i} -> y={y}')
  378. if i not in self.Memore_x:
  379. self.Memore_x.append(i)
  380. self.Memore_y.append(y)
  381. except:#捕捉运算错误
  382. continue
  383. self.__MemoryAnswer += answer
  384. self.__Best_value()
  385. return answer
  386. def Periodic(self,addNews=lambda x:x):#计算周期
  387. if not tkinter.messagebox.askokcancel('提示', f'计算周期需要一定时间,是否执行?(计算过程程序可能无响应)'):
  388. return None,[]#无结果
  389. if not self.HaveDone: self.Cul()
  390. p = []#可能的周期
  391. ran = len(self.__x)
  392. k = int(ran/20)
  393. addNews('正在预测可能的周期')
  394. for i in range(0,ran,k):
  395. start = self.__x[i]
  396. try:
  397. y = self(start)
  398. x_list = self.Cul_dichotomy(y)[1]
  399. # print(x_list)
  400. q = []
  401. for o_x in x_list:
  402. a = abs(o_x - start)
  403. if a == 0:continue
  404. if a:q.append(a)
  405. p.extend(list(set(q)))
  406. except:
  407. pass
  408. p_c = list(set(p))
  409. a = []#a的可能列表
  410. c = 0
  411. addNews('正在筛选结果')
  412. for i in p_c:
  413. n_c = p.count(i)
  414. if n_c > c:
  415. a = [i]
  416. c = n_c
  417. elif n_c == c:
  418. a.append(i)
  419. try:
  420. a.sort()#
  421. addNews('计算完毕')
  422. return a[0],a
  423. except:
  424. addNews('无周期')
  425. return None,[]#无结果
  426. def Symmetry_axis(self,addNews=lambda x:x):#计算对称轴
  427. if not tkinter.messagebox.askokcancel('提示', f'计算对称轴需要一定时间,是否执行?(计算过程程序可能无响应)'):
  428. return None,[]#无结果
  429. if not self.HaveDone: self.Cul()
  430. p = []#可能的对称轴
  431. ran = len(self.__x)
  432. k = int(ran / 20)
  433. addNews('正在预测可能的对称轴')
  434. for i in range(0, ran, k):
  435. start = self.__x[i]
  436. try:
  437. y = self(start)
  438. x_list = self.Cul_dichotomy(y)[1]
  439. print(x_list)
  440. q = []
  441. for o_x in x_list:
  442. a = (o_x + start)/2
  443. if a:q.append(a)
  444. p.extend(list(set(q)))
  445. except:
  446. pass
  447. p_c = list(set(p))
  448. a = []#a的可能列表
  449. c = 0
  450. addNews('正在筛选结果')
  451. for i in p_c:
  452. n_c = p.count(i)
  453. if n_c > c:
  454. a = [i]
  455. c = n_c
  456. elif n_c == c:
  457. a.append(i)
  458. try:
  459. a.sort() #
  460. addNews('计算完毕')
  461. return a[0], a
  462. except:
  463. addNews('无对称轴')
  464. return None, [] # 无结果
  465. def Center_of_symmetry(self,addNews=lambda x:x): # 计算对称中心
  466. if not tkinter.messagebox.askokcancel('提示', f'计算对称中心需要一定时间,是否执行?(计算过程程序可能无响应)'):
  467. return None, [] # 无结果
  468. if not self.HaveDone: self.Cul()
  469. point = [] # 可能的对称轴
  470. ran = len(self.__x)
  471. k = int(ran / 20)
  472. addNews('正在计算坐标点')
  473. for i in range(0, ran, k):
  474. start = self.__x[i]
  475. try:
  476. y = self(start)
  477. x = start
  478. point.append((x,y))
  479. except:
  480. pass
  481. p = []
  482. addNews('正在预测对称中心')
  483. for i in point:
  484. for o in point:
  485. x = i[0] + o[0] / 2
  486. y = i[1] + o[1] / 2
  487. if i == o:continue
  488. # print(f'i={i},o={o},x={x},y={y}')
  489. p.append((x,y))
  490. p_c = list(set(p))
  491. a = [] # a的可能列表
  492. c = 0
  493. addNews('正在筛选结果')
  494. for i in p_c:
  495. n_c = p.count(i)
  496. if n_c > c:
  497. a = [i]
  498. c = n_c
  499. elif n_c == c:
  500. a.append(i)
  501. try:
  502. if c < 5:raise Exception
  503. addNews('计算完毕')
  504. a.sort() #
  505. return a[int(len(a)/2)], a
  506. except:
  507. addNews('无对称中心')
  508. return None, [] # 无结果
  509. class HS_lambda:
  510. def __init__(self,HS,name,view,start = -10,end = 10,kd = 0.1,JD = 2,a = 1,a_start=-10,a_end=10,a_kd=1,c_Son = False):
  511. self.x = sympy.Symbol('x')
  512. Name = {'a':a,'x': self.x, 'Pi': sympy.pi, 'e': sympy.E, 'log': sympy.log,
  513. 'sin': sympy.sin, 'cos': sympy.cos, 'tan': sympy.tan,
  514. 'cot': lambda x: 1 / sympy.tan(x), 'csc': lambda x: 1 / sympy.sin(x),
  515. 'sec': lambda x: 1 / sympy.cos(x), 'sinh': sympy.sinh, 'cosh': sympy.cosh,
  516. 'tanh': sympy.tanh, 'asin': sympy.asin, 'acos': sympy.acos,
  517. 'atan': sympy.atan,'abs':abs} # 这个是函数命名域
  518. self.HS = eval(HS.replace(' ', ''), Name)#函数解析式
  519. self.str_HS = HS.replace(' ', '')
  520. #函数基本信息
  521. self.View = view#绘制样式
  522. #数据辨析
  523. try:
  524. start = float(start)
  525. end = float(end)
  526. if start > end:#使用float确保输入是数字,否则诱发ValueError
  527. start, end = end, start
  528. kd = abs(float(kd))
  529. start = (start//kd)*kd#确保start可以恰好被kd整除
  530. end = (end//kd+1)*kd
  531. JD = abs(int(JD))
  532. if JD >= 3:JD = 3
  533. except ValueError:
  534. start,end,kd,JD = -10,10,0.1,2#保底设置
  535. #基本数据存储
  536. self.JD = JD
  537. self.start = start
  538. self.end = end
  539. self.kd = kd
  540. #x和y数据存储
  541. self.__x = []
  542. self.__y = []
  543. self.__ya = []
  544. self.__fx = [[]]
  545. self.__fy = [[]]
  546. #记忆数据存储
  547. self.Memore_x = []
  548. self.Memore_y = []
  549. self.__MemoryAnswer = []
  550. #最值和极值点
  551. self.max_y = None
  552. self.max_x = []
  553. self.min_y = None
  554. self.min_x = []
  555. self.YC = False
  556. self.Best_R = None#是否计算最值
  557. self.HaveDone = False#是否已经计算过xy
  558. #函数求导
  559. try:
  560. self.DHS = sympy.diff(self.HS, self.x)
  561. except:
  562. self.DHS = None
  563. #儿子函数
  564. try:
  565. a_start = float(a_start)
  566. a_end = float(a_end)
  567. if a_start > a_end:#使用float确保输入是数字,否则诱发ValueError
  568. a_start, a_end = a_end, a_start
  569. a_kd = abs(float(a_kd))
  570. except ValueError:
  571. a_start,a_end,a_kd = -10,10,1#保底设置
  572. if c_Son:
  573. self.Son_List = []
  574. while a_start <= a_end:
  575. try:
  576. self.Son_List.append(HS_lambda_Son(HS,name,view,start,end,kd,JD,a_start))
  577. except:pass#不应该出现
  578. a_start += a_kd
  579. self.Func_Name = f'{name}:y={HS} a={a}({a_start},{a_end},{a_kd})' # 这个是函数名字
  580. else:
  581. self.Son_List = []
  582. self.Func_Name = f'{name}:y={HS} a={a})' # 这个是函数名字
  583. def Return_Son(self):
  584. return self.Son_List
  585. def __call__(self,x):
  586. return self.HS.subs({self.x:x})
  587. def __str__(self):
  588. return f'{self.Func_Name} {self.start,self.end,self.kd}'
  589. def __Best_value(self):#计算最值和极值点
  590. #使用ya解决了因计算器误差而没计算到的最值,但是同时本不是最值的与最值相近的数字也被当为了最值,所以使用群组击破
  591. if not self.HaveDone: self.Cul()#检查Cul的计算
  592. if len(self.__fx) != 1:#没有计算的必要
  593. if self.Best_R == None:
  594. self.Best_R = not tkinter.messagebox.askokcancel('建议不计算最值', f'{self}的最值计算不精确,函数可能无最值,是否不计算最值')
  595. if not self.Best_R:
  596. pass
  597. return self.max_x,self.max_y,self.min_x,self.min_y
  598. y = self.__ya + self.Memore_y#x和y数据对齐(因为是加法,所以y的修改不影响self.__ya)
  599. _y = self.__y + self.Memore_y
  600. x = self.__x + self.Memore_x
  601. max_y = max(y)
  602. min_y = min(y)
  603. max_x = Find(x.copy(),y,max_y)
  604. min_x = Find(x.copy(),y,min_y)
  605. #处理最大值极值点重复
  606. max_x = sorted(list(set(max_x)))#处理重复
  607. n = []
  608. o_a = None
  609. flat = False
  610. b = max_x.copy() #可处理列表
  611. for i in range(len(max_x)): #迭代选择
  612. g_a = max_x[i]
  613. if o_a == None or abs(g_a - o_a) >= 1:#1-连续系数
  614. flat = False
  615. else:
  616. if flat:#加入群组
  617. n[-1].append(g_a)
  618. else:#新键群组
  619. n.append([o_a, g_a])
  620. del b[b.index(o_a)]
  621. flat = True
  622. del b[b.index(g_a)]#删除可处理列表
  623. o_a = g_a
  624. for i in n:#逐个攻破群组
  625. y_For_X = []#群组中x的y值
  626. for Qx in i:
  627. num = x.index(Qx)
  628. y_For_X.append(_y[num])#找到对应y值
  629. n_max = max(y_For_X)#求解最大y值
  630. n_x = Find(i,y_For_X,n_max)
  631. n_max_x = n_x[int(len(n_x)/2)]
  632. b.append(n_max_x)#取中间个
  633. self.max_y = max_y
  634. self.max_x = b
  635. # 处理最小值极值点重复
  636. min_x = sorted(list(set(min_x))) # 处理重复
  637. n = []
  638. o_a = None
  639. flat = False
  640. b = min_x.copy() # 可处理列表
  641. for i in range(len(min_x)): # 迭代选择
  642. g_a = min_x[i]
  643. if o_a == None or abs(g_a - o_a) >= 1: # 1-连续系数
  644. flat = False
  645. else:
  646. if flat: # 加入群组
  647. n[-1].append(g_a)
  648. else: # 新键群组
  649. n.append([o_a, g_a])
  650. del b[b.index(o_a)]
  651. flat = True
  652. del b[b.index(g_a)] # 删除可处理列表
  653. o_a = g_a
  654. for i in n: # 逐个攻破群组
  655. y_For_X = [] # 群组中x的y值
  656. for Qx in i:
  657. num = x.index(Qx)
  658. y_For_X.append(_y[num]) # 找到对应y值
  659. n_min = min(y_For_X) # 求解最大y值
  660. n_x = Find(i,y_For_X,n_min)
  661. n_min_x = n_x[int(len(n_x) / 2)]
  662. b.append(n_min_x) # 取中间个
  663. self.min_y = min_y
  664. self.min_x = b
  665. return self.max_x,self.max_y,self.min_x,self.min_y
  666. def Cul(self,it=float):
  667. if self.HaveDone:
  668. return self.__x,self.__y,self.Func_Name,self.View
  669. #混合存储
  670. self.__y = []
  671. self.__ya = []
  672. self.__x = []
  673. self.__xy = []
  674. self.__fx = [[]]
  675. self.__fy = [[]]
  676. reason = [30]
  677. o_y = None
  678. p = None#单调性 0-增,1-减
  679. _p = 1
  680. try:
  681. a = int(self.start)
  682. while a <= int(self.end): # 因为range不接受小数
  683. p2 = 1
  684. try:
  685. c = 0
  686. a_x = round(a, self.JD)
  687. y = self(a_x)
  688. y = it(y)#数字处理方案
  689. a_y=round(y,self.JD)
  690. if o_y != None and o_y > y:
  691. _p = 1
  692. elif o_y != None and o_y < y:
  693. _p = 0
  694. elif o_y != None and o_y == y:
  695. try:
  696. z_x = round(a_x - 0.5 * self.kd)
  697. z_y = self(z_x)
  698. if z_y == o_y == y: # 真实平衡
  699. p2 = 2
  700. elif abs(z_y - o_y) >= 10 * self.kd or abs(z_y - y) >= 10 * self.kd:
  701. p2 = 3
  702. c += 5
  703. except:
  704. p2 = 4
  705. c += 9
  706. _p = 2
  707. if o_y != None and p != _p:
  708. if (o_y * y) < 0:
  709. c += 5
  710. elif abs(o_y - y) >= (10 * self.kd):
  711. c += 5
  712. if c >= 5 and (_p != 2 or p2 != 2):
  713. reason.append(c)
  714. self.__fx.append([])
  715. self.__fy.append([])
  716. p = _p
  717. self.__x.append(a_x)#四舍五入减少计算量
  718. self.__y.append(y)#不四舍五入
  719. self.__ya.append(a_y) # 四舍五入(用于求解最值)
  720. self.__xy.append(f'x:{a_x},y:{a_y}')
  721. self.__fx[-1].append(a_x)
  722. self.__fy[-1].append(y)
  723. o_y = y
  724. except:
  725. reason.append(0)
  726. self.__fx.append([])
  727. self.__fy.append([])
  728. a += self.kd
  729. except (TypeError, IndexError, ValueError):
  730. pass
  731. newfx = []
  732. newfy = []
  733. must = False
  734. for i in range(len(self.__fx)):#去除只有单个的组群
  735. if len(self.__fx[i]) <= 1:#检测到有单个群组
  736. q_r = reason[i]#前原因
  737. b_r = reason[i]#后原因
  738. if q_r < b_r:#前原因小于后原因,连接到前面
  739. try:
  740. newfx[-1] += self.__fx[i]
  741. newfy[-1] += self.__fy[i]
  742. except:#按道理不应该出现这个情况
  743. newfx.append(self.__fx[i])
  744. newfy.append(self.__fy[i])
  745. else:
  746. newfx.append(self.__fx[i])
  747. newfy.append(self.__fy[i])
  748. must = True
  749. else:
  750. if not must:
  751. newfx.append(self.__fx[i])
  752. newfy.append(self.__fy[i])
  753. else:
  754. newfx[-1] += self.__fx[i]
  755. newfy[-1] += self.__fy[i]
  756. must = False
  757. self.__fx = newfx
  758. self.__fy = newfy
  759. self.HaveDone = True
  760. self.__xyCSV = pandas.DataFrame((self.__x,self.__y),index=('x','y'))
  761. self.__Best_value()
  762. return self.__x,self.__y,self.Func_Name,self.View
  763. def Iterative_method_Of_Huan(self,y_in,start,end,k=100,kx=0.00001):#梯度计算(kx表示精度)
  764. try:
  765. y_in = float(y_in)
  766. start = float(start)
  767. end = float(end)
  768. except:
  769. return '',None
  770. try:
  771. k = int(k)
  772. kx = float(kx)
  773. except:
  774. k = 100
  775. kx = 0.00001
  776. a = start
  777. b = end
  778. o_a = []
  779. o_b = []
  780. c = 0
  781. o_c = None
  782. _a = 0
  783. _b = 0
  784. _c = 0
  785. flat = 0#收缩方向1=a往b,2=b往a,0=未知
  786. p = 0#增or减
  787. q = 0#增减预测1增,0减
  788. for i in range(k):
  789. #a,b,c确定
  790. if a > b: a, b = b, a # a是小的数字,b是大的数字,c是中间
  791. o_a.append(a)#赋值a的回退值
  792. o_b.append(b)
  793. c = (a + b) / 2
  794. _a = self(a)
  795. _b = self(b)
  796. _c = self(c)
  797. #增减预测
  798. if abs(_c - y_in)<kx:#数据计算完成
  799. break
  800. elif _c < y_in:#预测增还是减:_c移动到y_in需要增还是间
  801. q = 1#增
  802. else:
  803. q = 0#减
  804. try:#当前是增还是减
  805. if o_c == _c:#恰好关于了原点对称
  806. pass#保持不变
  807. elif o_c < _c:
  808. p = 1#增
  809. else:
  810. p = 0#减
  811. except:
  812. flat = 1
  813. p = q
  814. o_c = _c
  815. #开始行动
  816. if q == p:#实际和预测一样,保持相同执行方案
  817. if flat == 1:#a往b方向收缩
  818. a = c
  819. else:
  820. b = c
  821. else:
  822. if flat == 1:#收缩方向相反
  823. a = o_a[-2]
  824. b = c
  825. flat = 0
  826. else:
  827. a = c
  828. b = o_b[-2]
  829. flat = 1
  830. else:
  831. return '', None
  832. self.Memore_x.append(c)
  833. self.Memore_y.append(y_in)
  834. self.__MemoryAnswer.append(f'y={y_in} -> x={c}')
  835. print(f'y={y_in} -> x={c}',c)
  836. return f'y={y_in} -> x={c}',c
  837. def Cul_dichotomy(self, y_in, k=100, d=0.0001, ky=0.1, dx=0.5, r_Cul=False,H_Cul=True, deep=1000, cx=0.1, kx=0.1,f_On=False,f=None,all=False):
  838. #y_in输入的参数,k最大迭代数,r_Cul允许使用原来的数值,d精度,ky最值允许偏移量,kx新区间偏移量,cx扩张限制,dx两零点的最小范围,deep扩张深度
  839. #H_Cul允许扩展计算,f_On开启二级验证,f二级验证效果
  840. if f == None:f = d
  841. try:#参数处理
  842. r_Cul = Bool(r_Cul)
  843. H_Cul = Bool(H_Cul,True)
  844. f_On = Bool(f_On)
  845. k = abs(int(k))
  846. d = abs(float(d))
  847. ky = abs(float(ky))
  848. kx = abs(float(kx))
  849. cx = abs(float(cx))
  850. dx = abs(float(dx))
  851. deep = abs(int(deep))
  852. f = abs(float(f))
  853. except:
  854. r_Cul = False
  855. H_Cul = True
  856. f_On = False
  857. k = 100
  858. d = 0.0001
  859. ky = 0.1
  860. kx = 0.1
  861. cx = 0.5
  862. dx = 0.5
  863. deep = 100
  864. f = d
  865. if not self.HaveDone: self.Cul()
  866. x = self.__x + self.Memore_x
  867. y = self.__y + self.Memore_x
  868. try:#y_in是否为数字
  869. y_in = float(y_in)
  870. except:
  871. return [], []
  872. try:
  873. if y_in < self.min_y-ky or y_in > self.max_y+ky: return [],[] # 返回空值
  874. if r_Cul and y_in in y: # 如果已经计算过
  875. num = y.index(y_in)
  876. return x[num]
  877. except:
  878. pass
  879. iter_list = [[self.start, self.end]] # 准备迭代的列表
  880. c_list = []
  881. c_o_list = []
  882. c = 0
  883. for ab in iter_list:
  884. a = ab[0]
  885. b = ab[1]
  886. c = None
  887. br = False
  888. for i in range(k): # 限定次数的迭代
  889. try:
  890. if a > b:a,b=b,a#a是小的数字,b是大的数字,c是中间
  891. if a == b:#如果相等,作废
  892. c=None
  893. break
  894. _a = self(a) - y_in#计算a
  895. _b = self(b) - y_in#计算b
  896. c = (a + b) / 2#计算c
  897. try:
  898. _c = self(c) - y_in#计算c
  899. except:
  900. if deep > 0: # 尝试向两边扩张,前提是有deep余额(扩张限制)而且新去见大于cx
  901. if abs(a - (c - kx)) > cx:
  902. iter_list.append([a, c - kx]) # 增加区间(新区间不包括c,增加了一个偏移kx)
  903. deep -= 1 # 余额减一
  904. if abs((c + kx) - b) > cx:
  905. iter_list.append([c + kx, b]) # 增加区间
  906. deep -= 1
  907. c = None
  908. break
  909. # print(f'a={a},b={b},c={c},_a={_a},_b={_b}')
  910. q = _a * _c#a,c之间零点
  911. p = _b * _c#b,c之间零点
  912. if _c == 0:#如果c就是零点
  913. if deep > 0:#尝试向两边扩张,前提是有deep余额(扩张限制)而且新去见大于cx
  914. if abs(a - (c-kx)) > cx:
  915. iter_list.append([a, c-kx])#增加区间(新区间不包括c,增加了一个偏移kx)
  916. deep -= 1#余额减一
  917. if abs((c+kx) - b) > cx:
  918. iter_list.append([c+kx, b])#增加区间
  919. deep -= 1
  920. break#这个区间迭代完成,跳出返回c
  921. elif q * p == 0:#a或者b之间有一个是零点
  922. if q == 0:#a是零点
  923. c = a
  924. if deep > 0 and abs((a+kx) - b) > cx:#尝试往b方向扩张
  925. iter_list.append([a+kx, b])
  926. deep -= 1
  927. break
  928. else:
  929. c = b#同上
  930. if deep > 0 and abs(a - (b-kx)) > cx:
  931. iter_list.append([a, b-kx])
  932. deep -= 1
  933. break
  934. elif q * p > 0:#q和p都有或都没用零点
  935. if q > 0 and abs(a - b) < dx:#如果ab足够小反围,则认为a和b之间不存在零点
  936. if H_Cul:
  937. # addNews('进入梯度运算')
  938. c = self.Iterative_method_Of_Huan(y_in, a, b)[1]
  939. if c != None:
  940. break
  941. c = None
  942. break
  943. iter_list.append([b, c])#其中一个方向继续迭代,另一个方向加入候选
  944. b = c
  945. _b = self(b) - y_in
  946. elif q < 0:#往一个方向收缩,同时另一个方向增加新的区间
  947. if deep > 0 and abs(c - b) > cx:
  948. iter_list.append([c,b])
  949. deep -= 1
  950. b = c
  951. _b = self(b) - y_in
  952. elif p < 0:#同上
  953. if deep > 0 and abs(a - c) > cx:
  954. iter_list.append([a,c])
  955. deep -= 1
  956. a = c
  957. _a = self(a) - y_in
  958. if abs(a - b) < d:#a和b足够小,认为找到零点
  959. c = (a + b) / 2
  960. _c = self(c)
  961. if f_On and abs(y_in - _c) > f:#_c不是目标输出
  962. print("A")
  963. c = None
  964. break
  965. except:
  966. break
  967. else:#证明没有break
  968. br = True
  969. if c == None:
  970. continue#去除c不存在的选项
  971. if not br:
  972. c_list.append(c)
  973. else:
  974. c_o_list.append(c)
  975. answer = []
  976. for i in c_list:
  977. self.Memore_x.append(i)
  978. self.Memore_y.append(y_in)
  979. answer.append(f'y={y_in} -> x={i}')
  980. if all:
  981. for i in c_o_list:
  982. answer.append(f'(误差)y={y_in} -> x={i}')
  983. self.__MemoryAnswer += answer
  984. return answer, c_list
  985. def __Parity(self,ro=False):#启动round处理
  986. if not self.HaveDone: self.Cul()#运行Cul计算
  987. if len(self.__fx) != 1:
  988. m = True#通过self计算y
  989. else:
  990. m = False
  991. y = self.__y.copy()
  992. x = self.__x.copy()
  993. a = self.start
  994. b = self.end
  995. a = -min([abs(a),abs(b)])
  996. b = -a
  997. flat = None#0-偶函数,1-奇函数
  998. for i in range(len(x)):
  999. _x = x[i]#正项x
  1000. if _x < a or _x > b:continue#x不在区间内
  1001. try:
  1002. if m:
  1003. _y = self(_x)
  1004. else:
  1005. _y = y[i] # 求得x的y
  1006. if m:
  1007. o_y = self(-_x)
  1008. else:
  1009. o_y = y[x.index(-_x)]#求得-x的y
  1010. if ro:
  1011. _y = round(_y,self.JD)
  1012. o_y = round(o_y, self.JD)
  1013. if o_y == _y == 0:
  1014. continue
  1015. elif o_y == _y:
  1016. if flat == None:
  1017. flat = 0
  1018. elif flat == 1:
  1019. raise Exception
  1020. elif o_y == -_y:
  1021. if flat == None:
  1022. flat = 1
  1023. elif flat == 0:
  1024. raise Exception
  1025. else:
  1026. raise Exception
  1027. except:
  1028. flat = None
  1029. break
  1030. return flat,[a,b]
  1031. def __Monotonic(self):
  1032. if not self.HaveDone: self.Cul() # 运行Cul计算
  1033. fy = self.__fy.copy()
  1034. fx = self.__fx.copy()
  1035. Increase_interval = []#增区间
  1036. Minus_interval = []#减区间
  1037. Interval = []#不增不减
  1038. for i in range(len(fx)):
  1039. x = fx[i]
  1040. y = fx[i]
  1041. o_x = None
  1042. o_y = None
  1043. start_x = None
  1044. flat = None#当前研究反围:0-增区间,1-减区间,2-不增不减
  1045. for i in range(len(x)):
  1046. _x = x[i]#正项x
  1047. _y = y[i]#正项y
  1048. if start_x == None:
  1049. start_x = _x
  1050. else:
  1051. if o_y > _y:#减区间
  1052. if flat == None or flat == 1:#减区间
  1053. pass
  1054. elif flat == 0:#增区间
  1055. Increase_interval.append((start_x,o_x))
  1056. start_x = o_x
  1057. elif flat == 2:
  1058. Interval.append((start_x, o_x))
  1059. start_x = o_x
  1060. flat = 1
  1061. elif o_y < _y:#增区间
  1062. if flat == None or flat == 0: # 增区间
  1063. pass
  1064. elif flat == 1: # 减区间
  1065. Minus_interval.append((start_x, o_x))
  1066. start_x = o_x
  1067. elif flat == 2:
  1068. Interval.append((start_x, o_x))
  1069. start_x = o_x
  1070. flat = 0
  1071. else:#水平区间
  1072. if flat == None or flat == 2:
  1073. pass
  1074. elif flat == 1: # 减区间
  1075. Minus_interval.append((start_x, o_x))
  1076. start_x = o_x
  1077. elif flat == 0: # 增区间
  1078. Increase_interval.append((start_x, o_x))
  1079. start_x = o_x
  1080. flat = 2
  1081. o_x = _x
  1082. o_y = _y
  1083. if flat == 2:
  1084. Interval.append((start_x, o_x))
  1085. elif flat == 1: # 减区间
  1086. Minus_interval.append((start_x, o_x))
  1087. elif flat == 0: # 增区间
  1088. Increase_interval.append((start_x, o_x))
  1089. return Increase_interval,Minus_interval,Interval
  1090. def Nature(self,addNews=lambda x:x,all=False,JD=None,must=False):
  1091. try:
  1092. if not must:JD = float(JD)
  1093. except:
  1094. JD = None
  1095. answer = []
  1096. P = self.__Parity()
  1097. M = self.__Monotonic()
  1098. ZQ = self.Periodic(addNews,JD)
  1099. DCZ = self.Symmetry_axis(addNews,JD)
  1100. DCZX = self.Center_of_symmetry(addNews,JD)
  1101. if P[0] == 1:
  1102. answer.append(f'奇函数 区间:[{P[1][0]},{P[1][0]}]')
  1103. elif P[0] == 0:
  1104. answer.append(f'偶函数 区间:[{P[1][0]},{P[1][0]}]')
  1105. for i in M[0]:
  1106. answer.append(f'增区间:[{i[0]},{i[1]}]')
  1107. for i in M[1]:
  1108. answer.append(f'减区间:[{i[0]},{i[1]}]')
  1109. for i in M[2]:
  1110. answer.append(f'水平区间:[{i[0]},{i[1]}]')
  1111. if self.DHS:
  1112. answer.append(f'导函数:{self.DHS}')
  1113. if ZQ[0] != None:
  1114. answer.append(f'最小正周期:{ZQ[0]}')
  1115. if DCZ[0] != None:
  1116. answer.append(f'对称轴:x={DCZ[0]}')
  1117. if DCZX[0] != None:
  1118. answer.append(f'对称中心:{DCZX[0]}')
  1119. if all:
  1120. try:
  1121. for i in ZQ[1][1:]:
  1122. answer.append(f'可能的最小正周期:{i}')
  1123. except:
  1124. pass
  1125. try:
  1126. for i in DCZ[1][1:]:
  1127. answer.append(f'可能的对称轴:{i}')
  1128. except:
  1129. pass
  1130. try:
  1131. for i in DCZX[1][1:]:
  1132. answer.append(f'可能的对称中心:{i}')
  1133. except:
  1134. pass
  1135. return answer
  1136. def YC_On_Off(self):#记忆数据显示和隐藏
  1137. if self.YC:
  1138. if tkinter.messagebox.askokcancel('提示', f'是否显示{self}的记忆数据?'):
  1139. # addNews('记忆显示完毕')
  1140. self.YC = False
  1141. else:
  1142. if tkinter.messagebox.askokcancel('提示', f'是否隐藏{self}的记忆数据?'):
  1143. # addNews('记忆隐藏完毕')
  1144. self.YC = True
  1145. def Out(self):
  1146. if not self.HaveDone: self.Cul()
  1147. if tkinter.messagebox.askokcancel('提示', f'是否确认导出函数:\n{str(self)}'):
  1148. try:
  1149. Dic = tkinter.filedialog.asksaveasfilename(title='选择导出位置', filetypes=[("CSV", ".csv")]) + '.csv'
  1150. if Dic == '.csv':raise Exception
  1151. self.__xyCSV.to_csv(Dic)
  1152. return True
  1153. except:
  1154. pass
  1155. return False
  1156. def returnList(self):#导出列表
  1157. if not self.HaveDone:self.Cul()
  1158. #最值和极值点设计
  1159. a = []
  1160. for i in self.min_x:
  1161. a.append(f'极值点:{i}>最小值{self.min_y}')
  1162. for i in self.max_x:
  1163. a.append(f'极值点:{i}>最大值{self.max_y}')
  1164. return a + self.__MemoryAnswer +self.__xy
  1165. def Best_value(self):
  1166. return self.max_x, self.max_y, self.min_x, self.min_y
  1167. def getMemory(self):
  1168. if self.YC:return [],[]
  1169. return self.Memore_x,self.Memore_y
  1170. def Clear_Memory(self):
  1171. self.Memore_x = []
  1172. self.Memore_y = []
  1173. self.__MemoryAnswer = []
  1174. def Draw_Cul(self):
  1175. if not self.HaveDone:self.Cul()
  1176. return self.__fx,self.__fy,self.Func_Name,self.View
  1177. def Cul_Y(self,x_in):
  1178. answer = []
  1179. for i in x_in:
  1180. try:
  1181. i = float(i)
  1182. y = self(i)
  1183. answer.append(f'x={i} -> y={y}={float(y)}')
  1184. if i not in self.Memore_x:
  1185. self.Memore_x.append(i)
  1186. self.Memore_y.append(y)
  1187. except:#捕捉运算错误
  1188. continue
  1189. self.__Best_value()
  1190. self.__xyCSV = pandas.DataFrame((self.__x+self.Memore_x, self.__y+self.Memore_y), index=('x', 'y'))
  1191. self.__MemoryAnswer += answer
  1192. return answer
  1193. def Periodic(self,addNews=lambda x:x,JD=None):#计算周期
  1194. if not tkinter.messagebox.askokcancel('提示', f'计算周期需要一定时间,是否执行?(计算过程程序可能无响应)'):
  1195. return None,[]#无结果
  1196. if not self.HaveDone: self.Cul()
  1197. p = []#可能的周期
  1198. start = self.start
  1199. end = self.end
  1200. if JD != None:
  1201. k = JD
  1202. else:
  1203. k = abs(start - end) / 20
  1204. addNews('正在预测可能的周期')
  1205. print(start,end,k)
  1206. while start <= end:
  1207. try:
  1208. y = self(start)
  1209. x_list = self.Cul_dichotomy(y)[1]
  1210. addNews('迭代运算...')
  1211. # print(x_list)
  1212. q = []
  1213. for o_x in x_list:
  1214. a = round(abs(o_x - start),self.JD)
  1215. if a == 0:
  1216. start += k
  1217. continue
  1218. if a:q.append(round(a,self.JD))
  1219. p.extend(list(set(q)))
  1220. except:
  1221. pass
  1222. start += k
  1223. print(start)
  1224. p_c = list(set(p))
  1225. a = []#a的可能列表
  1226. c = 0
  1227. addNews('正在筛选结果')
  1228. for i in p_c:
  1229. n_c = p.count(i)
  1230. if n_c > c:
  1231. a = [i]
  1232. c = n_c
  1233. elif n_c == c:
  1234. a.append(i)
  1235. try:
  1236. a.sort()#
  1237. addNews('计算完毕')
  1238. return a[0],a
  1239. except:
  1240. addNews('无周期')
  1241. return None,[]#无结果
  1242. def Symmetry_axis(self,addNews=lambda x:x,JD=None):#计算对称轴
  1243. if not tkinter.messagebox.askokcancel('提示', f'计算对称轴需要一定时间,是否执行?(计算过程程序可能无响应)'):
  1244. return None,[]#无结果
  1245. if not self.HaveDone: self.Cul()
  1246. p = []#可能的对称轴
  1247. start = self.start
  1248. end = self.end
  1249. if JD != None:
  1250. k = JD
  1251. else:
  1252. k = abs(start - end) / 20
  1253. addNews('正在预测对称轴')
  1254. while start <= end:
  1255. try:
  1256. y = self(start)
  1257. x_list = self.Cul_dichotomy(y)[1]
  1258. addNews('迭代运算...')
  1259. # print(x_list)
  1260. q = []
  1261. for o_x in x_list:
  1262. a = (o_x + start)/2
  1263. if a:q.append(round(a,self.JD))
  1264. p.extend(list(set(q)))
  1265. except:
  1266. pass
  1267. start += k
  1268. p_c = list(set(p))
  1269. a = []#a的可能列表
  1270. c = 0
  1271. addNews('正在筛选结果')
  1272. for i in p_c:
  1273. n_c = p.count(i)
  1274. if n_c > c:
  1275. a = [i]
  1276. c = n_c
  1277. elif n_c == c:
  1278. a.append(i)
  1279. try:
  1280. a.sort() #
  1281. addNews('计算完毕')
  1282. return a[0], a
  1283. except:
  1284. addNews('无对称轴')
  1285. return None, [] # 无结果
  1286. def Center_of_symmetry(self,addNews=lambda x:x,JD=None): # 计算对称中心
  1287. if not tkinter.messagebox.askokcancel('提示', f'计算对称中心需要一定时间,是否执行?(计算过程程序可能无响应)'):
  1288. return None, [] # 无结果
  1289. if not self.HaveDone: self.Cul()
  1290. point = [] # 可能的对称轴
  1291. start = self.start
  1292. end = self.end
  1293. addNews('正在计算坐标点')
  1294. if JD != None:
  1295. k = JD
  1296. else:
  1297. k = 1
  1298. while start <= end:
  1299. try:
  1300. y = self(start)
  1301. x = start
  1302. point.append((x,y))
  1303. except:
  1304. pass
  1305. start += k
  1306. p = []
  1307. addNews('正在预测对称中心')
  1308. for i in point:
  1309. for o in point:
  1310. x = round((i[0] + o[0])/2,self.JD)
  1311. y = round((i[1] + o[1]) / 2, self.JD)
  1312. if i == o:continue
  1313. # print(f'i={i},o={o},x={x},y={y}')
  1314. p.append((x,y))
  1315. p_c = list(set(p))
  1316. a = [] # a的可能列表
  1317. c = 0
  1318. addNews('正在筛选结果')
  1319. for i in p_c:
  1320. n_c = p.count(i)
  1321. if n_c > c:
  1322. a = [i]
  1323. c = n_c
  1324. elif n_c == c:
  1325. a.append(i)
  1326. try:
  1327. if c < 5:raise Exception
  1328. addNews('计算完毕')
  1329. a.sort() #
  1330. return a[int(len(a)/2)], a
  1331. except:
  1332. addNews('无对称中心')
  1333. return None, [] # 无结果
  1334. def Check_Monotonic(self,cs,addNews=lambda x:x,JD = None):#检查单调性
  1335. test = True#预测结果
  1336. try:
  1337. cd = cs.split(',')
  1338. start = float(cd[0])
  1339. end = float(cd[1])
  1340. flat = float(cd[2]) # 当前研究反围:0-增区间,1-减区间,2-不增不减
  1341. except:
  1342. return False,''
  1343. if start > end:
  1344. start,end = end,start
  1345. o_y = None
  1346. if JD != None:
  1347. k = JD
  1348. else:
  1349. k = self.kd
  1350. while start<= end:
  1351. try:
  1352. addNews('迭代运算...')
  1353. y = round(self(start),self.JD)
  1354. except:
  1355. start += k
  1356. continue
  1357. start += k
  1358. if o_y == None:continue
  1359. if flat == 0 and o_y > y:#增区间,o_y不小于y
  1360. test = False
  1361. break
  1362. elif flat == 1 and o_y < y:#减小区间,o_y不小于y
  1363. test = False
  1364. break
  1365. elif flat == 2 and o_y != y:
  1366. test = False
  1367. break
  1368. o_y = y
  1369. #Start+=k在上面
  1370. key = {0:'单调递增',1:'单调递减',2:'平行'}
  1371. keys = {True: '成立', False: '不成立'}
  1372. return test,f'{self}在[{cd[0]},{cd[1]}]{key[flat]}{keys[test]}'
  1373. def Check_Periodic(self,cs,addNews=lambda x:x,JD = None):#检查周期性
  1374. test = True
  1375. try:
  1376. cs = float(cs)
  1377. except:
  1378. return False,''
  1379. start = self.start
  1380. end = self.end
  1381. if JD != None:
  1382. k = JD
  1383. else:
  1384. k = self.kd
  1385. while start <= end:
  1386. try:
  1387. addNews('迭代运算...')
  1388. y = round(self(start),self.JD)
  1389. o_y = round(self(start + cs),self.JD)
  1390. if y != o_y:
  1391. test = False
  1392. except:
  1393. pass
  1394. start += k
  1395. key = {True:'是',False:'不是'}
  1396. return test,f'{self}的周期{key[test]}{cs}'
  1397. def Check_Symmetry_axis(self,cs,addNews=lambda x:x,JD=None):#检查对称轴
  1398. test = True
  1399. try:
  1400. cs = 2 * float(cs)
  1401. except:
  1402. return False,''
  1403. start = self.start
  1404. end = self.end
  1405. if JD != None:
  1406. k = JD
  1407. else:
  1408. k = self.kd
  1409. while start <= end:
  1410. try:
  1411. addNews('迭代运算...')
  1412. y = round(self(start),self.JD)
  1413. o_y = round(self(cs-start),self.JD)#(a+b)/2=c >>> b = 2c-a
  1414. if y != o_y:
  1415. test = False
  1416. except:
  1417. pass
  1418. start += k
  1419. key = {True:'是',False:'不是'}
  1420. return test,f'{self}的对称轴{key[test]}{cs}'
  1421. def Check_Center_of_symmetry(self,in_cs,addNews=lambda x:x,JD=None):#检查对称中心
  1422. test = True
  1423. try:
  1424. cs = []
  1425. for i in in_cs.split(','):
  1426. cs.append(float(i))
  1427. except:
  1428. return False,''
  1429. start = self.start
  1430. end = self.end
  1431. if JD != None:
  1432. k = JD
  1433. else:
  1434. k = self.kd
  1435. while start <= end:
  1436. try:
  1437. addNews('迭代运算...')
  1438. y = round(self(start),self.JD)
  1439. o_y = round(self(2*cs[0]-start),self.JD)#(a+b)/2=c >>> b = 2c-a
  1440. if round((y+o_y)/2,self.JD) != cs[1]:
  1441. test = False
  1442. except:
  1443. pass
  1444. start += k
  1445. key = {True:'是',False:'不是'}
  1446. return test,f'{self}的对称中心{key[test]}{cs}'
  1447. def Sympy_Cul(self,y_in):#利用Sympy解方程
  1448. try:
  1449. f = self.HS - float(y_in)
  1450. x_list = sympy.solve(f,self.x)
  1451. answer = []
  1452. for x in x_list:
  1453. self.Memore_x.append(x)#可能需要修复成float(x)
  1454. self.Memore_y.append(y_in)
  1455. answer.append(f'y={y_in} -> x={x}')
  1456. return answer,x_list
  1457. except:
  1458. return [],[]
  1459. def Sympy_DHS(self,x_in,dx=0.1,must=False):#可导函数求导,不可导函数逼近
  1460. DHS = self.DHS
  1461. try:
  1462. dx = abs(float(dx))
  1463. except:
  1464. dx = 0.1
  1465. try:
  1466. x_in = float(x_in)
  1467. if DHS != None and not must:#导函数法
  1468. get = DHS.evalf(subs ={self.x:x_in})
  1469. a = '导函数求值'
  1470. else:
  1471. x1 = x_in - dx/2
  1472. x2 = x_in + dx/2
  1473. y1 = self(x1)
  1474. y2 = self(x2)
  1475. dy = y2 - y1
  1476. get = dy/dx
  1477. a = '逼近法求值'
  1478. except:
  1479. return None,None
  1480. answer = f'({a})x:{x_in} -> {get}'
  1481. return answer, get
  1482. def Find(x,y,in_y):#输入x和y照除In_Y的所有对应x值
  1483. m = []
  1484. while True:
  1485. try:
  1486. num = y.index(in_y)
  1487. m.append(x[num])
  1488. del x[num]
  1489. del y[num]
  1490. except ValueError:
  1491. break
  1492. return m
  1493. class HS_lambda_Son:
  1494. def __init__(self,HS,name,view,start = -10,end = 10,kd = 0.1,JD = 2,a=1):
  1495. self.x = sympy.Symbol('x')
  1496. Name = {'a':a,'x': self.x, 'Pi': sympy.pi, 'e': sympy.E, 'log': sympy.log,
  1497. 'sin': sympy.sin, 'cos': sympy.cos, 'tan': sympy.tan,
  1498. 'cot': lambda x: 1 / sympy.tan(x), 'csc': lambda x: 1 / sympy.sin(x),
  1499. 'sec': lambda x: 1 / sympy.cos(x), 'sinh': sympy.sinh, 'cosh': sympy.cosh,
  1500. 'tanh': sympy.tanh, 'asin': sympy.asin, 'acos': sympy.acos,
  1501. 'atan': sympy.atan,'abs':abs} # 这个是函数命名域
  1502. self.HS = eval(HS.replace(' ', ''), Name)#函数解析式
  1503. self.str_HS = HS.replace(' ', '')
  1504. #函数基本信息
  1505. self.Func_Name = f'y={HS} a={a}'#这个是函数名字
  1506. self.View = view#绘制样式
  1507. #数据辨析
  1508. try:
  1509. start = float(start)
  1510. end = float(end)
  1511. if start > end:#使用float确保输入是数字,否则诱发ValueError
  1512. start, end = end, start
  1513. kd = abs(float(kd))
  1514. start = (start//kd)*kd#确保start可以恰好被kd整除
  1515. end = (end//kd+1)*kd
  1516. JD = abs(int(JD))
  1517. if JD >= 3:JD = 3
  1518. except ValueError:
  1519. start,end,kd,JD = -10,10,0.1,2#保底设置
  1520. #基本数据存储
  1521. self.JD = JD
  1522. self.start = start
  1523. self.end = end
  1524. self.kd = kd
  1525. #x和y数据存储
  1526. self.__x = []
  1527. self.__y = []
  1528. self.__ya = []
  1529. self.__fx = [[]]
  1530. self.__fy = [[]]
  1531. #最值和极值点
  1532. self.HaveDone = False#是否已经计算过xy
  1533. #函数求导
  1534. try:
  1535. self.DHS = sympy.diff(self.HS, self.x)
  1536. except:
  1537. self.DHS = None
  1538. def __call__(self,x):
  1539. return self.HS.evalf(subs={self.x:x})
  1540. def __str__(self):
  1541. return f'{self.Func_Name} {self.start,self.end,self.kd}'
  1542. def Creat_Son(self,a_start = -10,a_end = 10,a_kd = 0.1):
  1543. self.Son_List = []
  1544. while a_start <= a_end:
  1545. self.Son_List.append(HS_lambda_Son())
  1546. def Cul(self,it=float):
  1547. if self.HaveDone:
  1548. return self.__x, self.__y, self.Func_Name, self.View
  1549. # 混合存储
  1550. self.__y = []
  1551. self.__ya = []
  1552. self.__x = []
  1553. self.__xy = []
  1554. self.__fx = [[]]
  1555. self.__fy = [[]]
  1556. reason = [30]
  1557. o_y = None
  1558. p = None # 单调性 0-增,1-减
  1559. _p = 1
  1560. try:
  1561. a = int(self.start)
  1562. while a <= int(self.end): # 因为range不接受小数
  1563. p2 = 1
  1564. try:
  1565. c = 0
  1566. a_x = round(a, self.JD)
  1567. y = self(a_x)
  1568. y = it(y) # 数字处理方案
  1569. a_y = round(y, self.JD)
  1570. if o_y != None and o_y > y:
  1571. _p = 1
  1572. elif o_y != None and o_y < y:
  1573. _p = 0
  1574. elif o_y != None and o_y == y:
  1575. try:
  1576. z_x = round(a_x - 0.5 * self.kd)
  1577. z_y = self(z_x)
  1578. if z_y == o_y == y: # 真实平衡
  1579. p2 = 2
  1580. elif abs(z_y - o_y) >= 10 * self.kd or abs(z_y - y) >= 10 * self.kd:
  1581. p2 = 3
  1582. c += 5
  1583. except:
  1584. p2 = 4
  1585. c += 9
  1586. _p = 2
  1587. if o_y != None and p != _p:
  1588. if (o_y * y) < 0:
  1589. c += 5
  1590. elif abs(o_y - y) >= (10 * self.kd):
  1591. c += 5
  1592. if c >= 5 and (_p != 2 or p2 != 2):
  1593. reason.append(c)
  1594. self.__fx.append([])
  1595. self.__fy.append([])
  1596. p = _p
  1597. self.__x.append(a_x) # 四舍五入减少计算量
  1598. self.__y.append(y) # 不四舍五入
  1599. self.__ya.append(a_y) # 四舍五入(用于求解最值)
  1600. self.__xy.append(f'x:{a_x},y:{a_y}')
  1601. self.__fx[-1].append(a_x)
  1602. self.__fy[-1].append(y)
  1603. o_y = y
  1604. except:
  1605. reason.append(0)
  1606. self.__fx.append([])
  1607. self.__fy.append([])
  1608. a += self.kd
  1609. except (TypeError, IndexError, ValueError):
  1610. pass
  1611. newfx = []
  1612. newfy = []
  1613. must = False
  1614. for i in range(len(self.__fx)): # 去除只有单个的组群
  1615. if len(self.__fx[i]) <= 1: # 检测到有单个群组
  1616. q_r = reason[i] # 前原因
  1617. b_r = reason[i] # 后原因
  1618. if q_r < b_r: # 前原因小于后原因,连接到前面
  1619. try:
  1620. newfx[-1] += self.__fx[i]
  1621. newfy[-1] += self.__fy[i]
  1622. except: # 按道理不应该出现这个情况
  1623. newfx.append(self.__fx[i])
  1624. newfy.append(self.__fy[i])
  1625. else:
  1626. newfx.append(self.__fx[i])
  1627. newfy.append(self.__fy[i])
  1628. must = True
  1629. else:
  1630. if not must:
  1631. newfx.append(self.__fx[i])
  1632. newfy.append(self.__fy[i])
  1633. else:
  1634. newfx[-1] += self.__fx[i]
  1635. newfy[-1] += self.__fy[i]
  1636. must = False
  1637. self.__fx = newfx
  1638. self.__fy = newfy
  1639. self.HaveDone = True
  1640. return self.__x, self.__y, self.Func_Name, self.View
  1641. def Draw_Cul(self):
  1642. if not self.HaveDone:self.Cul()
  1643. return self.__fx,self.__fy,self.Func_Name,self.View