load(sym)$ load("sym/compile")$ load(gcdex)$ rtL:[α,β,γ,δ,ε,λ,ρ]; cL:[1,2,3,4,5,6,7]; eiL:[e1,e2,e3,e4,e5,e6,e7]; /* 多項式の最高次数と対称式としての値を返す面白い命令 polynome2ele */ fx:x^3+3*x+1; fxinfoL:polynome2ele(fx,x); N:fxinfoL[1]; NN:N!; feL:rest(fxinfoL,1); eiL:rest(eiL,N-7); fxeL:map( lambda([x,y],x=y),eiL,feL); /*本当は eiL:makelist(e[i],i,1,Nfpwr); としたい のだが e[i]のようなサフィックスだと根[α,β,γ]の対称式から方程式の 係数に変換すると他の関数 " tcontract(...), elem(...) " の出力がe1,e2,e3を使っておりと一致しないので、やめにした */ /* 3次方程式 fx=0の根を ( α, β, γ ) とするとき (α,β,γ)の全ての置換の組をリスト化する命令 permutations([α,β,γ]) */ rtL:rest(rtL,N-7); cL:rest(cL,N-7); zL:[u,w,y]; /* v[i]の計算の時に必要*/ V(cL,rtL):=sum(cL[i]*rtL[i],i,1,N); V(cL,rtL); /* α,β,γの計算の時に必要*/ prtL:listify( permutations(rtL)); viL:makelist(v[i],i,1,NN); pVrtL:makelist(V(cL,prtL[i]),i,1,NN); virtL:map( lambda([x,y],x=y),viL,pVrtL); awL:[1,0,0]; bwL:[0,1,0]; cwL:[0,0,1]; pawL:makelist(V(awL,prtL[i]),i,1,NN); pbwL:makelist(V(bwL,prtL[i]),i,1,NN); pcwL:makelist(V(cwL,prtL[i]),i,1,NN); vxL:makelist(x-v[i],i,1,NN); awxL:makelist(pawL[i]/(x-v[i]),i,1,NN); bwxL:makelist(pbwL[i]/(x-v[i]),i,1,NN); cwxL:makelist(pcwL[i]/(x-v[i]),i,1,NN); Vx:apply("*",vxL); /* α, β, γ の計算 の準備 */ Pax:0$ for i:1 thru NN do( Pax:Pax+Vx*awxL[i])$ Pax; Pbx:0$ for i:1 thru NN do( Pbx:Pbx+Vx*bwxL[i])$ Pbx$ Pcx:0$ for i:1 thru NN do( Pcx:Pcx+Vx*cwxL[i])$ Pcx$ Vrt:ev(Vx,virtL); Vrt:expand(Vrt)$ Part:ev(Pax,virtL); Pbrt:ev(Pbx,virtL)$ Pcrt:ev(Pcx,virtL)$ for i:0 thru NN do(c[i]:coeff(Vrt,x,i), ct[i]:tcontract(c[i],[α,β,γ]), ce[i]:elem([3],ct[i],[α,β,γ]), ce[i]:expand(ce[i]) )$ for i:0 thru NN do (print(NN-i," ",c[NN-i])); for i:0 thru NN do (print(NN-i," ",ce[NN-i])); Vei:0$ for i:0 thru NN do (Vei:Vei+ce[i]*x^i)$ Vei:expand(Vei); Vx:ev(Vei,fxeL); /* Vxは最小多項式gx[0]の候補となる。 Vx が因数分解されたかどうかチェックする。 因数分解されないとき gx[0]=Vx とする Vxが因数分解されたとき gx[0]=part(Vx,1) として因数分解の第1因子をgx[0]とする 以上の判断をして以下の議論をする。 参考:式" f "の1番目(n=1)の因数を取り出す命令 part(f,n) hipow(Vx,x) と言うコマンドも面白い */ Vx:factor(Vx); Vpw:hipow(Vx,x)$ if Vpw=NN then gx[0]:Vx else gx[0]:part(Vx,1)$ gx[0]; gv[0]:subst(v,x,gx[0]); /* P(x)の計算 */ /* α の計算 最終的にαをvの多項式で表現する計算*/ Pw:expand(Part)$ for i:0 thru (NN-1) do(c[i]:coeff(Pw,x,i), ct[i]:tcontract(c[i],[α,β,γ]), ce[i]:elem([3],ct[i],[α,β,γ]), ce[i]:expand(ce[i]) )$ for i:0 thru (NN-1) do (print(NN-1-i," ",c[NN-1-i])); for i:0 thru (NN-1) do (print(NN-1-i," ",ce[NN-1-i])); Pei:0$ for i:0 thru (NN-1) do (Pei:Pei+ce[i]*x^i)$ Pei:expand(Pei); Pax:ev(Pei,fxeL); /* βの計算 */ Pw:expand(Pbrt)$ for i:0 thru (NN-1) do(c[i]:coeff(Pw,x,i), ct[i]:tcontract(c[i],[α,β,γ]), ce[i]:elem([3],ct[i],[α,β,γ]), ce[i]:expand(ce[i]) )$ for i:0 thru (NN-1) do (print(NN-1-i," ",ce[NN-1-i]))$ Pei:0$ for i:0 thru (NN-1) do (Pei:Pei+ce[i]*x^i)$ Pei:expand(Pei)$ Pbx:ev(Pei,fxeL); /* γの計算 */ Pw:expand(Pcrt)$ for i:0 thru (NN-1) do(c[i]:coeff(Pw,x,i), ct[i]:tcontract(c[i],[α,β,γ]), ce[i]:elem([3],ct[i],[α,β,γ]), ce[i]:expand(ce[i]) )$ for i:0 thru (NN-1) do (print(NN-1-i," ",ce[NN-1-i]))$ Pei:0$ for i:0 thru (NN-1) do (Pei:Pei+ce[i]*x^i)$ Pei:expand(Pei)$ Pcx:ev(Pei,fxeL); /* Vxの微分した dV の逆元 IdV を計算する これらを使いα,β,γを計算する 逆元を求める際には、ここではmaximaが持っているgcdexという命令を 使ってみる */ dV:diff(Vx,x); gc:gcdex(Vx,dV,x); IdV:gc[2]$ check:remainder(dV*IdV,Vx); /* 上記check=1となったのでIdVがdVの逆元である事が 確認された */ /* 逆元がvの多項式としても止まったので、α,β,γ の計算が出来るようになった */ SoL:[]$ αx:remainder(Pax*IdV,Vx)$ αv:subst(v,x,αx)$ SoL:endcons(α=αv,SoL)$ βx:remainder(Pbx*IdV,Vx)$ βv:subst(v,x,βx)$ SoL:endcons(β=βv,SoL)$ γx:remainder(Pcx*IdV,Vx)$ γv:subst(v,x,γx)$ SoL:endcons(γ=γv,SoL)$ SoL; VivL:expand(ev(virtL,SoL)); check:[]$ GgrL:[]$ for i:1 thru NN do( z:remainder(subst(rhs(VivL[i]),x,Vx),gv[0]), check:endcons(z,check), if z=0 then GgrL:endcons(i,GgrL) )$ check; GgrL; /* 第1ステップ 6次式のg[0]を分解して3次のg[1]を計算する ガロア群はGal0= [1,2,3,4,5,6]からGal1=[1,4,5]に縮小 Gal0/Gail1=2 の計算である */ h0:(x-v[1])*(x-v[4])*(x-v[5]); h0:ev(h0,VivL); h0:expand(h0); h0:remainder(h0,gv[0]); h1:(x-v[2])*(x-v[3])*(x-v[6]); h1:ev(h1,VivL); h1:expand(h1); h1:remainder(h1,gv[0]); t0:(h0+h1)/2; t1:(h0-h1)/2; T1:expand(t1^2); T1:remainder(T1,gv[0]); A[1]:T1; B[1]:a[1]^2-A[1]; t1:a[1]$ h0:expand(t0+t1); gx[1]:h0; gv[1]:subst(v,x,h0); /* 以下は念のためのチェック */ h1:t0-t1; h01:expand(h0*h1); h01:remainder(h01,B[1],a[1]); /* 第2ステップ 3次多項式のg[1]をさらに分解してゆき1次多項式のg[2]を求める ガロア群はGal0= [1,2,3,4,5,6]からGal1=[1,4,5]になり 以下の計算は Gal1=[1,4,5]から Gal2=[1] への最後の 計算である Gal1/Gal2=3 である */ Ω:ω^2+ω+1$ h0:ev(x-v[1],VivL); h1:ev(x-v[4],VivL)$ h1:remainder(h1,gv[1])$ h1:expand(h1); h2:ev(x-v[5],VivL)$ h2:remainder(h2,gv[1])$ h2:expand(h2); t0:expand((h0+h1+h2)/3)$ t0:remainder(t0,g[1]); t0:remainder(t0,B[1]); t0:remainder(t0,Ω); t1:(h0+ω*h1+ω^2*h2)/3$ t1:remainder(t1,g[1]); t1:remainder(t1,B[1]); t1:remainder(t1,Ω); t1:expand(t1); t2:(h0+ω^2*h1+ω*h2)/3$ t2:remainder(t2,g[1]); t2:remainder(t2,B[1]); t2:remainder(t2,Ω); t2:expand(t2); /* T1=t1^3 を求める計算*/ T1:expand(t1^3); T1:remainder(T1,gv[1]); T1:remainder(T1,Ω); T1:remainder(T1,B[1]); T1:expand(T1); t1; t2; T12:t1*t2; T12:expand(T12); T12:remainder(T12,gv[1]); T12:remainder(T12,Ω); T12:remainder(T12,B[1]); T12:expand(T12); t1; t2; T12:t1*t2; T12:expand(T12); T12:remainder(T12,gv[1]); T12:remainder(T12,B[1]); T12:remainder(T12,Ω); T12:expand(T12); /* ここまでのまとめが以下の式*/ A[2]:T1; B[2]:a[2]^3-A[2]; t1:a[2]$ /* T1の逆数を求める計算 IAと言う逆元多項式を仮定して係数を決定する方式 個の逆数を求めるやり方は重要 */ IA:d[0]+d[1]*ω+d[2]*a[1]+d[3]*ω*a[1]; W:IA*A[2]; W:expand(W); W:remainder(W,Ω); W:remainder(W,B[1]); W:expand(W); D[0]:coeff(W,ω,0)$ D[0]:coeff(D[0],a[1],0); D[1]:coeff(W,ω,1)$ D[1]:coeff(D[1],a[1],0); D[2]:coeff(W,ω,0)$ D[2]:coeff(D[2],a[1],1); D[3]:coeff(W,ω,1)$ D[3]:coeff(D[3],a[1],1); Dsol:solve([D[0]=1,D[1]=0,D[2]=0,D[3]=0],[d[0],d[1],d[2],d[3]]); IA:ev(IA,Dsol[1]); t2:-3*a[2]^2*IA; t2:expand(t2); t2:factor(t2); t0; t1; t2; h0:t0+t1+t2; A[1]; B[1]; A[2]; B[2]; h0:t0+t1+t2$ gx[2]:h0; gv[2]:subst(v,x,h0); gv[0]; gv[1]; gv[2]; B[1]; B[2]; Ω; W:solve(gx[2],x); W:expand(W); /* 以下はg[1]が以下に分解されたかのチェック*/ h1:t0+t1*ω^2+t2*ω; h2:t0+t1*ω+t2*ω^2; h012:expand(h0*h1*h2)$ h012:remainder(h012,B[2],a[2])$ h012:remainder(h012,Ω,ω)$ h012:remainder(h012,B[1],a[1]); SoL; Rt:subst(v,x,W); /* 以下はgx[2]=0で求まるvの値を、vの多項式で表現された[α,β,γ]に 代入して、添加数a[1],a[2]で3根を表す計算 */ SoL:ev(SoL,Rt); AnsL:[]$ for i:1 thru 3 do( z:rhs(SoL[i]), z:remainder(z,B[2],a[2]), z:remainder(z,Ω,ω), z:remainder(z,B[1],a[1]), AnsL:endcons(z,AnsL) )$ AnsL$ /* 以下の式が添加数a[1],a[2],ωで記述されたf(x)の3根の数式である */ AnsL:map( lambda([x,y],x=y),rtL,AnsL); /* 実際に数値的に正しいか計算してみる。 maximaで数値で解を求める命令はallroots()である*/ root:[]$ ωr:allroots(Ω)$ root:endcons(ω=rhs(ωr[1]),root); a1r:allroots(B[1])$ root:endcons(a[1]=rhs(a1r[1]),root); b2:ev(B[2],root)$ b2r:allroots(b2)$ root:endcons(a[2]=rhs(b2r[1]),root); FansL:ev(AnsL,root)$ FansL:expand(FansL); allroots(fx); /*FansLとallroota(fx)の実数値で一致している事が判ったので、AnsLの数式は正しい事が判った*/