2 Lập trình tính cơ sở Groebner của iđêan các đa thức triệt tiêu
2.1.2 Đa thức trong Zm[x1, , xn]
Một đa thức được biểu diễn là một cấu trúc bao gồm hai thành phần: số lượng các đơn thức (count) và bảng các đơn thức. Kiểu đa thức được định nghĩa như sau:
typedef struct poly {
int count;
int term[L][N+1];
} POLY;
Một đa thức f = 0 tương đương với f.count = 0. Các hạng tử của đa thức được sắp xếp từ trái qua phải theo các đơn thức được chọn tương ứng.
Hàm stringToArray có nhiệm vụ nhận một đa thức từ một xâu kí tự và biểu diễn đa thức theo cấu trúc trên.
Ví dụ 2.1.4. Với số biến là 4: w, x, y, z. Với thứ tự đơn thức là thứ tự từ điển. Từ xâu kí tựxy2z+5z3−4x3+6wxy+3qua hàm stringToArray ta được đa thứcf
f =
(
count= 5
[0 0 0 0 3], [0 0 0 3 5], [0 1 2 1 1], [0 3 0 0 −4], [1 1 1 0 6]
Hàm printPolynomial sẽ in lên màn hình đa thức có các hạng tử được sắp xếp theo thứ tự giảm dần từ trái qua phải theo thứ tự đơn thức đã được chọn trong chương trình tính tương ứng. Với ví dụ trên màn hình printPolynomial sẽ in trên màn hình đa thức với thứ tự đơn thức là thứ tự từ điển thông thường có dạng:
6wxy−4x3+xy2z+ 5z3+ 3
Một đoạn code sắp xếp đơn thức theo các kiểu thứ tự từ.
void sort(POLY *f) { int c,d; int tmp[MAX_ELEMENT]; int n = countOfMonomial(f); for (c = 0; c < n - 1 ; c++){ for (d = 0; d < n - c -1 ; d++) { int kq = compare(setMononimal(f, d), setMononimal(f, d + 1)); if (kq > 0) { copyArray(tmp, setMononimal(f, d)); copyArray(setMononimal(f, d), setMononimal(f, d+1 )); copyArray(setMononimal(f, d+1), tmp); } } } } /*---*/ int compareByLex(int a[], int b[]) {/* Lex ordering */
int d, i;
for (i = 0; i<MAX_ELEMENT; ++i) { if (a[i] <b[i]) { d = -1; break; } if (a[i] > b[i]) { d = 1; break; } }
if (i == MAX_ELEMENT) d = 0; return d;
}
/*---*/ int compareByRLex(int a[], int b[]) { /* Rlex order */
int d, i, s = 0, t = 0;
for (i = 0; i<MAX_ELEMENT-1; ++i) { s += a[i];
t += b[i]; }
if (s<t) { d = -1; return d; } if (s>t) { d = 1; return d; }
for (i = MAX_ELEMENT - 1; i >= 0; --i) { if (a[i]<b[i]) { d = -1; break; } if (a[i]>b[i]) { d = 1; break; } } if (i == -1) d = 0; return d; } /*---*/ int compareByGLex(int a[], int b[]) { /* Glex */
int d, i, s = 0, t = 0;
for (i = 0; i<MAX_ELEMENT -1; ++i) { s += a[i];
t += b[i]; }
if (s<t) { d = -1; return d; } if (s>t) { d = 1; return d; }
for (i = 0; i<MAX_ELEMENT-1; ++i) { if (a[i] <b[i]) { d = -1; break; } if (a[i]>b[i]) { d = 1; break; } } if (i == MAX_ELEMENT) d = 0; return d; } /*---*/ /* So sánh hai đơn thức */
int compare(int a[], int b[]) { switch (order) {
case 1: return (compareByLex(a, b)); case 2: return (compareByRLex(a, b)); case 3: return (compareByGLex(a, b)); }
Ví dụ 2.1.5. Cho f =xy2z+ 5z3−4x3+ 6y4. i) Đối với thứ tự từ điển mà x > y > z:
f = −4x3+xy2z+ 6y4+ 5z3
ii) Đối với thứ tự từ điển phân bậc mà x > y > z:
f =xy2z+ 6y4−4x3+ 5z3
iii) Đối với thứ tự từ điển ngược màx > y > z:
f = 6y4+xy2z−4x3+ 5z3
Phép cộng đa thức với đa thức chính là việc thực hiện cộng đa thức này với từng đơn thức có trong đa thức kia. Bằng kiểu dữ liệu mảng, phép cộng đa thức với đơn thức là thực hiện cộng từng thành phần trong mảng và in ra màn hình kết quả nhận được. /*---*/ int reverse(int n) { int i; n = n%m; if(n<0) n = m + n; for (i = 1; i<m; ++i)
if ((i*n) % m == 1) return i; }
/*---*/ /* Cộng đa thức với đơn thức. */
void plusPolyMono(POLY*f, int a[]) { int i, t;
bool isAdded = false;
for (i = 0; i<countOfMonomial(f); ++i) { // Kiểm tra có trùng hệ số không? if(setMononimal(f, i)[0] == a[0] && setMononimal(f, i)[1] == a[1]
&& setMononimal(f, i)[3] == a[3]){ setMononimal(f, i)[POS_NUMERATOR]
= setMononimal(f, i)[POS_NUMERATOR] + a[POS_NUMERATOR]; if(setMononimal(f, i)[POS_NUMERATOR] == 0){
for (; i<countOfMonomial(f) - 1; ++i){ copyArray(setMononimal(f, i), setMononimal(f, i + 1)); } countOfMonomial(f) = countOfMonomial(f) - 1; } isAdded = true; } } if(!isAdded){
for (i = 0; i<MAX_ELEMENT; i++){
setMononimal(f, countOfMonomial(f))[i] = a[i]; } countOfMonomial(f) += 1; } //sort(f); } /*---*/ /* Cộng đa thức với đa thức. */
void plusPolyPoly(POLY *f, POLY *g) { int i;
for (i = 0; i<countOfMonomial(g); ++i) { plusPolyMono(f, setMononimal(g, i));
} }
Phép nhân đa thức với đơn thức cũng được thực hiện tương tự như phép cộng hai đa thức đối với từng thành phần trong mảng.
void multiPolynomial(POLY *f, int a[], POLY *g) { int i;
countOfMonomial(g) = countOfMonomial(f); for (i = 0; i<countOfMonomial(g); ++i)
multiMononimal(setMononimal(f, i), a, setMononimal(g, i)); }
Ví dụ 2.1.6. Xét Z7[x, y, z]
• Phép cộng hai đa thức:
Cho f =wx2y−3xyz+ 2yz−3, g = 2xyz−4x+ 5.
f +g =wx2y+ 6xyz+ 2yz+ 3x+ 2
• Phép nhân hai đa thức:
Cho f =wx2+xy2, g = 2xz2+x+ 4
f ·g = 2wx3z2+wx3+ 4wx2+ 2x2y2z2+x2y2+ 4xy2