多項式の解き方をpythonコードで実装してみる。

多項式分解のコードをDKA法で書いてみました。行列の固有多項式の計算用のコードと合わせて載せてあります。最初は稚拙なもので、このコードでは15桁くらいまで桁が上がると時間がかかったり、うまく解を求められなくなったりします。

DKA法による多項式の因数分解の他に、できた多項式の解の重複の確認のために、行列の性質を使っています。ある行列Aと単位行列の整数乗で構成される行列が変数の方程式を考えた際に、対角成分に方程式の解となる数値を置いた行列を代入すると、0行列になります。また、対角成分の右隣に1を置いて同じく代入すると、同じ行の対角成分が両方方程式の解を為す場合にのみ、0行列になる性質があります。この性質を利用して、求めた解の重複の確認をおこなっています。

また、重複の確認を行った後は、計算した解から方程式を作り、元の式から割り算をすることで、元の方程式の簡略化をおこなっています。

出力はこんな感じ。流石に何回かトライしないと失敗する。

import numpy as np
import scipy.linalg as linalg
import random

def solv(a0,b0,c0):
    D=b0**2-4*a0*c0
    if D<0:
        D=complex(0,(-D)**0.5)
    x_1=(-b0+D)/2/a0
    x_2=(-b0-D)/2/a0
    return x_1,x_2

import random
def warizan(keisuu,bunbo,krank,brank):
    p=keisuu
    b=bunbo
    jisuuk=krank
    jisuub=brank
    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 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

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 dkahou(keisuu,keisanjougen=13):
    jougen=keisanjougen
    seido=1.0e-10
    klist=keisuu
    jisuu=len(klist)-1
    bibklist=[0]*(jisuu-1)
    #print(jisuu,klist)
    #if jisuu<jougen:
    jougen=jisuu
    for i in range(jisuu-1):
        bibklist[i]=(jisuu-i)*klist[i]
    i0=0
    waribase=[[]]*jisuu
    amaribase=[[]]*jisuu
    tugir=jisuu
    tugik=klist
    bk=[1,klist[1]/jisuu]
    while tugir>=1:
        tugik,amari0,tugir=warizan(tugik,bk,tugir,1)
        waribase[i0]=tugik
        amaribase[i0]=amari0
        i0+=1
    #print(bk)
    #print(waribase)
    #print(amaribase)
    kumitatek=[0]*(jisuu+1)
    kumitatek[0]=1
    for i in range(jisuu):
        kumitatek[i+1]=-abs(amaribase[jisuu-i-1][0])
    #print(kumitatek)
    r=1
    for i in range(30):
        rsabun=dainyu(r,kumitatek)
        r-=rsabun/bibun(r,kumitatek)
        if rsabun<seido:
            break
        #print(r)
    shokiti=[0]*jougen
    if jougen<0:
        for i in range(jougen):
        #shokiti[i]=-klist[1]/jisuu/klist[0]+r*complex(np.sin(2*np.pi/jougen*i+np.pi/2/jougen),np.cos(2*np.pi/jougen*i+np.pi/2/jougen))
            randoms=random.random()
            shokiti[i]=-klist[1]/jisuu/klist[0]+r*complex(np.sin(i/jougen*2*np.pi+np.pi/2/jougen),np.cos(i/jougen*2*np.pi+np.pi/2/jougen))
    else:
        for i in range(jougen):
            randoms=random.random()
            shokiti[i]=-klist[1]/jisuu/klist[0]+r*complex(np.cos(2*randoms*np.pi),np.sin(2*randoms*np.pi))*random.random()
    #dka
    kouho=shokiti
    normlist=[0]*jougen
    norm=1
    #print(kouho)
    for tr in range(80):
        sabun=np.array([[0]*jougen]*jougen,dtype=complex)
        norm=0
        for i in range(jougen):
            for j in range(jougen):
                sabun[i,j]=kouho[i]-kouho[j]
        #print(sabun)
        for i in range(jougen):
            kansuu=dainyu(kouho[i],klist)
            newkei=1
            for j in range(jougen):
                if j!=i:
                    newkei*=sabun[i,j]
            
            #print(newkei,kansuu)
            kouho[j]-=kansuu/newkei/klist[0]/pow(newkei,jisuu/jougen-1)
            #print(kansuu/newkei)
            norm+=abs(kansuu)
            #print(kouho)
        
        if norm<seido:
            
            break
        #print(norm)
        #print(kouho)
    if np.isnan(kouho).any()==True:
        for i in range(len(kouho)):
            if np.isnan(kouho[i])==True:
                kouho[i]=0
    if norm>seido:
        for tr in range(80):
            norm=0
            for i in range(jougen):
                dif=dainyu(kouho[i],klist)
                kouho[i]-=dif/bibun(kouho[i],klist)
                norm+=abs(dif)
            if norm<seido:
                break
    if np.isnan(kouho).any()==True:
        for i in range(len(kouho)):
            if np.isnan(kouho[i])==True:
                kouho[i]=0        

    #print (kouho)
    for i in range(jougen):
        normlist[i]=abs(dainyu(kouho[i],klist))
        if norm>=seido and normlist[i]<1:
            for tr in range(60):
                #kouho[i]+=0
                kouho[i]-=dainyu(kouho[i],klist)/bibun(kouho[i],klist)/20
            normlist[i]=abs(dainyu(kouho[i],klist))
#    print(normlist)
    return kouho,norm,normlist
    

