16. 多項式クラス(9)
ソースは次の5つです。
fact_test1.cpp
polynomial_z_001.h
polynomial3.h
p_numbers.h
fraction.h
fact_test1.cpp に main があります。
typedef vector<Polynomial_Z> Factorized;
void main(void) {
Polynomial p("x*x*x+y*y*y+z*z*z-3*x*y*z");
Polynomial_Z pz(p);
cout << pz.factorize() << endl;
Polynomial p2("x*x+y*y-x*y-x");
Polynomial p3("x*x+y*y+x*y-y");
Polynomial_Z pz2(p2 * p3);
cout << pz2.factorize() << endl;
Polynomial p4("1-x*x*x*x*x*x*x*x*x*x*x");
Polynomial_Z pz3(p4);
cout << pz3.factorize() << endl;
}
文字列から Polynomial クラスのオブジェクト作り、
そこから Polynomial_Z クラスのオブジェクトを作り、
それを因数分解すると、Polynomial を要素とする vector が返るので、
それを表示します。
上では3つの多項式を因数分解をしていますが、
別の多項式を因数分解する場合は、このファイルを改造してください。
Polynomial_Z は因数分解をするための整係数多項式クラスです
(Zは整数を意味します)。
それが、 polynomial_z_001.h で定義されています。
これが今回のプログラムの事実上の本体です。
今からこれを簡単に紹介していきます。
例として次の多項式を考えましょう。
x3 + y3 + z3 - 3xyz
まず、扱いやすくするために各項を順に並べます。
並び方は前のページにあったようになのですが、
詳しく言うと、次の条件で並べます。
1. 次数が小さいほうが前
2. 次数が同じならx1の次数が大きいほうが前
3. 2も同じならx2の次数が大きいほうが前
...
今考えている例では x
1 を x、x
2 を y
などと解釈します。
x y z で生成される3次までの項を全て並べると次のようになります。
1 x y z x2 xy xz y2 yz z2 x3 x2y x2z xy2 xyz xz2 y3 y2z yz2 z3
この順列を生成するために各項を、
各変数の指数を各桁とした4進数で表します。
そして、使われていない分の指数をその頭につけ加えます
(要するに各桁をたし合わせると3になるようにします)。
そうすると上の順列は次のように表されます。
3000 2100 2010 2001 1200 1110 1101 1020 1011 1002
0300 0210 0201 0120 0111 0102 0030 0021 0012 0003
以上は4進数表記です。
これをよく観察すると、
この値はその右隣の値との差が次のように求められることが分かります。
2番目に下の桁から見て最初に0でない桁が現れる前まで取る
ex) 2100 -> 0 2001 -> 00 0111 ->
頭に3から元の1番下の桁を引いたものを加える
ex) 2100 -> 30 2001 -> 200 0111 -> 1
元の1番下の桁を足す
ex) 2100 -> 30 2001 -> 201 0111 -> 2
x は2100だから、その次はそれから30を引いて2010で、これは y、などとなり、
各項を順に並べることができます。
前のページにも書きましたが、
この多項式関数の値 f
1, ... , f
10 が0にならないように、
x
0, x
1, x
2, y
0, y
1,
y
2, z
0, z
1, z
2
を選ばなければなりません。
まず、
x0 = y0 = z0 = 0
とします。これで、f
0 が0にならなければいいのですが、
0なら (x
0, y
0, z
0) を変えます。
このとき、あまり大きな数にならないように工夫しています。
すなわち、
(x0, y0, z0) = (1, 0, 0)
= (0, 1, 0)
= (0, 0, 1)
= (-1, 0, 0)
この並びは、基本的には上の項の並べ方と同じですが、
0 -> 0 1 -> 1 2 -> -1 3 -> 2 4 -> -2 ...
と読み替えます。
次に、x
1, y
1, z
1 が出てくる
f
i で0にならないようにする、
ということを繰り返します。
なんだか効率が悪そうですが、もっとずっと遅い部分があるので問題ありません。