Maxima で綴る数学の旅

紙と鉛筆の代わりに、数式処理システムMaxima / Macsyma を使って、数学を楽しみましょう

-数学- 可解な方程式を冪根で解く -解ける5次多項式の根も高速に求められる!!-

 

可解な多項式の根を求めるプログラムを提示してきましたが、このプログラムでの5次方程式の解の計算の計算時間的なボトルネックは、原子元Vで多項式の根を表す部分にありました。

ガロアが考えた方法をほぼそのまま実装した場合、5次方程式の場合で、数時間のオーダーがかかる計算になっていました。

この計算についてehitoさんから2019年に入ってから頂いたコメントで、Maximaの2引数版のfactor(p,q)を使い、qで指定した代数体でpを因数分解することで、画期的な高速化が得られました。

具体的にはpとして解きたい多項式(xの多項式)、qとして原子元Vの最小多項式を指定します。Vはpの全ての根の一次結合ですから、qで指定した代数体はpの根を全て含みます。したがってこの体はpの分解体になるので、pをxの一次式の積に分解します。つまりpは解けました。この時、解はVの式になるのです。

実際にやってみましょう。

まず必要なプログラムを読み込み、原子元を作るためのgal_phi()を定義します。

(%i31) load("~/Programming2/GaloisGroup2/Gal.mac");
$$ \tag{%o31} \verb|~/Programming2/GaloisGroup2/Gal.mac| $$
(%i32) gal_phi(xlist):=ev(sum(xlist[i]*cl[i],i,1,length(xlist)),cl:[1,-1,2,5,0,3,2])$

例題でよく使う3次式を定義します。

(%i33) p1:x^3-3*x-1;
$$ \tag{%o33} x^3-3\,x-1 $$
(%i34) PS:gal_init_polynomial_info(p1)$

p1の原子元の最小多項式を求めます。
(%i35) gal_minimal_polynomial_V2(PS);
$$ \tag{%o35} V^3-21\,V-17 $$

元の式p1をこの最小多項式が定義する代数体で因数分解します。
(%i36) factor(p1,%);
$$ \tag{%o36} \frac{\left(19\,x-2\,V^2-3\,V+28\right)\,\left(19\,x-V^2+8\,V+14\right)\,\left(19\,x+3\,V^2-5\,V-42\right)}{6859} $$

見易いように解の形に直します。
(%i37) solve(%,x);
$$ \tag{%o37} \left[ x=-\frac{3\,V^2-5\,V-42}{19} , x=\frac{V^2-8\,V-14}{19} , x=\frac{2\,V^2+3\,V-28}{19} \right] $$

確認のためにガロアがもともと考えた方式でp1の解をVで表す計算を行います。
(%i38) gal_sol_V(PS)$

計算結果を表示します。
(%i39) PS@solcond;
$$ \tag{%o39} \left[ \mathrm{solV}_{3}(V):=\frac{2\,V^2+3\,V-28}{19} , \mathrm{solV}_{2}(V):=\frac{V^2-8\,V-14}{19} , \mathrm{solV}_{1}(V):=-\frac{3\,V^2-5\,V-42}{19} \right] $$

解の並びの順番を別にすると、factor(p,q)で求めた式とgal_sol_V()で求めた式は一致していることが分かります。 

 

これ、可解な5次方程式に出てくる計算(pが5次、qが10次とか20次)でも非常に高速に実行します。

実際には井汲 景太さんが指摘されているように、これらの解が元の解a, b, cのどれに対応するのかを決定する必要があります。数値計算で対応を決めるやっつけなコードを書いたところ、ehitoさんから代数計算で対応をきちんと求める方法をご教授いただきました。下記のコードは数値計算による確認を代数計算による確認に置き換えたものです。ehitoさんには感謝します。

 

gal_sol_V4(pi):=block([rootVlist,solcond:[]],
  rootVlist:map(rhs,solve(factor(pi@polynomial,pi@gal_minpoly),x)),
  if length(rootVlist)#length(pi@sollist) then error("error gal_sol_V3: two args factor seems not working."),
  for a in permutations(rootVlist) do if is(ratsimp(gal_phi(a))=V) then block([p1solcond],
    pi@solcond:makelist(define(solV[i](V),a[i]),i,1,pi@degree),
    p1solcond:makelist(pi@sollist[i]=solV[i](V),i,1,pi@degree),
    pi@vncond:ev(pi@vcond,p1solcond,solcond,ratsimp,eval),
    return()),
  pi@vncond)$