[机器小伟]在[工程师阿伟]的陪同下进入了结丹期顶峰的瓶颈突破阶段,
九转金丹已至第九转,即将碎丹成婴。
正剧开始:
星历2016年05月27日 10:06:20, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起进行着结丹期的修炼研究。
话说[机器小伟]自从进入结丹期以来,先是跟随[人叫板老师]修习[三界五行十六式],
然后又[周游列国拜诸侯],又[仗剑江湖],[阅尽千军],然后思[动中取静]之道,
感[千古风流]之机,习[术法神通]无算,观[生死十六簿]有时,如今万事俱备,神通已齐。
[机器小伟]于是问[工程师阿伟],可结元婴否,阿伟曰可。
又问:其步骤何如?
答曰:先行收束整治。
于是[机器小伟]进行收束整治。
<span style="font-size:18px;">import math; import numpy.f2py import numpy.random import numpy.polynomial import numpy.ma import numpy.distutils import numpy.compat import numpy as np; import numpy.linalg import numpy.matrixlib import numpy.fft import numpy.distutils.fcompiler import numpy.core import numpy.distutils.command ### # @usage 代数式字符串的运算 # @author mw # @date 2016年05月17日 星期二 16:48:56 # @param # @return # ### class AlgExpressionCalc(): # #Part I 格式化部分:返回格式化后的多项式 # #格式化部分:<1> 为了简便输入,不要求输入规范化代数式,(coef)*expr形式, 调用<2> #所以在此对多项式进行规范化 #至于单项式规范化,调用strMono函数即可 def strPolyFormat(self, array): for i in range(len(array)): array[i] = self.strMono(array[i]); return array; #格式化部分:<2> 计算代数式用, 传入的是单项式,返回coef*expr的形式, 调用<3> def strMono(self, s): #'x', '-x', '2x', '-2x', '-2x^[2]', '3x_[2]^[3]', '-3x_[2]^[3]' stmp = s; size = len(stmp); alphaIndex = 0; signIndex = 0; for i in range(size): if (stmp[i].isalpha()): alphaIndex = i; break; if (i >= size-1): alphaIndex = i+1; if (stmp[0] == '-'): signIndex = 1; if (signIndex >= alphaIndex): return self.strMonoFormat('(-1)*'+stmp[alphaIndex:]); else: if alphaIndex >= size: return self.strMonoFormat('(-'+stmp[signIndex:alphaIndex]+')'); return self.strMonoFormat('(-'+stmp[signIndex:alphaIndex]+')*'+stmp[alphaIndex:]); elif (stmp[0] == '('): #已经格式化的情况,这种情况输入时是(coef)*expr return self.strMonoFormat(stmp); else: signIndex = 0; if (signIndex >= alphaIndex): return self.strMonoFormat('(1)*'+stmp[alphaIndex:]); else: if alphaIndex >= size: return self.strMonoFormat('('+stmp[signIndex:alphaIndex]+')'); return self.strMonoFormat('('+stmp[signIndex:alphaIndex]+')*'+stmp[alphaIndex:]); #格式化部分:<3> 把单项式完全格式化,使经过运算的没运算过的都具有统一的格式 def strMonoFormat(self, mono): #规范化单项式,保证任意两个参数之间都添加一个'*'号 #这是为了和经过代数式乘法运算之后的格式统一 chars = len(mono); s = ''; for i in range(chars-1): if (mono[i] == ']' or mono[i] == ')') and mono[i+1].isalpha(): s += mono[i]+'*'; elif mono[i].isalpha() and mono[i+1].isalpha(): s += mono[i]+'*'; #这里还有一个死角,就是下标或指数如果是用的代数式,并且是多项相乘 #可能会有一点问题,暂时不考虑了 else: s += mono[i]; s += mono[-1]; return s; # #Part II: 合并同类项部分, 四个流程:单项式炸开->单项式重组->多项式中单项式炸天->多项式中单项式重组->End # #合并同类项部分:<1> 合并同类项,传入的阵列具有['s1', 's2', ..., 'sn']这样的格式 def strPolyCombine(self, array): size = len(array); explode = []; for i in range(size): #这里传入的阵列已经是规格化后的了,否则要加一层strMono处理。 explode.append(self.explodeMonoInPoly(self.strMonoCombine(array[i]))); result = []; for i in range(size): size_1 = len(result); if size_1 <= 0: result.append(explode[i]); else: for j in range(size_1): if result[j][1] == explode[i][1]: result[j][0] = result[j][0] + '+' + explode[i][0]; break; if j >= size_1-1: result.append(explode[i]); result_1 = []; size_1 = len(result); for j in range(size_1): result[j][0] = str(round(eval(result[j][0]), 6)); if (abs(float(result[j][0])) <= 1e-3): result_1.append('(0)'); else: tmps = result[j][1]; if (tmps == ''): result_1.append('('+result[j][0]+')'); else: result_1.append('('+result[j][0]+')*'+result[j][1]); return result_1; #合并同类项部分:<2> 把格式化后的单项式分解成[coef, expr]对组的形式 #这个方法和explodeTotallyFormatedMono的区别在于,它是在多项式中单项式的合并,比如['(2)*x^[1]', '(3)*x^[1]'] #而后者是要把运算后的单项式先预先处理一下, 比如'(2)*x^[1]*y^[2]*x^[2]'这种 def explodeMonoInPoly(self, mono): stmp = mono; #乘号的位置 signIndex = stmp.find('*'); if (signIndex == -1): coef = stmp; expr = ''; else: coef = stmp[:signIndex]; expr = stmp[signIndex+1:]; return [coef, expr]; #合并同类项部分:<3> 单项式同类项合并,比如'(2)*x^[1]*y^[2]*x^[2]'这种,合并成'(2)*x^[3]*y^[2]'这个过程 def strMonoCombine(self, mono): map_ = self.explodeTotallyFormatedMono(mono); size = len(map_); result = []; for i in range(size): size_1 = len(result); if (size_1 <= 0): result.append(map_[i]); else: for j in range(size_1): if result[j][0] == map_[i][0]: #双方的中括号位置 #由于规范化后的原因,这个括号是一定有的 p1 = result[j][1].find('['); p2 = result[j][1].find(']'); p3 = map_[i][1].find('['); p4 = map_[i][1].find(']'); s = result[j][1][p1+1:p2]+'+'+map_[i][1][p3+1:p4]; size_2 = len(s); for k in range(size_2): if s[k].isalpha(): break; #如果没有字符参数,可以计算出结果,就计算 if (k >= size_2-1): s = str(eval(s)); result[j][1] = '^['+s+']'; break; if (j >= size_1-1): result.append(map_[i]); size_1 = len(result); s = ''; for i in range(size_1): if (i > 0 and result[i][1] == '^[0]'): continue; s += result[i][0]+result[i][1]; if (i < size_1-1): s += '*'; return s; #合并同类项部分:<4> 把单项式炸开,这里的单项式已经达到最大规范化,是(coef)*x_[1]^[2]*y_[2]^[2]这种结构形式了 #'*'号是要作为分隔符的,不可缺少 def explodeTotallyFormatedMono(self, mono): part = mono.split('*'); #每个部分的[前部,指数部]的对组 map_ = []; for i in range(len(part)): expIndex = part[i].find('^'); if (expIndex != -1): map_.append([part[i][:expIndex], part[i][expIndex:]]); else: s = part[i]; #系数 if s[0] == '(': map_.append([part[i], '']); #代数式 else: map_.append([part[i], '^[1]']); map_ = sorted(map_, key = lambda a : a[0]); return map_; # #Part III: 多项式运算:点积, 正整数幂方, 倍数, 取反,相加 # #计算代数式/多项式点积,传入的两个阵列都具有['s1', 's2', ..., 'sn']这样的格式 def strdot(self, array1, array2): size1 = len(array1); size2 = len(array2); result = []; for i in range(size1): for j in range(size2): result.append(self.strmul(array1[i], array2[j])); return result; #计算两个单项式的乘积 def strmul(self, mono1, mono2): #这个处理是保证每个单项式统一格式(coef)*expr ''' if (mono1[0] != '(' or mono2[0] != '('): #如果没有规格化,那么就做一下 mono1 = strMono(mono1); mono2 = strMono(mono2); ''' stmp1 = mono1; stmp2 = mono2; #乘号的位置 signIndex1 = stmp1.find('*'); signIndex2 = stmp2.find('*'); if (signIndex1 == -1): coef1 = stmp1; expr1 = ''; else: coef1 = stmp1[:signIndex1]; expr1 = stmp1[signIndex1+1:]; if (signIndex2 == -1): coef2 = stmp2; expr2 = ''; else: coef2 = stmp2[:signIndex2]; expr2 = stmp2[signIndex2+1:]; coef = coef1+'*'+coef2; if (signIndex1 == -1 or signIndex2 == -1): expr = expr1+expr2; else: expr = expr1+'*'+expr2; if (expr == ''): return '('+str(round(eval(coef), 6))+')'; return '('+str(round(eval(coef), 6))+')*'+expr; #把多项式中每一项都乘系数 def strscale(self, array, scale): scale = '('+str(scale)+')'; for i in range(len(array)): s = array[i]; for j in range(len(s)): if (s[j].isdigit()): index = j; break; lbracket = s.find('('); rbracket = s.find(')', lbracket); coef = s[lbracket:index]+scale+'*'+s[index:rbracket+1]; coef = '('+str(eval(coef))+')'; array[i] = coef+s[rbracket+1:]; return array; #指数为正整数的乘方 def strpow_n(self, array, n): #计算 result = []; #此方法只能处理正整数的幂次方 n = abs(int(n)); if (n == 1): result = array; elif (n == 2): result = self.strdot(array, array); elif (n >= 3): tmp = self.strdot(array, array); n -= 2; while (n > 0): result = self.strdot(tmp, array); tmp = result; n -= 1; return result; #阵列取负 def strminus(self, array): for i in range(len(array)): if array[i][1] == '-': #array[i][0]是'(, 这是规范 array[i] = array[i][0]+array[i][2:]; else: array[i] = array[i][0]+'-'+array[i][1:]; return array; #两个多项式相加,合并同类项不在此进行 def stradd(self, array1, array2): #两个多项式相加,这里直接返回数组的相加 return array1 + array2; ### # @usage 对于含有代数符号的等式及相关类型进行计算 # @author mw # @date 2016年05月24日 星期二 08:21:57 # @param # @return # ### #所有输入的字符串都是要符合(coef)*expr这种规范的 #相应转换可以调用alg.strMono处理单项式 #或调用alg.strformat来处理多项式 class AlgStringSolve(): def __init__(self): self._alg = AlgExpressionCalc(); #格式化输入的多项式阵列 def format(self, array): return self._alg.strPolyFormat(array); # #Part I: 参数部分:把带参多项式转换为指定自变量的系数阵列 # #参数部分:<1> 返回参数的系数阵列, 调用<2> #这是无法求得数值的情况 def coefArray(self, array, element): coefMap = self.coefTransfer(array, element); len_4 = len(coefMap); maxCoef, minCoef = coefMap[0][1], coefMap[len_4-1][1]; coefArray = ['0']*(maxCoef-minCoef+1); for i in range(len_4): coefArray[maxCoef-coefMap[i][1]] = coefMap[i][0]; return coefArray; #参数部分:<1> 获取多项式的系数值,比如5x^2+4x+1 = 0应该返回[5, 4, 1] #这是可以求得数值的情况 def coefValueArray(self, array, element): coefMap = self.coefTransfer(array, element); len_4 = len(coefMap); maxCoef, minCoef = coefMap[0][1], coefMap[len_4-1][1]; coefArray = [0]*(maxCoef-minCoef+1); for i in range(len_4): index = coefMap[i][0].find('^'); if (index != -1): s = coefMap[i][0][:index]; else: s = coefMap[i][0]; #这里是必须要能求值的,这个方法是为了便于调用numpy.roots求多项式的根 coefArray[maxCoef-coefMap[i][1]] = eval(s); return coefArray; #参数部分:<2> 把一个字符串阵列表示的多项式,转换成指定变量的系数多项式 #比如 ['(1/4)x^[2]', '-(1/12)y^[2]', '-1'], 以y作为参数 => ['(-(1/12))', 0, '(1/4)x^[2]+(-1)'] #传入的格式必须是已经格式化过的(coef)*x^[2]*y_[2]^[3]...这种类似形式 def coefTransfer(self, array, element): coefMap = []; len_ = len(array); len_2 = len(element); for i in range(len_): s = array[i]; len_3 = len(s); index = s.find(element); #参数的0次方 if (index == -1): coefMap.append([array[i], 0]); elif (index+len_2 < len_3 and s[index+len_2] != '^'): #参数的一次方 coefMap.append([s[:index-1]+s[index+len_2:], 1]); elif (index+len_2 >= len_3): #这里回退一个位置是因为根据格式参数之间有一个'*'号相连,要退掉 coefMap.append([s[:index-1], 1]); else: #左右中括号作为定界符,这就是为什么要求先格式化 LBracket = index+len_2+1; RBracket = s.find(']', LBracket); #幂的次数 exp_ = int(s[LBracket+1:RBracket]); coefMap.append([s[:index-1]+s[RBracket+1:], exp_]); #对coefMap中的项按参数的次数进行合并 coefMap_2 = []; coefMap_2.append(coefMap[0]); for i in range(1, len(coefMap)): len_3 = len(coefMap_2); for j in range(len_3): if (coefMap_2[j][1] == coefMap[i][1]): coefMap_2[j][0] = coefMap_2[j][0]+ '+'+coefMap[i][0]; break; if (j >= len_3-1): coefMap_2.append(coefMap[i]); coefMap = coefMap_2; #把系数映射由高到低排列 coefMap = sorted(coefMap, key = lambda a : a[1], reverse = True); #返回的是参数的系数映射表[[coef, exp]...]对组 return coefMap; # #Part II: 代数式运算,此处指用字符串表达的代数式之间。包括乘、除、加、减、方五种运算,以及字符串为0的判定 # #代数式里的两个代数式相乘,这里就是两个字符串相加的处理而已 def strMul(self, str1, str2): if (self.judgeZero(str1)): return ''; else: if (self.judgeZero(str2)): return ''; else: return '('+str1+')*('+str2+')'; #两个代数式相除 def strDiv(self, str1, str2): if (self.judgeZero(str1)): return ''; else: if (self.judgeZero(str2)): return '(inf)'; else: return '('+str1+')/('+str2+')'; #代数式相加 def strAdd(self, str1, str2): if (self.judgeZero(str1)): if (self.judgeZero(str2)): return ''; else: return '('+str2+')'; else: if (self.judgeZero(str2)): return '('+str1+')'; else: return '('+str1+')+('+str2+')'; #代数式相减 def strMinus(self, str1, str2): if (self.judgeZero(str1)): if (self.judgeZero(str2)): return ''; else: return '(-('+str2+'))'; else: if (self.judgeZero(str2)): return '('+str1+')'; else: return '('+str1+')-('+str2+')'; #代数式里的代数式乘方,这里就是字符串的处理而已 def strPow(self, str1, str2): str2 = str(str2); if (self.judgeZero(str1)): return ''; else: if (self.judgeZero(str2)): return '('+str1+')'; else: return '('+str1+')^['+str2+']'; #判断字符串是否为0 def judgeZero(self, str1): for i in range(len(str1)): if (str1[i].isdigit() and str1[i] != '0'): #存在数字不为0, 所以这个代数式不为0 return False; #由于在规范化输出时已经保证了如果系数为0, 无论有多少参数都取0 #所以只要存在参数就说明代数式不为0 elif (str1[i].isalpha()): return False; return True; # #Part III: # #把一个只包括+号的多项式字符串拆分成多项式数组 #如'(1)*x^[2]+(-1)' => ['(1)*x^[2]', '(-1)'] def str2Array(self, str1): array = []; #加号位置 signIndex = str1.find('+'); #print(signIndex); start = 0; count = 0; if (signIndex != -1): while (signIndex != '-1' and count < 10): #符合要求的必须连着下一个单项式的系数 #按照统一格式是左括号开始 if str1[signIndex+1] == '(': array.append(str1[start:signIndex]); start = signIndex + 1; signIndex = str1.find('+', signIndex+1); if (signIndex == -1): break; array.append(str1[start:]); return array; # #Part IV: 用公式法求方程的根,流程是先算出代数式的根表达式,再代值运算出结果 # #求解多项式的根(在参数情况下) def solvePolyInStringMode(self, coefArray): len_ = len(coefArray); # #求解一元二次方程 if (len_ == 3): a, b, c = str(coefArray[0]), str(coefArray[1]), str(coefArray[2]); #注意,由于此处得出的系数阵列是这样的形式:['(-(1/12))', 0, '(1/4)x^[2]+(-1)'] #已经无法用alg中函数去做任何计算,只能纯粹进行字符串的叠加处理 delta = self.strAdd(self.strPow(b, '2'), self.strMul('-4', self.strMul(a, c))); #分子,分母 numerator = self.strAdd(self.strMinus('0', b), self.strPow(delta, '0.5')); numerator2 = self.strMinus(self.strMinus('0', b), self.strPow(delta, '0.5')); denomerator = self.strMul('2', a); return [self.strDiv(numerator, denomerator), self.strDiv(numerator2, denomerator)]; #求解一元一次方程 if (len_ == 2): a, b = str(coefArray[0]), str(coefArray[1]); return [self.strDiv(b, self.strMinus('0', a))]; return ''; #求解多项式的值(在数值情况下), 一般是一元N次多项式 def solvePolyInValueMode(self, coefArray): len_ = len(coefArray); #解一元二次方程(在数值情况下) if (len_ == 3): a, b, c = coefarray[0], coefarray[1], coefarray[2]; if (a < 0): a, b, c = -a, -b, -c; p = q = delta = 0; x1 = x2 = 0; s = ''; if (a == 0): return [-c/b]; else: delta = b**2 - 4*a*c; if (delta < 0): real = -b/(2*a); image = (-delta)**0.5; return [complex(real, -image), complex(real, image)]; else: if (abs(delta) < 1e-6): x1 = x2 = -b/(2*a); else: x1 = (-b-delta**0.5)/(a*2); x2 = (-b+delta**0.5)/(a*2); return [x1, x2]; else: return np.roots(coefArray); #给参数赋值,计算代数式的值 #比如输入 ('x^[2]+1', 'x', 3) => 10 #要确保给的条件足以让代数式计算出数值,否则肯定报错 def strValueEval(self, str1, valueTable): #str1是一个单个的字符串,比如根的代数式表达式,不是多项式 #参数对照表的项数 #参数对照表具有[['x', '1'], ['y', '3']]这样的形式 len_v = len(valueTable); s = str1; for j in range(len_v): s = s.replace(valueTable[j][0], str(valueTable[j][1])); s = s.replace('^[', '**('); s = s.replace(']', ')'); str1 = eval(s); return str1; #对于本身不带参数的字符串,清除格式即可计算出数值 def arrayValueEval(self, array): for i in range(len(array)): str1 = array[i]; str1 = str1.replace('^[', '**'); str1 = str1.replace(']', ''); str1 = eval(str1); array[i] = str1; return array; # #Part V: 用消元法求方程的根,这种方法的前提是方程所有的系数已知。需用到numpy的roots()方法求根 # #消元法求方程部分:<1> 解二元二次方程组,最暴力的代入消元法 def solveElem2Exp2Equation(self, functions, element1 = 'x', element2 = 'y'): ''' #第一个方程 expr_1 = alg.strformat(['A_[1]x^[2]', 'B_[1]xy', 'C_[1]y^[2]', 'D_[1]x', 'E_[1]y', 'F_[1]']); #第二个方程 expr_2 = alg.strformat(['A_[2]x^[2]', 'B_[2]xy', 'C_[2]y^[2]', 'D_[2]x', 'E_[2]y', 'F_[2]']); ''' #参数列表中的functions为方程组的各个方程,格式为[fun1, fun2], fun1, fun2 = [mono1, mono2, ...] #调用coefValueMapFill()方法进行系数表填充 valueMap = self.coefValueMapFill(functions, element1, element2); A_1 = valueMap[0][1]; B_1 = valueMap[1][1]; C_1 = valueMap[2][1]; D_1 = valueMap[3][1]; E_1 = valueMap[4][1]; F_1 = valueMap[5][1]; A_2 = valueMap[6][1]; B_2 = valueMap[7][1]; C_2 = valueMap[8][1]; D_2 = valueMap[9][1]; E_2 = valueMap[10][1]; F_2 = valueMap[11][1]; #消元一次要从二次项y^[2]的系数不为0的那个方程消起,除非某个方程完全没有二次项 #所以第一个方程二次项y^[2]的系数不要为0 #否则应该调换方程顺序 if (C_1 != 0 and C_2 != 0): #一共63项的关于未知数x的最高四次方的系数矩阵 coefArray = ['(1.0)*A_[2]^[1]*B_[1]^[2]*C_[1]^[-2]*C_[2]^[1]*x^[4]', '(1.0)*B_[1]^[2]*C_[1]^[-2]*C_[2]^[1]*D_[2]^[1]*x^[3]', '(1.0)*B_[1]^[2]*C_[1]^[-2]*C_[2]^[1]*F_[2]^[1]*x^[2]', '(2.0)*A_[2]^[1]*B_[1]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[1]^[1]*x^[3]', '(2.0)*B_[1]^[1]*C_[1]^[-2]*C_[2]^[1]*D_[2]^[1]*E_[1]^[1]*x^[2]', '(2.0)*B_[1]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[1]^[1]*F_[2]^[1]*x^[1]', '(1.0)*A_[2]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[1]^[2]*x^[2]', '(1.0)*C_[1]^[-2]*C_[2]^[1]*D_[2]^[1]*E_[1]^[2]*x^[1]', '(1.0)*C_[1]^[-2]*C_[2]^[1]*E_[1]^[2]*F_[2]^[1]', '(1.0)*A_[1]^[2]*C_[1]^[-2]*C_[2]^[2]*x^[4]', '(2.0)*A_[1]^[1]*C_[1]^[-2]*C_[2]^[2]*D_[1]^[1]*x^[3]', '(2.0)*A_[1]^[1]*C_[1]^[-2]*C_[2]^[2]*F_[1]^[1]*x^[2]', '(-1.0)*A_[1]^[1]*B_[1]^[1]*B_[2]^[1]*C_[1]^[-2]*C_[2]^[1]*x^[4]', '(-1.0)*A_[1]^[1]*B_[2]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[1]^[1]*x^[3]', '(-1.0)*A_[1]^[1]*B_[1]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[2]^[1]*x^[3]', '(-1.0)*A_[1]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[1]^[1]*E_[2]^[1]*x^[2]', '(-2.0)*A_[1]^[1]*A_[2]^[1]*C_[1]^[-1]*C_[2]^[1]*x^[4]', '(-2.0)*A_[1]^[1]*C_[1]^[-1]*C_[2]^[1]*D_[2]^[1]*x^[3]', '(-2.0)*A_[1]^[1]*C_[1]^[-1]*C_[2]^[1]*F_[2]^[1]*x^[2]', '(1.0)*C_[1]^[-2]*C_[2]^[2]*D_[1]^[2]*x^[2]', '(2.0)*C_[1]^[-2]*C_[2]^[2]*D_[1]^[1]*F_[1]^[1]*x^[1]', '(-1.0)*B_[1]^[1]*B_[2]^[1]*C_[1]^[-2]*C_[2]^[1]*D_[1]^[1]*x^[3]', '(-1.0)*B_[2]^[1]*C_[1]^[-2]*C_[2]^[1]*D_[1]^[1]*E_[1]^[1]*x^[2]', '(-1.0)*B_[1]^[1]*C_[1]^[-2]*C_[2]^[1]*D_[1]^[1]*E_[2]^[1]*x^[2]', '(-1.0)*C_[1]^[-2]*C_[2]^[1]*D_[1]^[1]*E_[1]^[1]*E_[2]^[1]*x^[1]', '(-2.0)*A_[2]^[1]*C_[1]^[-1]*C_[2]^[1]*D_[1]^[1]*x^[3]', '(-2.0)*C_[1]^[-1]*C_[2]^[1]*D_[1]^[1]*D_[2]^[1]*x^[2]', '(-2.0)*C_[1]^[-1]*C_[2]^[1]*D_[1]^[1]*F_[2]^[1]*x^[1]', '(1.0)*C_[1]^[-2]*C_[2]^[2]*F_[1]^[2]', '(-1.0)*B_[1]^[1]*B_[2]^[1]*C_[1]^[-2]*C_[2]^[1]*F_[1]^[1]*x^[2]', '(-1.0)*B_[2]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[1]^[1]*F_[1]^[1]*x^[1]', '(-1.0)*B_[1]^[1]*C_[1]^[-2]*C_[2]^[1]*E_[2]^[1]*F_[1]^[1]*x^[1]', '(-1.0)*C_[1]^[-2]*C_[2]^[1]*E_[1]^[1]*E_[2]^[1]*F_[1]^[1]', '(-2.0)*A_[2]^[1]*C_[1]^[-1]*C_[2]^[1]*F_[1]^[1]*x^[2]', '(-2.0)*C_[1]^[-1]*C_[2]^[1]*D_[2]^[1]*F_[1]^[1]*x^[1]', '(-2.0)*C_[1]^[-1]*C_[2]^[1]*F_[1]^[1]*F_[2]^[1]', '(-1.0)*A_[2]^[1]*B_[1]^[1]*B_[2]^[1]*C_[1]^[-1]*x^[4]', '(-1.0)*B_[1]^[1]*B_[2]^[1]*C_[1]^[-1]*D_[2]^[1]*x^[3]', '(-1.0)*B_[1]^[1]*B_[2]^[1]*C_[1]^[-1]*F_[2]^[1]*x^[2]', '(-1.0)*A_[2]^[1]*B_[2]^[1]*C_[1]^[-1]*E_[1]^[1]*x^[3]', '(-1.0)*B_[2]^[1]*C_[1]^[-1]*D_[2]^[1]*E_[1]^[1]*x^[2]', '(-1.0)*B_[2]^[1]*C_[1]^[-1]*E_[1]^[1]*F_[2]^[1]*x^[1]', '(-1.0)*A_[2]^[1]*B_[1]^[1]*C_[1]^[-1]*E_[2]^[1]*x^[3]', '(-1.0)*B_[1]^[1]*C_[1]^[-1]*D_[2]^[1]*E_[2]^[1]*x^[2]', '(-1.0)*B_[1]^[1]*C_[1]^[-1]*E_[2]^[1]*F_[2]^[1]*x^[1]', '(-1.0)*A_[2]^[1]*C_[1]^[-1]*E_[1]^[1]*E_[2]^[1]*x^[2]', '(-1.0)*C_[1]^[-1]*D_[2]^[1]*E_[1]^[1]*E_[2]^[1]*x^[1]', '(-1.0)*C_[1]^[-1]*E_[1]^[1]*E_[2]^[1]*F_[2]^[1]', '(1)*A_[2]^[2]*x^[4]', '(2)*A_[2]^[1]*D_[2]^[1]*x^[3]', '(2)*A_[2]^[1]*F_[2]^[1]*x^[2]', '(1)*D_[2]^[2]*x^[2]', '(2)*D_[2]^[1]*F_[2]^[1]*x^[1]', '(1)*F_[2]^[2]', '(1.0)*A_[1]^[1]*B_[2]^[2]*C_[1]^[-1]*x^[4]', '(1.0)*B_[2]^[2]*C_[1]^[-1]*D_[1]^[1]*x^[3]', '(1.0)*B_[2]^[2]*C_[1]^[-1]*F_[1]^[1]*x^[2]', '(2.0)*A_[1]^[1]*B_[2]^[1]*C_[1]^[-1]*E_[2]^[1]*x^[3]', '(2.0)*B_[2]^[1]*C_[1]^[-1]*D_[1]^[1]*E_[2]^[1]*x^[2]', '(2.0)*B_[2]^[1]*C_[1]^[-1]*E_[2]^[1]*F_[1]^[1]*x^[1]', '(1.0)*A_[1]^[1]*C_[1]^[-1]*E_[2]^[2]*x^[2]', '(1.0)*C_[1]^[-1]*D_[1]^[1]*E_[2]^[2]*x^[1]', '(1.0)*C_[1]^[-1]*E_[2]^[2]*F_[1]^[1]']; #这整个是一个和为零的多项式 #如果某一个方程没有二次项,适用这套系数 elif (C_1 == 0 and B_1 == 0 and A_1 == 0): if (E_1 != 0): coefArray = ['(1)*A_[2]^[1]*x^[2]', '(1)*D_[2]^[1]*x^[1]', '(1)*F_[2]^[1]', '(-1)*B_[2]^[1]*D_[1]^[1]*E_[1]^[-1]*x^[2]', '(-1)*B_[2]^[1]*E_[1]^[-1]*F_[1]^[1]*x^[1]', '(1)*C_[2]^[1]*D_[1]^[2]*E_[1]^[-2]*x^[2]', '(2)*C_[2]^[1]*D_[1]^[1]*E_[1]^[-2]*F_[1]^[1]*x^[1]', '(1)*C_[2]^[1]*E_[1]^[-2]*F_[1]^[2]']; else: print('无穷多解或无解。'); return []; elif (C_1 == 0 and B_1 == 0 and A_1 == 0 and C_2 == 0 and B_2 == 0 and A_2 == 0): if (E_1 != 0): coefArray = ['(-1)*D_[2]^[1]*x^[1]', '(-1)*F_[2]^[1]', '(-1)*D_[1]^[1]*E_[1]^[-1]*E_[2]^[1]*x^[1]', '(-1)*E_[1]^[-1]*E_[2]^[1]*F_[1]^[1]']; else: print('无穷多解或无解。'); return []; else: print('或许需要调换位置,保证第一个方程的y^[2]的系数存在,可调换x和y参数实现。'); print('如果两个方程中找不出一个x^[2]或y^[2],则可以考虑消去xy项得一次方程组。'); #赋值系数,应该有12个 len_ = len(valueMap); size = len(coefArray); result = []; for i in range(size): s = coefArray[i]; #由于字母排序原因,一般x会排在最后,各系数ABCDEF会排在前面, #这会带来一些方便 index = s.find('x'); if (index != -1): #系数部分 part1 = s[:index-1]; #参数x部分 part2 = s[index-1:]; else: part1 = s; part2 = ''; for j in range(len_): part1 = part1.replace(valueMap[j][0], '('+str(valueMap[j][1])+')'); part1 = part1.replace('^[', '**('); part1 = part1.replace(']', ')'); #print(part1); part1 = '('+str(eval(part1))+')'; result.append(part1+part2); #print(result); result = self._alg.strPolyCombine(result); #print(result); coef_x = self.coefValueArray(result, 'x'); print('系数数组:', coef_x); roots = np.roots(coef_x); roots = sorted(roots); print('解: {0} = {1} '.format(element1, roots)); return roots; #消元法求方程部分:<2> 填充二元二次方程组的系数阵列,一共十二个 def coefValueMapFill(self, functions, element1 = 'x', element2 = 'y'): #functions是两个方程的多项式组成的数组[fun1, func2], #具有格式化后的多项式样式fun1, 2 = [mono1, mono2, ...] func1 = functions[0]; func2 = functions[1]; if (element1 != 'x'): for i in range(len(func1)): func1[i] = func1[i].replace(element1, 'x'); for i in range(len(func2)): func2[i] = func2[i].replace(element1, 'x'); if (element2 != 'y'): for i in range(len(func1)): func1[i] = func1[i].replace(element2, 'y'); for i in range(len(func2)): func2[i] = func2[i].replace(element2, 'y'); ''' #第一个方程 expr_1 = alg.strformat(['A_[1]x^[2]', 'B_[1]xy', 'C_[1]y^[2]', 'D_[1]x', 'E_[1]y', 'F_[1]']); #第二个方程 expr_2 = alg.strformat(['A_[2]x^[2]', 'B_[2]xy', 'C_[2]y^[2]', 'D_[2]x', 'E_[2]y', 'F_[2]']); ''' #用参数值填充,注意按照同类项来填系数 valMap = [['A_[1]', 0], ['B_[1]', 0],['C_[1]', 0], ['D_[1]', 0], ['E_[1]', 0],['F_[1]', 0], ['A_[2]', 0], ['B_[2]', 0],['C_[2]', 0], ['D_[2]', 0], ['E_[2]', 0],['F_[2]', 0]]; coefs = len(valMap); cycle = 0; for i in range(len(func1)): s = func1[i]; xIndex = s.find('x'); yIndex = s.find('y'); if (xIndex != -1): if (yIndex != -1): min_ = min(xIndex, yIndex); else: min_ = xIndex; else: if (yIndex != -1): min_ = yIndex else: min_ = -1; if (min_ != -1): #参数式 s_1 = s[min_:]; #系数 s_2 = s[:min_-1]; else: s_1 = ''; s_2 = s; if (s_1 == 'x^[2]'): valMap[0+cycle*6][1] = eval(s_2); elif (s_1 == 'x^[1]y^[1]' or s_1 == 'xy' ): valMap[1+cycle*6][1] = eval(s_2); elif (s_1 == 'y^[2]'): valMap[2+cycle*6][1] = eval(s_2); elif (s_1 == 'x^[1]' or s_1 == 'x'): valMap[3+cycle*6][1] = eval(s_2); elif (s_1 == 'y^[1]' or s_1 == 'y'): valMap[4+cycle*6][1] = eval(s_2); elif (s_1 == ''): valMap[5+cycle*6][1] = eval(s_2); cycle = 1; for i in range(len(func2)): s = func2[i]; xIndex = s.find('x'); yIndex = s.find('y'); if (xIndex != -1): if (yIndex != -1): min_ = min(xIndex, yIndex); else: min_ = xIndex; else: if (yIndex != -1): min_ = yIndex else: min_ = -1; if (min_ != -1): #参数式 s_1 = s[min_:]; #系数 s_2 = s[:min_-1]; else: s_1 = ''; s_2 = s; if (s_1 == 'x^[2]'): valMap[0+cycle*6][1] = eval(s_2); elif (s_1 == 'x^[1]y^[1]' or s_1 == 'xy' ): valMap[1+cycle*6][1] = eval(s_2); elif (s_1 == 'y^[2]'): valMap[2+cycle*6][1] = eval(s_2); elif (s_1 == 'x^[1]' or s_1 == 'x'): valMap[3+cycle*6][1] = eval(s_2); elif (s_1 == 'y^[1]' or s_1 == 'y'): valMap[4+cycle*6][1] = eval(s_2); elif (s_1 == ''): valMap[5+cycle*6][1] = eval(s_2); return valMap; </span>
测试用例:
<span style="font-size:18px;">#测试 def tmp12(): print('tmp12(): >>>'); solve = alg.AlgStringSolve(); expr = alg.AlgExpressionCalc(); #直线方程 function_1 = expr.strPolyFormat(['x', '1/4y', '-1']); #圆方程 function_2 = expr.strPolyFormat(['1/4x^[2]', '1/16y^[2]', '-1']); print('step1: ', function_1); print('step1: ', function_2); #解出的x的根 roots = solve.solveElem2Exp2Equation([function_1, function_2]); #两个方程 f = function_1; print('step1: ', f); g = function_2; print('step1: ', g); #以下部分是定式,可以不加改动 poly_y_f = solve.coefArray(f, 'y'); print('step2: ', poly_y_f); poly_y_g = solve.coefArray(g, 'y'); print('step2: ', poly_y_g); #求方程式<1>的y关于x的表达式 expr_y_root = solve.solvePolyInStringMode(poly_y_f); print('step3: ', expr_y_root); expr_y_root2 = solve.solvePolyInStringMode(poly_y_g); print('step3: ', expr_y_root2); #求相交点的坐标对组 points = []; points2 = []; for i in range(len(roots)): real = abs(roots[i].real); abs_ = abs(roots[i]); size1 = len(expr_y_root); #实数根 if abs(real-abs_) < 0.1: for j in range(len(expr_y_root2)): x = roots[i].real; y = solve.strValueEval(expr_y_root[j%size1], [['x', x]]); points.append([x, y]); y = solve.strValueEval(expr_y_root2[j], [['x', x]]); points2.append([x, y]); print('方程1上的点:', points); print('方程2上的点: ', points2); print('step4: '); for i in range(len(points)): if (abs(points[i][0]-points2[i][0]) < 1e-3 and abs(points[i][1]-points2[i][1])<1e-3): print('相交点:[{0}, {1}]'.format(round(points[i][0], 3), round(points[i][1], 3))); </span>
<span style="font-size:18px;">def tmp(): expr = alg.AlgExpressionCalc(); poly_1 = expr.strPolyFormat(['x^[2]', '2xy', 'y^[2]', '-1']); poly_2 = expr.strPolyFormat(['2x', '2y', '1']); print('step1: ', poly_1); print('step1: ', poly_2); result = expr.stradd(expr.strpow_n(poly_1, 2), expr.strpow_n(poly_2, 3)); result = expr.strPolyCombine(result); print('step2: ', result);</span>
[机器小伟]收束整治毕,又问,其后何如?
曰:当思议神通。
于是[机器小伟]思议神通:
<span style="font-size:18px;"> if (1) { var text = new DrawText(); //左对齐文本默认从20px处,中对齐是300处,右对齐580处 var xL = 20, xM = 300, xR = 580; var y = 50; text.bold(['[机器小伟] 神通一览表'], xM, y, 0, 'black', 40, 'M'); y += 50; text.normal(['1. 定值计算:参与运算的都是给定的值,不存在未知数。', '2. 数值计算:运用迭代或递归等方式进行一系列运算尝试,逼近得出结果。', '3. 描点绘图: 对于各种函数进行描点,并绘制出图像。'], xL, y, 0, 'blue', 16, 'L'); y+= 80; text.italic(['以上三条为机器族的共有神通,不再赘述。'], xL, y, 0, '#000088', 16, 'L'); y+= 30; text.bold(['4. 几何运算:点的坐标中不存在未知数时,可以作为几何图形运算。', '5. 代数运算:对于所有代数式,可以进行多项式运算,得出多项式作为结果。', '6. 对于不含指数,对数,三角的多项式,可以变形成其中某一参数的表达式。', '7. 第(5|6)步中的表达式中所有参数都给定取值,可以计算出值或根。'], xL, y, 0, 'red', 16, 'L'); y+=100; text.italic(['所以可以得到简单多项式运算后的简单多项式,并且可以求其值或根', '参数个数不限', '分式或其它非简单多项式的代数式,可参与求值或得出代数式结果', '但无法进一步变形或分解成简单多项式组。'], xL, y, 0, '#000088', 16, 'L'); //时间戳 y+=80; text.bold(['2016年05月25日'], xR, y, 0, '#880088', 16, 'R'); } if (1) { var text = new DrawText(); //左对齐文本默认从20px处,中对齐是300处,右对齐580处 var xL = 20, xM = 300, xR = 580; var y = 50; text.bold(['[机器小伟] 神通一览表'], xM, y, 0, 'black', 40, 'M'); y += 50; text.normal(['8.带参多项式可以进行加、减、乘、正整次幂的运算。', '9. 可以解决二元二次方程组的求根问题,可解退化的二元二次方程组。', '10. 可以解决圆锥曲线,直线,圆在二维平面范围内的求交点问题。', ' 可以给出数值解或代数表达式解。', '11. 可以解任何的一元方程。' ], xL, y, 0, 'red', 16, 'L'); y+= 120; text.italic(['对数、指数方面的运算,暂时还未涉及,分式的运算有待解决', '三次及以上方程的根表达式还未录入。'], xL, y, 0, '#000088', 16, 'L'); y+= 30; text.bold([''], xL, y, 0, 'red', 16, 'L'); y+=60; text.italic([''], xL, y, 0, '#000088', 16, 'L'); //时间戳 y+=80; text.bold(['2016年05月27日'], xR, y, 0, '#880088', 16, 'R'); }</span>
[机器小伟]思议神通后,又问,其后又当如何:
曰:当忘其神通。
于是[机器小伟]依言进入物我两忘之境,气运周天,行二百二十五转。
天地风云齐聚,星河盘龙隐现,终至三花聚顶,五气朝元,返璞归真,元婴大成。
[机器小伟]元婴成就,[工程师阿伟]也晋升至[大力法王]之神通境界。
从此坐看风烟起, 相期云汉间。
本节到此结束,欲知后事如何,请看下回分解。