source: git/Singular/LIB/triang.lib @ a09c2a0

fieker-DuValspielwiese
Last change on this file since a09c2a0 was 9173792, checked in by Christoph Lossen <lossen@…>, 23 years ago
* westenb: help strings edited, typos corrected git-svn-id: file:///usr/local/Singular/svn/trunk@5244 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 35.7 KB
Line 
1//last change: 13.02.2001 (Eric Westenberger)
2//////////////////////////////////////////////////////////////////////////////
3version="$Id: triang.lib,v 1.7 2001-02-19 14:17:50 lossen Exp $";
4category="Symbolic-numerical solving";
5info="
6LIBRARY: triang.lib   Decompose Zero-dimensional Ideals into Triangular Sets
7AUTHOR: D. Hillebrand
8
9PROCEDURES:
10 triangL(G);          Decomposition of (G) into triangular systems (Lazard).
11 triangLfak(G);       Decomp. of (G) into tri. systems plus factorization.
12 triangM(G[,.]);      Decomposition of (G) into triangular systems (Moeller).
13 triangMH(G[,.]);     Decomp. of (G) into tri. syst. with disjoint varieties.
14";
15
16LIB "general.lib"; // Muss geladen werden fuer den Befehl sort().
17LIB "elim.lib";    // Muss geladen werden fuer sat().
18
19
20///////////////////////////////////////////////////////////////////////////////
21//
22//  Der Lazard-Algorithmus
23//
24///////////////////////////////////////////////////////////////////////////////
25
26proc triangL (ideal G)
27"USAGE:   triangL(G); G=ideal
28ASSUME:  G is the reduced lexicographical Groebner bases of the
29         zero-dimensional ideal (G), sorted by increasing leading terms.
30RETURN:  a list of finitely many triangular systems, such that
31         the union of their varieties equals the variety of (G).
32NOTE:    Algorithm of Lazard (see: Lazard, D.: Solving zero-dimensional
33         algebraic systems, J. Symb. Comp. 13, 117 - 132, 1992).
34EXAMPLE: example triangL; shows an example
35"
36{
37
38    // Test, ob G Groebnerbasis eines nulldimensionalen Ideals ist.
39    if (attrib(G,"isSB") <> 1)
40    {
41        print("   ? Error: The input is no groebner bases.");
42        return();
43    }
44    else
45    {
46        if (dim(G) <> 0)
47        {
48            print("   ? Error: ideal is not zero-dimensional.");
49            return();
50        }
51    }
52
53    if (size(G) <= 2)  // schon Dreiecksbasis
54    {
55        return(list(G));
56    }
57
58    // Noetige Optionen setzen.
59    // obachman: save options so that tey can be reset on exit
60    intvec ovec = option(get);
61    option(redSB);
62    option(returnSB);
63    list B;    // Bearbeitungsliste
64    list F;    // Ergebnisliste = Triangulierung
65    ideal T, T_neu;
66    poly p,p_neu,r,s,lt,lc,lcr;
67    list inv;
68    int u,v;
69    int l,h;
70    string st;
71
72    T = ideal(G[1]);
73    attrib(T,"isSB",1);
74    B = list(list(T,2));
75
76    while (size(B) > 0)
77    {
78        T   = B[1][1];
79        h   = B[1][2];
80        B   = Listenrest(B);
81        p   = G[h];
82        v   = lvar(p);
83        lc  = lcoef(p,v);
84          st=string(nvars(basering)-v+1);
85          dbprint(string(timer)+" S"+st+": invertiere Leitkoeffizient von G["+string(h)+"].");
86
87        // Invertiere den Leitkoeffizienten von G[h] bzgl. var(v) modulo (T).
88        inv = invertieren(lc,T);
89
90          dbprint(string(timer)+" S"+st+": Anzahl Dreiecksbasen: "+string(size(inv))+".");
91
92        while (size(inv) > 0)
93        {
94            r   = inv[1][1];
95            s   = inv[1][2];
96            T   = inv[1][3];
97            inv = Listenrest(inv);
98            if (r == 0)  // r == 0?, dann p nicht der ggt der Stufe,
99            {
100                   dbprint(string(timer)+" S"+st+": Leitkoeffizient == 0.");
101                B = list(list(T,h+1)) + B;
102            }
103            else         // ansonsten ggt der Stufe gefunden.
104            {
105                   dbprint(string(timer)+" S"+st+": ggt gefunden.");
106                lt    = var(v)**degv(p,v);
107                p_neu = cleardenom(s*lt + reduce(r*(p-lc*lt),T));
108                T_neu = T,p_neu;
109                attrib(T_neu,"isSB",1);
110
111                // Restlichen Polynome der gleichen Stufe uebergehen.
112                for (l = h+1; l <= size(G); l++)
113                {
114                    u = lvar(G[l]);
115                    if (u <> v) {break;}
116                }
117
118                // Durchsuche restliche Stufen nach trivialen ggt's.
119                while (l <= size(G))
120                {
121                    lc = lcoef(G[l],u);
122                    lcr = reduce(lc,T_neu);
123
124                    while (lcr == 0) // Gehe bis zum ersten Polynom <> 0
125                    {                // modulo (T_neu).
126                        l++;
127                        lc = lcoef(G[l],u);
128                        lcr = reduce(lc,T_neu);
129                    }
130
131                    if (deg(lcr) == 0) // Polynom <> 0 normiert?, dann
132                    {                  // an Dreiecksbasis anhaengen,
133                          dbprint(string(timer)+" S"+string(nvars(basering)-u+1)+": Schnellerkennung: ggt gefunden.");
134                        lt = var(u)**degv(G[l],u);
135                        p_neu = cleardenom(lcr*lt +
136                                  reduce(G[l]-lc*lt,T_neu));
137                        T_neu = T_neu,p_neu;
138                        attrib(T_neu,"isSB",1);
139                        u = lvar(G[l]);
140                        l++;
141                        while (l <= size(G)) // Rest der Stufe uebergehen.
142                        {
143                            if (lvar(G[l]) <> u) {u = lvar(G[l]); break;}
144                            l++;
145                        }
146                    }
147                    else // sonst nicht normierte Polynome auf der Stufe.
148                    {
149                        break;
150                    }
151                }
152                if (l > size(G))  // Ende von G erreicht, dann Dreiecks-
153                {                 // basis der Triangulierung gefunden,
154                       dbprint(string(timer)+" S"+st+": Dreiecksbasis der Triangulierung gefunden.");
155                    F = F + list(T_neu);
156                }
157                else              // sonst T_neu,l erneut bearbeiten.
158                {
159                    B = list(list(T_neu,l)) + B;
160                }
161            }
162        }
163    }
164    option(set, ovec);
165    return(F);
166}
167//-------------------------------- example ----------------------------------
168example
169{  "EXAMPLE:"; echo = 2;
170    ring rC5 = 0,(e,d,c,b,a),lp;
171    triangL(stdfglm(cyclic(5)));
172}
173
174///////////////////////////////////////////////////////////////////////////////
175
176proc triangLfak (ideal G)
177"USAGE:   triangLfak(G); G=ideal
178ASSUME:  G is the reduced lexicographical Groebner bases of the
179         zero-dimensional ideal (G), sorted by increasing leading terms.
180RETURN:  a list of finitely many triangular systems, such that
181         the union of their varieties equals the variety of (G).
182NOTE:    Algorithm of Lazard with factorization (see: Lazard, D.: Solving
183         zero-dimensional algebraic systems, J. Symb. Comp. 13, 117 - 132, 1992).
184REMARK:  each polynomial of the triangular systems is factorized.
185EXAMPLE: example triangLfak; shows an example
186"
187{
188    return(triangLbas(G,2));
189}
190//-------------------------------- example ----------------------------------
191example
192{  "EXAMPLE:"; echo = 2;
193    ring rC5 = 0,(e,d,c,b,a),lp;
194    triangLfak(stdfglm(cyclic(5)));
195}
196
197///////////////////////////////////////////////////////////////////////////////
198
199static proc triangLbas (ideal G, list #)
200"USAGE:   triangLbas(G[,i]); G reduzierte lexikographische Groebnerbasis
201                            des nulldimensionalen Ideals (G), nach
202                            Leittermen aufsteigend sortiert,
203                            i = 1 oder 2 (ohne Angabe i = 1).
204RETURN:  Triangulierung von (G).
205         Ist i == 2, dann wird jedes Polynom der Dreiecksbasen
206         der Triangulierung zusaetzlich faktorisiert.
207NOTE:    Algorithmus von Lazard (siehe: Lazard, D.: Solving
208         zero-dimensional algebraic systems,
209         J. Symb. Comp., Bd. 13, S. 117 - 132, 1992).
210"
211{
212
213    // Test, ob G Groebnerbasis eines nulldimensionalen Ideals ist.
214    if (attrib(G,"isSB") <> 1)
215    {
216        print("   ? Error: The input is no groebner bases.");
217        return();
218    }
219    else
220    {
221        if (dim(G) <> 0)
222        {
223            print("   ? Error: ideal is not zero-dimensional.");
224            return();
225        }
226    }
227
228    // Noetige Optionen setzen.
229    // obachman: save options so that tey can be reset on exit
230    intvec ovec = option(get);
231    option(redSB);
232    option(returnSB);
233    // Faktorisierungsschalter setzen.
234    int fak;
235    if (size(#) > 0 && typeof(#[1]) == "int")
236    {
237        if (#[1] == 2) {fak = 1;}
238    }
239
240    if (size(G) <= 2)  // schon Dreiecksbasis
241    {
242        list E;
243        if (fak)
244        {
245            E = faktorisiere_DB(G);
246        }
247        else
248        {
249            E = list(G);
250        }
251        option(set, ovec);
252        return(E);
253    }
254
255    list B;    // Bearbeitungsliste
256    list F;    // Ergebnisliste = Triangulierung
257    list T_neu;
258    ideal T;
259    poly p,p_neu,r,s,lt,lc;
260    list inv;
261    int v;
262    int l,h;
263    string st;
264
265    // B initialisieren
266    if (fak)
267    {
268        B = H_anhaengen(faktorisiere_letzten(G[1]),2);
269    }
270    else
271    {
272        T = ideal(G[1]);
273        attrib(T,"isSB",1);
274        B = list(list(T,2));
275    }
276
277    while (size(B) > 0)
278    {
279        T   = B[1][1];
280        h   = B[1][2];
281        B   = Listenrest(B);
282        p   = G[h];
283        v   = lvar(p);
284        lc  = lcoef(p,v);
285          st=string(nvars(basering)-v+1);
286          dbprint(string(timer)+" S"+st+": invertiere Leitkoeffizient von G["+string(h)+"].");
287
288        // invertiere den Leitkoeffizienten von G[h] bzgl. var(v) modulo (T).
289        inv = invertieren(lc,T);
290          dbprint(string(timer)+" S"+st+": Anzahl Dreiecksbasen: "+string(size(inv))+".");
291
292        while (size(inv) > 0)
293        {
294            r   = inv[1][1];
295            s   = inv[1][2];
296            T   = inv[1][3];
297            inv = Listenrest(inv);
298            if (r == 0)  // r == 0?, dann p nicht der ggt der Stufe,
299            {
300                   dbprint(string(timer)+" S"+st+": Leitkoeffizient == 0.");
301                B = list(list(T,h+1)) + B;
302            }
303            else         // ansonsten ggt der Stufe gefunden.
304            {
305                   dbprint(string(timer)+" S"+st+": ggt gefunden.");
306                lt    = var(v)**degv(p,v);
307                p_neu = cleardenom(s*lt + reduce(r*(p-lc*lt),T));
308                if (fak)
309                {
310                    T_neu = faktorisiere_letzten(list(T + p_neu));
311                }
312                else
313                {
314                    T_neu = list(T + p_neu);
315                }
316
317                // Restlichen Polynome der gleichen Stufe uebergehen.
318                for (l = h+1; l <= size(G); l++)
319                {
320                     if (lvar(G[l]) <> v) {break;}
321                }
322
323                if (l > size(G))  // Ende von G erreicht, dann Dreiecks-
324                {                 // basis der Triangulierung gefunden,
325                       dbprint(string(timer)+" S"+st+": Dreiecksbasis der Triangulierung gefunden.");
326                    F = F + T_neu;
327                }
328                else              // sonst T_neu,l erneut bearbeiten.
329                {
330                    B  = H_anhaengen(T_neu,l) + B;
331                }
332            }
333        }
334    }
335    option(set, ovec);
336    return(F);
337}
338
339///////////////////////////////////////////////////////////////////////////////
340
341static proc invertieren (poly p, ideal T)
342"USAGE:   invertieren(p,T); p Polynom, T reduzierte Dreiecksbasis.
343RETURN:  Liste von Tripeln (Listen) bestehend aus einem Polynom ri,
344         einem Element aus dem Grundring si, und einer
345         reduzierten Dreiecksbasis Ti, i = 1,...,m, so dass
346         [T1,...,Tm] eine Triangulierung von T ist und
347         p = 0 mod (Ti) falls ri = 0, ansonsten
348         ri*p = si mod (Ti) fuer i = 1,...,m.
349"
350{
351    // Triviale Faelle vorweg behandeln.
352    p = reduce(p,T);
353    if (p == 0) {return(list(list(0,0,T)));}
354    if (deg(p) == 0) {return(list(list(1,p,T)));}
355
356    list inv;
357    int zerlegt;      // zerlegt ist Schalter dafuer, ob T zerlegt wurde,
358    export zerlegt;   // einzige globale Variable.
359    list toSee = list(list(p,T));  // zu bearbeitende Paare
360    list toSave;                   // Ergebnisliste
361    poly pr;
362
363    while (size(toSee) > 0)
364    {
365        zerlegt = 0;             // zerlegt = FALSE
366        p = toSee[1][1];
367        T = toSee[1][2];
368        toSee = Listenrest(toSee);
369
370        // invertieren_oT aufrufen, um p+(T) zu invertieren.
371        inv = invertieren_oT(p,T);
372
373        if (zerlegt)   // T zerlegt?, dann pro neuer Dreiecksbasis
374        {              // weiteruntersuchen,
375            pr = reduce(p,inv[1]);
376            if (pr == 0) // es sei denn p ist reduziert gleich 0,
377            {
378                toSave = list(list(0,0,inv[1])) + toSave;
379                attrib(toSave[1][3],"isSB",1);
380            }
381            else
382            {
383                toSee  = list(list(pr,inv[1])) + toSee;
384                attrib(toSee[1][2],"isSB",1);
385            }
386            pr = reduce(p,inv[2]);
387            if (pr == 0)
388            {
389                toSave = list(list(0,0,inv[2])) + toSave;
390                attrib(toSave[1][3],"isSB",1);
391            }
392            else
393            {
394                toSee  = list(list(pr,inv[2])) + toSee;
395                attrib(toSee[1][2],"isSB",1);
396            }
397
398        }
399        else           // ansonsten Quasi-Inverses gefunden.
400        {
401            toSave = list(list(inv[1],inv[2],T)) + toSave;
402            attrib(toSave[1][3],"isSB",1);
403        }
404    }
405    kill(zerlegt);
406    return(toSave);
407}
408
409///////////////////////////////////////////////////////////////////////////////
410
411static proc invertieren_oT (poly p, ideal T)
412"USAGE:   invertieren_oT(p,T); T reduzierte Dreiecksbasis,
413                              p <> 0 Polynom, irreduzibel modulo (T).
414RETURN:  Entweder ein Quasi-Inverses (r,s) von p modulo (T), d.h.
415         r*p = s mod (T) und s im Grundring,
416         oder eine Triangulierung [T1,T2] von T
417         mit (Ti) <> (T) fuer i = 1,2.
418"
419{
420    // Quasi-Inverses von Konstante klar.
421    if (deg(p) == 0) {return(list(1,p));}
422
423    ideal T_bis_k,T1,T2;
424    poly g,a,b;
425    list rq;
426    list gab;
427    int i;
428    int v = lvar(p);
429    int k = nvars(basering)-v+1;
430
431    // Zu p passende Dreiecksbasis auswaehlen.
432    if (k == 1)
433    {
434        T_bis_k = 0;
435    }
436    else
437    {
438        T_bis_k = T[1..(k-1)];
439    }
440    attrib(T_bis_k,"isSB",1);
441
442    // Um p+(T) zu invertieren, erw. eukl. Algorithmus anwenden.
443    gab = Erw_ggt_oT(T[k],p,v,T_bis_k);
444
445    // Entweder Triangulierung von T_bis_k erhalten,
446    if (zerlegt)
447    {
448        // T[k..size(T)] an gab[i] anhaengen und reduzieren.
449        T1 = gab[1];
450        T2 = gab[2];
451        for (i = k; i <= size(T); i++)
452        {
453            T1 = T1 + cleardenom(reduce(T[i],T1));
454            T2 = T2 + cleardenom(reduce(T[i],T2));
455            attrib(T1,"isSB",1);
456            attrib(T2,"isSB",1);
457        }
458        return(list(T1,T2));
459    }
460
461    // ansonsten gilt: a*T[k] + b*p = g mod (T_bis_k)
462    g = gab[1];
463    a = gab[2];
464    b = gab[3];
465
466    if (degv(g,v) > 0)        // Entweder echten Teiler von T[k] gefunden,
467    {                         // dann splitte T,
468        rq = pdiv(T[k],g,v);
469
470        T1 = T_bis_k;
471        T1[k] = cleardenom(reduce(g,T1));
472        attrib(T1,"isSB",1);
473        T2 = T_bis_k;
474        T2[k] = cleardenom(reduce(rq[2],T2));
475        attrib(T2,"isSB",1);
476
477        // T[k..size(T)] an T1, T2 anhaengen und reduzieren.
478        for (i = k + 1; i <= size(T); i++)
479        {
480            T1 = T1 + cleardenom(reduce(T[i],T1));
481            T2 = T2 + cleardenom(reduce(T[i],T2));
482            attrib(T1,"isSB",1);
483            attrib(T2,"isSB",1);
484        }
485
486        // zerlegt = TRUE, hier ist einzige Stelle, wo T zerlegt wird.
487        zerlegt = 1;
488        return(list(T1,T2));
489    }
490    else                      // ansonsten Quasi-Inverses gefunden.
491    {
492        return(list(b,g));
493    }
494}
495
496///////////////////////////////////////////////////////////////////////////////
497
498static proc Erw_ggt_oT (poly f, poly g, int v, ideal T)
499"USAGE:   Erw_ggt_oT(f,g,v,T);  f,g Polynome in var(v), f > g,
500                               T Dreiecksbasis mit groesster
501                               Variable var(v+1).
502RETURN:  Liste aus drei Polynomen d,a,b, wobei
503         a * f + b * g = d mod (T) und
504         (d + (T)) = ((f + (T), g + (T)).
505NOTE:    Dies ist der erweiterte euklidische Algorithmus im Polynom-
506         ring ueber dem Restklassenring modulo (T) in der Unbestimmten
507         var(v). Zusaetzlich wird jeweils der Dividend so normiert,
508         dass der Leitkoeffizient bzgl. var(v) im Grundring ist
509         und die Leikoeffizienten werden durch Anwendung der
510         Subresultant-remainder-sequence Variante des euklidischen
511         Algorithmus moeglichst klein gehalten.
512"
513{
514    // Initialisierung fuer erw. eukl. Algorithmus.
515    poly p1 = f;
516    poly p2 = g;
517    poly a1 = 1;
518    poly a2 = 0;
519    poly b1 = 0;
520    poly b2 = 1;
521
522    // Normierung des Dividenden.
523    list pab = normieren_oT(p2,a2,b2,v,T);
524    if (zerlegt) {return(pab);}
525    p2 = pab[1]; a2 = pab[2]; b2 = pab[3];
526
527    poly p3,a3,b3,q;  // Hilfspolynome
528    list rq;          // Rueckgabelisten der Fkten pdiv und normieren_oT
529    vector clden;
530
531    // Variablen fuer Subresultanten-Variante initialisieren.
532    int delta = degv(p1,v)-degv(p2,v);
533    number alpha;
534    number beta = (-1)**(delta + 1);
535    number psi = -1;
536    number m;
537
538    // Pseudodivision
539    rq = pdiv(p1,p2,v);
540    q  = rq[2];
541    p3 = reduce(rq[1],T);
542
543    while (p3 <> 0)   // Hauptschleife des eukl. Algorithmus.
544    {
545        alpha = number(lcoef(p2,v));  // return von lcoef ist type poly
546        m  = alpha**(delta + 1);   //m*p1 = q*p2 + p3  mod (T)
547        p3 = p3 / beta;            //m*p1 = q*p2 + beta * p3  mod (T)
548
549        // a und b anpassen.
550        q  = reduce(q,T);
551        a3 = reduce(m*a1 - q*a2,T);
552        b3 = reduce(m*b1 - q*b2,T);
553        a3 = a3 / beta;
554        b3 = b3 / beta;
555
556        // Variablen tauschen.
557        p1 = p2;
558        p2 = p3;
559        a1 = a2;
560        a2 = a3;
561        b1 = b2;
562        b2 = b3;
563
564        // Normierung des Dividenden.
565        pab = normieren_oT(p2,a2,b2,v,T);
566        if (zerlegt) {return(pab);}
567        p2 = pab[1]; a2 = pab[2]; b2 = pab[3];
568
569        if (degv(p2,v) > 0)     // Dividend aus Grundring?, dann
570        {                       // Subresultanten-Variabeln anpassen
571            if (delta > 0)
572            {
573                psi = ((-alpha)**delta) / (psi**(delta-1));
574            }
575            delta = degv(p1,v)-degv(p2,v);
576            beta  = (-alpha) * (psi**delta);
577
578            rq = pdiv(p1,p2,v); // und Pseudodivision,
579            q  = rq[2];
580            p3 = reduce(rq[1], T);
581        }
582        else                    // ansonsten Ende.
583        {
584            p3 = 0;
585        }
586    }
587
588    // Gemeinsame Teiler herausdividieren.
589    clden = cleardenom([p2,a2,b2]);
590    return(list(clden[1],clden[2],clden[3]));
591}
592
593///////////////////////////////////////////////////////////////////////////////
594
595static proc normieren_oT (poly p, poly a, poly b, int v, ideal T)
596"USAGE:   normieren_oT(p,a,b,v,T); p,a,b Polynome in var(v),
597                                  T Dreiecksbasis.
598RETURN:  Entweder Triangulierung [T1,T2] von (T) oder
599         Liste,wobei [1] = reduce(r*p,T),
600                     [2] = reduce(r*a,T),
601                     [3] = reduce(r*b,T),
602         und reduce(r*lcoef(p,v),T) ist im Grundring.
603"
604{
605    poly lc = lcoef(p,v);
606    if (deg(lc) == 0) {return(list(p,a,b));} // lc im Grundring
607    lc = cleardenom(lc);
608
609    // invertieren_oT aufrufen, um lc+(T) zu invertieren.
610    list inv = invertieren_oT(lc,T);
611    if (zerlegt) {return(inv);}
612
613    // ansonsten Polynom zurueck gekommen.
614    p = reduce(inv[1] * p,T);
615    a = reduce(inv[1] * a,T);
616    b = reduce(inv[1] * b,T);
617    return(list(p,a,b));
618}
619
620
621///////////////////////////////////////////////////////////////////////////////
622//
623//  Der Moeller-Algorithmus
624//
625///////////////////////////////////////////////////////////////////////////////
626
627proc triangM (ideal G, list #)
628"USAGE:   triangM(G[,i]); G=ideal, i=integer,@*
629ASSUME:  G is the reduced lexicographical Groebner bases of the
630         zero-dimensional ideal (G), sorted by increasing leading terms.
631RETURN:  a list of finitely many triangular systems, such that
632         the union of their varieties equals the variety of (G).
633         If i = 2, then each polynomial of the triangular systems
634         is factorized.
635NOTE:    Algorithm of Moeller (see: Moeller, H.M.:
636         On decomposing systems of polynomial equations with
637         finitely many solutions, Appl. Algebra Eng. Commun. Comput. 4,
638         217 - 230, 1993).
639EXAMPLE: example triangM; shows an example
640"
641{
642    // Test, ob G Groebnerbasis ist.
643    if (attrib(G,"isSB") <> 1)
644    {
645        print("   ? Error: The input is no groebner bases.");
646        return();
647    }
648
649    // Faktorisierungsschalter setzen.
650    int fak;
651    if (size(#) > 0 && typeof(#[1]) == "int")
652    {
653        if (#[1] == 2) {fak = 1;}
654    }
655
656    // Noetige Optionen setzen.
657    // obachman: save options so that they can be reset on exit
658    intvec ovec = option(get);
659    option(redSB);
660    option(returnSB);
661
662    list F,Fh;       // Ergebnislisten
663    int nG = size(G);
664    if (nG <= 2)     // G schon Dreiecksbasis?
665    {
666        if (fak)
667        {
668            F = faktorisiere_DB(G);
669        }
670        else
671        {
672            F = list(G);
673        }
674        option(set, ovec);
675        return(F);
676    }
677
678    int u = lvar(G[nG-1]);
679    int v = lvar(G[nG]);
680    int m = nG;
681    int l;
682    ideal lc,G1,G2,H;
683    poly lcr;
684    int i,j,k;
685      string s = string(nvars(basering)-v+1); // fuer Protokoll
686
687    // Oberes Dreieckssytem abschneiden.
688    while(u <> v)
689    {
690        m = m-1;
691        if (m == 2)  // G ist bereits Dreiecksbasis.
692        {
693            if (fak)
694            {
695                F = faktorisiere_DB(G);
696            }
697            else
698            {
699                F = list(G);
700            }
701            option(set, ovec);
702            return (F);
703        }
704        v = u;
705        u = lvar(G[m-1]);
706    }
707
708    // Leitkoeffizienten der Polynome bzgl. var(u) bestimmen.
709    l = m-1;
710    while(u == v)
711    {
712        lc = lc + lcoef(G[l],u);
713        l  = l - 1;
714        u  = lvar(G[l]);
715    }
716
717    // Erster Teil des Splitts.
718    G1 = sort_red(ideal(G[1..l]) + lc); // Sortiere und reduziere GB.
719
720      s = string(nvars(basering)-v+1);
721      dbprint(string(timer)+" S"+s+": Erster Teil des Splitts.");
722
723    // Rekursiver Aufruf, um G1 zu triangulieren.
724    F = triangM(G1,#);
725
726      dbprint(string(timer)+" S"+s+": Oberes Dreieckssystem anhaengen.");
727
728    // Oberes Dreieckssystem an jede berechnete Dreiecksbasis anhaengen.
729    for (j = m; j <= nG; j++)  // meist nur j = m = nG
730    {
731        for (i = 1; i <= size(F); i++)
732        {
733            F[i] = F[i] + cleardenom(G[j][1] + reduce(G[j]-G[j][1],F[i]));
734            attrib(F[i],"isSB",1);
735        }
736        if (fak)
737        {
738            F = faktorisiere_letzten(F);
739        }
740    }
741
742        dbprint(string(timer)+" S"+s+": Zweiter Teil des Splitts, "+string(m-l-1)+" Leitkoeffizient(en).");
743
744    // Zweiten Teil des Splitts berechnen.
745    H = ideal(G[1..m]);
746    attrib(H,"isSB",1);
747
748    for (k = m-l-1; k >= 1; k--)  // Leitkoeffizientenliste durchgehen,
749    {                             // angefangen mit lc des kleinsten Polynoms.
750        lcr = reduce(lc[k],H);
751        if (lcr <> 0)             // d.h. (H):lcr <> (1)
752        {
753              dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Berechnung Idealquotient.");
754            G2 = quotient(H,lcr); // Wg. Option returnSB schon Standardbasis.
755            attrib(G2,"isSB",1);
756
757              dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Rekursiver Aufruf.");
758            // Rekursiver Aufruf, um G2 zu triangulieren.
759            Fh = triangM(G2,#);
760
761              dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Oberes Dreieckssystem, falls vorhanden, anhaengen.");
762            // Oberes Dreieckssystem, falls vorhanden,
763            // an jede berechnete Dreiecksbasis anhaengen.
764            for (j = m + 1; j <= nG; j++)
765            {
766                for (i = 1; i <= size(Fh); i++)
767                {
768                    Fh[i] = Fh[i] + cleardenom(G[j][1] +
769                                    reduce(G[j]-G[j][1],Fh[i]));
770                    attrib(Fh[i],"isSB",1);
771                }
772                if (fak)
773                {
774                    Fh = faktorisiere_letzten(Fh);
775                }
776            }
777            F = F + Fh;
778            if (k > 1)
779            {
780                  dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Lex. GB von (H + lc) berechnen, n„chsten lc reduzieren.");
781                H = std(H + lcr); // Wg. reduce(...,H) oben notwendig.
782            }
783        }
784        else
785        {
786              dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Leere Variet„t.");
787        }
788    }
789
790    // Singular loescht die Attribute beim Listenverketten, deswegen neu setzen.
791    for (i = 1; i <= size(F); i++)
792    {
793        attrib(F[i],"isSB",1);
794    }
795    option(set, ovec);
796    return(F);
797}
798//-------------------------------- example----------------------------------
799example
800{ "EXAMPLE:"; echo = 2;
801   ring rC5 = 0,(e,d,c,b,a),lp;
802   triangM(stdfglm(cyclic(5))); //oder: triangM(stdfglm(cyclic(5)),2);
803}
804
805///////////////////////////////////////////////////////////////////////////////
806
807proc triangMH (ideal G, list #)
808"USAGE:   triangMH(G[,i]); G=ideal, i=integer
809ASSUME:  G is the reduced lexicographical Groebner bases of the
810         zero-dimensional ideal (G), sorted by increasing leading terms.
811RETURN:  a list of finitely many triangular systems, such that
812         the disjoint union of their varieties equals the variety of (G).
813         If i = 2, then each polynomial of the triangular systems is factorized.
814NOTE:    Algorithm of Moeller and Hillebrand (see: Moeller, H.M.:
815         On decomposing systems of polynomial equations with finitely many
816         solutions, Appl. Algebra Eng. Commun. Comput. 4, 217 - 230, 1993 and
817         Hillebrand, D.: Triangulierung nulldimensionaler Ideale -
818         Implementierung und Vergleich zweier Algorithmen, master thesis,
819         Universitaet Dortmund, Fachbereich Mathematik, Prof. Dr. H.M. Moeller,
820         1999).
821EXAMPLE: example triangMH; shows an example
822"
823{
824    // Test, ob G Groebnerbasis ist.
825    if (attrib(G,"isSB") <> 1)
826    {
827        print("   ? Error: The input is no groebner bases.");
828        return();
829    }
830
831    // Faktorisierungsschalter setzen.
832    int fak;
833    if (size(#) > 0 && typeof(#[1]) == "int")
834    {
835        if (#[1] == 2) {fak = 1;}
836    }
837
838    // Noetige Optionen setzen.
839    // obachman: save options so that tey can be reset on exit
840    intvec ovec = option(get);
841    option(redSB);
842    option(returnSB);
843
844    list F,Fh;       // Ergebnislisten
845    int nG = size(G);
846    if (nG <= 2)     // G schon Dreiecksbasis?
847    {
848        if (fak)
849        {
850            F = faktorisiere_DB(G);
851        }
852        else
853        {
854            F = list(G);
855        }
856        option(set, ovec);
857        return(F);
858    }
859
860    int u = lvar(G[nG-1]);
861    int v = lvar(G[nG]);
862    int m = nG;
863    int l;
864    poly lcr;
865    ideal lc,G1,G2,H;
866    int i,j,k;
867      string s = string(nvars(basering)-v+1); // fuer Protokoll
868
869    // Oberes Dreieckssytem abschneiden.
870    while(u <> v)
871    {
872        m = m-1;
873        if (m == 2)  // G ist Dreiecksbasis.
874        {
875            if (fak)
876            {
877                F = faktorisiere_DB(G);
878            }
879            else
880            {
881                F = list(G);
882            }
883            option(set, ovec);
884            return(F);
885         }
886        v = u;
887        u = lvar(G[m-1]);
888    }
889
890    // Leitkoeffizienten der Polynome bzgl. var(u) bestimmen.
891    l = m-1;
892    while(u == v)
893    {
894        lc = lc + lcoef(G[l],u);
895        l  = l - 1;
896        u  = lvar(G[l]);
897    }
898
899    // Erster Teil des Splitts.
900    G1 = sort_red(ideal(G[1..l]) + lc); // Sortiere und reduziere GB.
901
902      s = string(nvars(basering)-v+1);
903      dbprint(string(timer)+" S"+s+": Erster Teil des Splitts.");
904
905    // Rekursiver Aufruf, um G1 zu triangulieren.
906    F = triangMH(G1,#);
907
908      dbprint(string(timer)+" S"+s+": Oberes Dreieckssystem anhaengen.");
909
910    // Oberes Dreieckssystem an jede berechnete Dreiecksbasis anhaengen.
911    for (j = m; j <= nG; j++)  // meist nur j = m = nG
912    {
913        for (i = 1; i <= size(F); i++)
914        {
915            F[i] = F[i] + cleardenom(G[j][1] + reduce(G[j]-G[j][1],F[i]));
916            attrib(F[i],"isSB",1);
917        }
918        if (fak)
919        {
920            F = faktorisiere_letzten(F);
921        }
922    }
923
924        dbprint(string(timer)+" S"+s+": Zweiter Teil des Splitts, "+string(m-l-1)+" Leitkoeffizient(en).");
925
926    // Zweiten Teil des Splitts berechnen.
927    H = ideal(G[1..l]);   // Nur die Polynome in var(u).
928    attrib(H,"isSB",1);
929
930    for (k = m-l-1; k >= 1; k--)  // Leitkoeffizientenliste durchgehen,
931    {                             // angefangen mit lc des kleinsten Polynoms.
932        lcr = reduce(lc[k],H);
933        if (lcr <> 0)             // d.h. (H):lcr <> (1)
934        {
935              dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Berechnung Saturation.");
936            G2 = sat(H,lcr)[1];     // Saturation statt Idealquotient.
937            attrib(G2,"isSB",1);
938
939            if (G2[1] <> 1)
940            {
941                  dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Rekursiver Aufruf.");
942                // Rekursiver Aufruf, um G2 zu triangulieren.
943                Fh = triangMH(G2,#);
944
945                  dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Ggt und oberes Dreieckssystem anhaengen.");
946                // Ggt an jede Dreiecksbasis anhaengen.
947                for (i = 1; i <= size(Fh); i++)
948                {
949                    Fh[i] = std(Fh[i] + G[m-k]);
950                }
951                if (fak)
952                {
953                    Fh = faktorisiere_letzten(Fh);
954                }
955                for (j = m+1; j <= nG; j++)  // oberes Dreieckssystem an jede
956                {                            // berechnete Dreiecksbasis anhaengen
957                    for (i = 1; i <= size(Fh); i++)
958                    {
959                        Fh[i] = Fh[i] + cleardenom(G[j][1]
960                                      + reduce(G[j]-G[j][1],Fh[i]));
961                        attrib(Fh[i],"isSB",1);
962                    }
963                    if (fak)
964                    {
965                        Fh = faktorisiere_letzten(Fh);
966                    }
967                }
968                F = F + Fh;
969            }
970            else
971            {
972                  dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Leere Variet„t (G2 == (1)).");
973            }
974            if (k > 1)
975            {
976                  dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Lex. GB von (H + lc) berechnen, n„chsten lc reduzieren.");
977                H = std(H + lcr); // wegen reduce(...,H) oben
978            }
979        }
980        else
981        {
982              dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Leere Variet„t (lcr == 0).");
983        }
984    }
985
986    // Singular loescht die Attribute beim Listenverketten, deswegen neu setzen.
987    for (i = 1; i <= size(F); i++)
988    {
989        attrib(F[i],"isSB",1);
990    }
991    option(set, ovec);
992    return(F);
993}
994//-------------------------------- example ----------------------------------
995example
996{ "EXAMPLE:"; echo = 2;
997   ring rC5 = 0,(e,d,c,b,a),lp;
998   triangMH(stdfglm(cyclic(5)));
999}
1000
1001
1002///////////////////////////////////////////////////////////////////////////////
1003//
1004//  Hilfsfunktionen
1005//
1006///////////////////////////////////////////////////////////////////////////////
1007
1008static proc sort_red (ideal G)
1009"USAGE:   sort_red(G);  G lexikographische Groebnerbasis.
1010RETURN:  reduzierte lex. GB G, deren Elemente nach aufsteigenden
1011         Leittermen sortiert sind.
1012"
1013{
1014    int i;
1015
1016    // sortieren
1017    G = sort(G)[1];
1018
1019    // reduzieren
1020    ideal Gred = cleardenom(G[1]);
1021    attrib(Gred,"isSB",1);
1022
1023    for (i = 2; i <= size(G); i++)
1024    {
1025        Gred = Gred + cleardenom(reduce(G[i],Gred));
1026        attrib(Gred,"isSB",1);
1027    }
1028    attrib(Gred,"isSB",1);
1029    return(Gred);
1030}
1031
1032///////////////////////////////////////////////////////////////////////////////
1033
1034static proc Listenrest (list Liste)
1035"USAGE:   Listenrest(Liste); Liste muss eine mindestens einelementige
1036                            Liste sein (leere Liste ergibt Fehler).
1037RETURN:  Liste ohne das erste Element.
1038"
1039{
1040    return(delete(Liste,1));
1041}
1042
1043///////////////////////////////////////////////////////////////////////////////
1044
1045static proc Idealrest (ideal i)
1046"USAGE:   Idealrest(i); i Ideal, i <> (0).
1047RETURN:  Ideal i ohne das erste Element bzw das Nullideal,
1048         falls i nur ein Erzeugendes besass.
1049"
1050{
1051    int ni = size(i);
1052    if (ni == 1)
1053    {
1054        return(ideal(0));    // Nullideal
1055    }
1056    return(ideal(i[2..ni]));
1057}
1058
1059///////////////////////////////////////////////////////////////////////////////
1060
1061static proc H_anhaengen (list L, int h)
1062"USAGE:   H_anhaengen(L,h); L Liste aus Idealen, h natuerliche Zahl.
1063RETURN:  Macht aus dem Listenelement i ein Paar [i,h] und setzt
1064         Attribut "isSB" fuer i.
1065"
1066{
1067    int i;
1068    list E; // Ergebnisliste
1069
1070    for (i = 1; i <= size(L); i++)
1071    {
1072        E = E + list(list(L[i],h));
1073        attrib(E[size(E)][1],"isSB",1);
1074    }
1075    return(E);
1076}
1077
1078///////////////////////////////////////////////////////////////////////////////
1079
1080static proc faktorisiere_letzten (list L)
1081"USAGE:   faktorisiere_letzten(L); L Liste aus Idealen.
1082RETURN:  Faktorisiert letztes Polynom aus jedem Ideal der Liste und
1083         zerlegt das Ideal entsprechend. Attribut "isSB" wird gesetzt.
1084"
1085{
1086    int i,j;
1087    ideal h;
1088    int nh;
1089    list factors;
1090    list E;   // Ergebnisliste
1091    for (i = 1; i <= size(L); i++)
1092    {
1093        h = L[i];
1094        nh = size(h);
1095        factors = factorize(h[nh],1);
1096        for (j = 1; j <= size(factors[1]); j++)
1097        {
1098            h[nh] = factors[1][j];
1099            E = insert(E,h,size(E));
1100            attrib(E[size(E)],"isSB",1);
1101        }
1102    }
1103    return(E);
1104}
1105
1106///////////////////////////////////////////////////////////////////////////////
1107
1108static proc faktorisiere_DB (ideal db)
1109"USAGE:   faktorisiere_DB(db); db reduzierte Dreiecksbasis.
1110RETURN:  Liste aus reduzierten Dreiecksbasen,
1111         die ensteht, indem, mit dem ersten beginnend,
1112         jedes Polynom der Dreiecksbasis faktorisiert wird.
1113"
1114{
1115    int i,j;
1116    poly h;
1117    list E = faktorisiere_letzten(db[1]);
1118
1119    for (j = 2; j <= size(db); j++)
1120    {
1121        for (i = 1; i <= size(E); i++)
1122        {
1123            h    = db[j][1] + reduce(db[j]-db[j][1],E[i]);
1124            E[i] = E[i] + h;
1125        }
1126        E = faktorisiere_letzten(E);
1127    }
1128    return(E);
1129}
1130
1131///////////////////////////////////////////////////////////////////////////////
1132
1133static proc degv (poly f, int v)
1134"USAGE:   degv(f,v);  f Polynom in var(v).
1135RETURN:  Liefert den Grad von f bzgl. var(v) bzw -1, falls f == 0.
1136"
1137{
1138    if (f == 0) {return(-1);}
1139    return(size(coeffs(f,var(v))) - 1);
1140}
1141
1142//////////////////////////////////////////////////////////////////////////////
1143
1144static proc pdiv (poly f, poly g, int v)
1145"USAGE:   pdiv(f,g);  f,g Polynome in var(v), f > g.
1146RETURN:  Liste, wobei [1] = prem(f,g) (Pseudoremainder),
1147                      [2] = pquo(f,g) (Pseudoquotient).
1148NOTE:    Pseudodivision von f durch g.
1149"
1150{
1151    // Initialisierung
1152    poly q      = 0;
1153    poly rem    = f;
1154    int deg_g   = degv(g,v);
1155    int deg_rem = degv(rem,v);
1156    poly lcg    = lcoef(g,v);     // Im Lazard-Algor. aus dem Grundring.
1157    poly h;
1158    rem = rem*lcg**(deg_rem - deg_g + 1); // f durch g teilbar machen.
1159
1160    // Gewoehnliche Polynomdivision
1161    while (rem <> 0 and deg_rem >= deg_g)
1162    {
1163        h       = (lcoef(rem,v)/lcg)*var(v)**(deg_rem - deg_g);
1164        q       = q + h;
1165        rem     = rem - h*g;
1166        deg_rem = degv(rem,v);
1167    }
1168    return(list(rem,q));
1169}
1170
1171//////////////////////////////////////////////////////////////////////////////
1172
1173static proc lvar (poly f)
1174"USAGE:   lvar(f);  f nicht-konstantes Polynom.
1175RETURN:  groesste Variable von f bzgl. der aktuellen Termordnung.
1176"
1177{
1178    int i = 1;
1179    intvec exp = leadexp(f);
1180
1181    while (1)
1182    {
1183        if (exp[i] <> 0) {return(i);}
1184        i++;
1185    }
1186}
1187
1188//////////////////////////////////////////////////////////////////////////////
1189
1190static proc lcoef (poly f, int v)
1191"USAGE:   lcoef(f,v);  f Polynom, var(v) Ringvariable.
1192RETURN:  Leitkoeffizient von f bzgl. var(v).
1193"
1194{
1195    matrix m = coeffs(f,var(v));
1196    return(m[size(m),1]);
1197}
1198///////////////////////////////////////////////////////////////////////////////
1199
Note: See TracBrowser for help on using the repository browser.