def kaikeisan(keisuu):
    motometai=keisuu
    seido=1.0e-5
    mrank=len(motometai)
    kailist,norm,norml=dkahou(motometai)
    #print(kailist,norm)
    kailen=len(kailist)
    d=np.zeros((kailen,kailen),dtype=complex)
    d[0,0]=kailist[0]
    for i in range(kailen-1):
        d[i,i]=kailist[i+1]
        d[i,i+1]=1
    b=np.eye(kailen,dtype=complex)*motometai[mrank-1]
    a=np.eye(kailen,dtype=complex)
    for i in range(1,mrank-1):
        a=a@d
        b+=a*motometai[mrank-1-i]
    
    normchouhuku=linalg.norm(b)
    #print(normchouhuku)
    kaikakutei=[]
    if normchouhuku>seido:
        d=np.eye(kailen,dtype=complex)*kailist[0]
        b=np.eye(kailen,dtype=complex)*motometai[mrank-1]
        a=np.eye(kailen,dtype=complex)
        for i in range(1,mrank):
            a=a@d
            b+=a*motometai[mrank-1-i]
#            print(b)
        normchouhuku=linalg.norm(b)
        row=0
        #print(normchouhuku)
        rowmax=kailen
        if normchouhuku>seido:
            for j in range(1,kailen):
                d=np.eye(kailen,dtype=complex)*kailist[j]
                b=np.eye(kailen,dtype=complex)*motometai[mrank-1]
                a=np.eye(kailen,dtype=complex)
                for i in range(1,mrank):
                    a=a@d
                    b=b+a*motometai[mrank-1-i]
                normchouhuku=linalg.norm(b)
                
                if normchouhuku>seido:
                    rowmax-=1
                else:
                    rowmax-=1
                    break
        
        #print(normchouhuku)
        for j in range(1,rowmax):
            if normchouhuku<seido:
                d[row,row+1]=1
                row+=1
            d[row,row]=kailist[j]
            
            #print(d)
            b=np.eye(kailen,dtype=complex)*motometai[mrank-1]
            a=np.eye(kailen,dtype=complex)
            for i in range(1,mrank):
                a=a@d
                b=b+a*motometai[mrank-1-i]
            normchouhuku=linalg.norm(b)
            #print(normchouhuku)
        for j in range(row):
            kaikakutei.append(d[j,j])
    else:
        kaikakutei=kailist
    #print(kaikakutei)
    
    return kaikakutei
    
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 kontansaku(keisuu):
    kakuteikeisuu=[]
    kyuukai=keisuu
    subkyuukai=kyuukai
    flag=0
    tr0=0
    while flag==0 and tr0<100:
        tr0+=1
        print(tr0)
        if flag==1:
            return kakuteikeisuu
        kaikeisuu=kaikeisan(subkyuukai)
        #print(subkyuukai,'subkyu')
        warilist=[1]

        if kaikeisuu==[]:
            continue
        if len(kaikeisuu)>=1:
            for i in range(len(kaikeisuu)):
                for tr in range(100):
                    kaikeisuu[i]-=dainyu(kaikeisuu[i],subkyuukai)/bibun(kaikeisuu[i],subkyuukai)
                    if abs(dainyu(kaikeisuu[i],subkyuukai))<1.0e-14:
                        kakekeisuu=[1,-kaikeisuu[i]]
                        warilist=kakezan(warilist,kakekeisuu)
                        kakuteikeisuu.append(kaikeisuu[i])
                        break

        #print(kaikeisuu,warilist,'warimoto')
        if len(warilist)>1:
            subkyuukai,dummy1,dummy2=warizan(subkyuukai,warilist,len(subkyuukai)-1,len(warilist)-1)
        ##print(subkyuukai,'kai')
        print(len(subkyuukai))
        if len(subkyuukai)==2:
            tmpkeisuu=kyuukai
            for i in range(len(kakuteikeisuu)):
                warilist=[1,-kakuteikeisuu[i]]

                tmpkeisuu,dummy1,dummy2=warizan(tmpkeisuu,warilist,len(tmpkeisuu)-1,1)
            kakuteikeisuu.append(-tmpkeisuu[1]/tmpkeisuu[0])
            flag=1
            break
        if len(subkyuukai)==1:
            kakuteikeisuu.append(0)
            flag=1
            break
        if subkyuukai==[] :
            flag=1
            break   
    return kakuteikeisuu



def gyouretukeisuu(gyouretu):
    gyousuu=gyouretu.shape[0]
    if gyousuu!=gyouretu.shape[1]:
        print('not seihougyouretu error')
            
    a=np.eye(gyousuu,dtype=complex)
    b=np.zeros((gyousuu,gyousuu),dtype=complex)
    for i in range(gyousuu):
        m=np.ones((gyousuu,1))
    
        a=a@gyouretu
    
        b[0:gyousuu,gyousuu-1-i:gyousuu-i]=a@m
    #print(b,'b')
    #print(n)
    p=-b**-1@np.ones((gyousuu,1),dtype=complex)#a,b,1
    print(p)
    keisuu=[0]*(gyousuu+1)
    for i in range(gyousuu):
        keisuu[i]=p[i,0]/p[0,0]
    keisuu[gyousuu]=1
    return keisuu

n=[[3,4,1,0],[1,4,-3,2],[-2,-8,1,5],[2,3,1,9]]
print(np.matrix(n),'matrix')
keisuu=gyouretukeisuu(np.matrix(n).reshape(4,4))
keisuu=[1,4,2,8,5,7,1,4,2,8,5,7,1,5,9+1.0j,3,9,2,-4,5,4,6]
print(keisuu,'keisuu')
konlist1=kontansaku(keisuu)
konlist2=[0]*len(konlist1)
for i in range(len(konlist1)):
    konlist2[i]=dainyu(konlist1[i],keisuu)
print(konlist1,konlist2)




この記事が気に入ったらサポートをしてみませんか?