多項式の解の推定のためのプログラムをpythonで作る。
引き続き多項式の解を求めるためのプログラムを書き続けていました。ある程度の数の解を求めるためのプログラムができたので、書き出しておきます。
import numpy as np
import scipy.linalg as linalg
import random
import math
def warizan(keisuu,bunbo,krank,brank):
p=keisuu
b=bunbo
jisuuk=krank
jisuub=brank
if krank<brank:
ci=[0]
ama=keisuu
else:
ci=np.array([0.0]*(jisuuk-jisuub+1),dtype=complex)
ama=np.array([0.0]*(jisuub),dtype=complex)
#print(jisuuk-jisuub)
for i in range(jisuuk-jisuub+1):
ci[i]=p[i]/b[0]
#print(ci,ama,b,jisuuk,jisuub)
for i in range(jisuub):
ama[i]=p[i+jisuuk-jisuub+1]
for i in range(1,jisuuk+1):
for j in range(1,jisuub+1):
if i>=j :
if i<=jisuuk-jisuub:
ci[i]-=ci[i-j]*b[j]/b[0]
elif i>jisuuk-jisuub and i-j<jisuuk-jisuub+1:
ama[i-jisuuk+jisuub-1]-=ci[i-j]*b[j]
return ci,ama,jisuuk-jisuub
def kakezan(keisuu1,keisuu2):
kakutei=[0]*(len(keisuu1)+len(keisuu2)-1)
for i in range(len(keisuu1)):
for j in range(len(keisuu2)):
kakutei[i+j]+=keisuu1[i]*keisuu2[j]
return kakutei
def dainyu(xval,keisuu):
x=xval
pkei=keisuu
rui=1
kekka=0
for i in range(len(pkei)):
kekka+=pkei[len(pkei)-i-1]*rui
rui*=xval
return kekka
class ButterEnzan():
def __init__(self,length):
self.value=length
self.keta=length
self.log2bord=math.ceil(np.log2(length))
self.yousosu=2**(self.log2bord-1)+1
self.bangou=[0]*(self.yousosu*2-1)
self.ruix=[0]*(self.log2bord+1)
self.nii=[2**i-1 for i in range(self.log2bord+1)]
for i in range(self.log2bord):
self.bangou[self.nii[i]]=2**(self.log2bord-i-1)
for j in range(self.nii[i]):
self.bangou[j+self.nii[i]+1]=self.bangou[self.nii[i]]+self.bangou[j]
self.bangou=np.array([int(self.bangou[i])for i in range(len(self.bangou))])
def dainyu2(self,xval,keisuu0):#maxlength<=self.keta
x=xval
pkei=keisuu0
maxketa=len(keisuu0)-1
maxlog2=math.ceil(np.log2(maxketa))
if maxketa>self.keta:
print('error')
ruilist=[0]*self.yousosu
kekka=pkei[maxketa]
for i in range(self.log2bord):
k=self.nii[i]
ruilist[k]=x**(2**(self.log2bord-i-1))
kekka+=pkei[maxketa-self.bangou[k]]*ruilist[k]
for j in range(k):
if i<self.log2bord-1 and self.bangou[k+1+j]<=maxketa:
ruilist[k+1+j]=ruilist[k]*ruilist[j]
kekka+=pkei[maxketa-self.bangou[k+1+j]]*ruilist[k+1+j]
elif self.bangou[k+1+j]<=maxketa and i==self.log2bord-1:
kekka+=pkei[maxketa-self.bangou[k+1+j]]*ruilist[k]*ruilist[j]
return kekka
def bibun2(self,xval,keisuu0):
x=xval
pkei=keisuu0
maxketa=len(keisuu0)-1
maxlog2=math.ceil(np.log2(maxketa))
if maxketa>self.keta:
print('error')
ruilist=[0]*self.yousosu
kekka=pkei[maxketa-1]
#print(self.log2bord,maxlog2)
for i in range(self.log2bord):
k=self.nii[i]
#if self.bangou[k]<=maxketa-1:
ruilist[k]=x**(2**(self.log2bord-i-1))
kekka+=pkei[maxketa-self.bangou[k]-1]*ruilist[k]*(self.bangou[k]+1)
for j in range(k):
if i<self.log2bord-1 and self.bangou[k+1+j]<=maxketa-1:
ruilist[k+1+j]=ruilist[k]*ruilist[j]
kekka+=pkei[maxketa-self.bangou[k+1+j]-1]*ruilist[k+1+j]*(self.bangou[k+1+j]+1)
elif self.bangou[k+1+j]<=maxketa-1 and i==self.log2bord-1:
kekka+=pkei[maxketa-self.bangou[k+1+j]-1]*ruilist[k]*ruilist[j] *(self.bangou[k+1+j]+1)
return kekka
def bibun(xval,keisuu):
x=xval
pkei=keisuu
rui=1
kekka=0
for i in range(1,len(pkei)):
kekka+=pkei[len(pkei)-i-1]*rui*i
rui*=xval
return kekka def tasizan(keisuu1,keisuu2):
if len(keisuu1)>=len(keisuu2):
rank=len(keisuu1)
kekka=[0]*rank
for i in range(rank):
kekka[i]=keisuu1[i]
for i in range(len(keisuu2)):
kekka[rank-i-1]+=keisuu2[len(keisuu2)-1-i]
else:
rank=len(keisuu2)
kekka=[0]*rank
for i in range(rank):
kekka[i]=keisuu2[i]
for i in range(len(keisuu1)):
kekka[rank-i-1]+=keisuu1[len(keisuu1)-1-i]
return kekka
def tasizan(keisuu1,keisuu2):
if len(keisuu1)>=len(keisuu2):
rank=len(keisuu1)
kekka=[0]*rank
for i in range(rank):
kekka[i]=keisuu1[i]
for i in range(len(keisuu2)):
kekka[rank-i-1]+=keisuu2[len(keisuu2)-1-i]
else:
rank=len(keisuu2)
kekka=[0]*rank
for i in range(rank):
kekka[i]=keisuu2[i]
for i in range(len(keisuu1)):
kekka[rank-i-1]+=keisuu1[len(keisuu1)-1-i]
return kekka
def kyuukai(x0keisuu):
bunkatusuu=30
maxtrytimes=100
xkeisuu=np.array(x0keisuu,dtype='complex128')
keisuu=xkeisuu
rank=len(xkeisuu)-1
xkai=[random.random() for i in range(rank)]
kyori=np.zeros((rank,rank),dtype=complex)
kakuteilist=[]
enz=ButterEnzan(rank)
if xkeisuu[rank]==0:
while xkeisuu[rank]==0:
warilist=[1,0]#warizan
keisuu,dummy1,dummy2=warizan(keisuu,warilist,len(keisuu)-1,1)
kakuteilist.append(0)
keisuu,dummy1,dummy2=warizan(keisuu,[keisuu[len(keisuu)-1]],len(keisuu)-1,0)
flag=0
bkeisuu=bibunkeisuu(keisuu)
kotaelist=[]
r=0
flag=0
for tr in range(maxtrytimes):
kotaelist=[]
if len(keisuu)<=1:
print('keisuu ended')
break
for j in range(bunkatusuu+1):
flag=0
rad=j/bunkatusuu*2*np.pi+np.random.uniform(-np.pi/bunkatusuu,np.pi/bunkatusuu)
kakudop=complex(np.cos(rad),np.sin(rad))
kakudon=complex(np.cos(rad),-np.sin(rad))
x=0
for i in range(100):
# fx=dainyu(x,keisuu)
fx=enz.dainyu2(x,keisuu)
# bx=bibun(x,keisuu)
bx=enz.bibun2(x,keisuu)
sabun=fx/bx*kakudon
if sabun.real>-abs((x*kakudon).real):
x-=sabun.real*kakudop
else:
flag=1
#print(x,fx,sabun,bx)
if abs(sabun.real)<0.1:
#print(x,fx,bx,sabun,'sabun0')
if abs(fx)<1.0e-5:
kotaelist.append(x)
#print('appended')
flag=1
break
else:
for k in range(100):
sabun=fx/bx
x-=sabun
# fx=dainyu(x,keisuu)
# bx=bibun(x,keisuu)
fx=enz.dainyu2(x,keisuu)
bx=enz.bibun2(x,keisuu)
#sabun=fx/bx
#print(x,fx,bx,sabun,'sabun')
if abs(fx)<1.0e-5:
kotaelist.append(x)
#print('appended')
flag=1
break
if flag==1:
flag=0
break
i=0
j=0
k=0
if len(kotaelist)>=0:
#keisuu,dummy1,dummy2=warizan(keisuu,[complex(np.sin(1),np.cos(1))],len(keisuu)-1,0)
print(dainyu(kotaelist[0],keisuu),dainyu(kotaelist[0],xkeisuu),'dainyu')
for i in range(len(kotaelist)):
for j in range(100):
# fx0=dainyu(kotaelist[i],keisuu)
# fx1=dainyu(kotaelist[i],xkeisuu)
fx0=enz.dainyu2(kotaelist[i],keisuu)
fx1=enz.dainyu2(kotaelist[i],xkeisuu)
fx0abs=abs(fx0)
fx1abs=abs(fx1)
# fx0b=bibun(kotaelist[i],keisuu)
# fx1b=bibun(kotaelist[i],xkeisuu)
fx0b=enz.bibun2(kotaelist[i],keisuu)
fx1b=enz.bibun2(kotaelist[i],xkeisuu)
#if tr>0:
#print(kotaelist[i],fx0,fx1,'hantei',fx0abs<1.0e-7,fx1abs<1.0e-13,len(kakuteilist),tr,fx0/fx0b,fx1/fx1b)
if fx0abs<1.0e-11 and fx1abs<1.0e-13:
kakuteilist.append(kotaelist[i])
keisuu,dummy1,dummy2=warizan(keisuu,[1,-kotaelist[i]],len(keisuu)-1,1)
keisuu,dummy1,dummy2=warizan(keisuu,[keisuu[len(keisuu)-1]],len(keisuu)-1,0)
print(kotaelist[i],fx0,fx1,fx0abs<1.0e-11,fx1abs<1.0e-13,len(kakuteilist),'. succeed. ',tr)
break
if np.isnan(kotaelist[i]) or np.isinf(kotaelist[i]):
break
if fx0abs<1 and fx0abs>1.0e-11:
#if fx0abs/abs(fx0b)<abs(kotaelist[i])*9.9e-12:
#kotaelist[i]-=fx0/fx0b/fx0abs*abs(fx0b)*abs(kotaelist[i])*9.9e-12
kotaelist[i]-=fx0/fx0b
continue
if fx1abs<1 and fx1abs>1.0e-30:
#if fx1abs/abs(fx1b)<9.9e-13*abs(kotaelist[i]):
#kotaelist[i]-=fx1/fx1b/ fx1abs*abs(fx1b)*9.9e-13*abs(kotaelist[i])
kotaelist[i]-=fx1/fx1b
continue
if fx0abs>100 and fx1abs>100 and j>20:
break
if fx0abs>1 and fx1abs>1 and j>50:
break
#if fx0abs>1.0e-10 and j>50:
#break
return kakuteilist
x=[np.random.uniform(-1,1)*3]*500
x[0]=1.0
import time
start=time.time()
lists=kyuukai(x)
end=time.time()
print('process time is ',end-start)
kotae=[dainyu(lists[i],x) for i in range(len(lists))]
print(kotae[20:30],kotae[100:110],lists[0:10])
print('value length is ',len(lists))
想定した通りに解を高い精度で求めることができているようです。
今回は複素数で表される解xの複素数的なところでいう角度(偏角というらしいです。)を固定して、x=0のところからニュートン法で近似を続けることによって、一度に5〜6個の解を探索することができるようになりました。
500係数がある式で、1600秒かけて150くらいの解しか見つけられなかったのは残念。
この記事が気に入ったらサポートをしてみませんか?