source: git/Singular/fglm.cc @ 6e56de

spielwiese
Last change on this file since 6e56de was c232af, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* omalloc stuff git-svn-id: file:///usr/local/Singular/svn/trunk@4524 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.4 KB
Line 
1// emacs edit mode for this file is -*- C++ -*-
2// $Id: fglm.cc,v 1.21 2000-08-14 12:56:12 obachman Exp $
3
4/****************************************
5*  Computer Algebra System SINGULAR     *
6****************************************/
7/*
8* ABSTRACT - The FGLM-Algorithm plus extension
9*   Calculate a reduced groebner basis for one ordering, given a
10*   reduced groebner basis for another ordering.
11*   In this file the input is checked. Furthermore we decide, if
12*   the input is 0-dimensional ( then fglmzero.cc is used ) or
13*   if the input is homogeneous ( then fglmhom.cc is used. Yet
14*   not implemented ).
15*   The extension (finduni) finds minimal univariate Polynomials
16*   lying in a 0-dimensional ideal.
17*/
18
19#include "mod2.h"
20
21#ifdef HAVE_FGLM
22#include "tok.h"
23#include "structs.h"
24#include "polys.h"
25#include "ideals.h"
26#include "ring.h"
27#include "ipid.h"
28#include "ipshell.h"
29#include "febase.h"
30#include "maps.h"
31#include <omalloc.h>
32#include "kstd1.h"
33#include "fglm.h"
34
35// internal Version: 1.18.1.6
36//     enumeration to handle the various errors to occour.
37enum FglmState{
38    FglmOk,
39    FglmHasOne,
40    FglmNoIdeal,
41    FglmNotReduced,
42    FglmNotZeroDim,
43    FglmIncompatibleRings,
44    // for fglmquot:
45    FglmPolyIsOne,
46    FglmPolyIsZero
47};
48
49// Has to be called, if currQuotient != NULL. ( i.e. qring-case )
50// Then a new ideal is build, consisting of the generators of sourceIdeal
51// and the generators of currQuotient, which are completely reduced by
52// the sourceIdeal. This means: If sourceIdeal is reduced, then the new
53// ideal will be reduced as well.
54// Assumes that currRing == sourceRing
55ideal fglmUpdatesource( const ideal sourceIdeal )
56{
57    int k, l, offset;
58    BOOLEAN found;
59    ideal newSource= idInit( IDELEMS( sourceIdeal ) + IDELEMS( currQuotient ), 1 );
60    for ( k= IDELEMS( sourceIdeal )-1; k >=0; k-- )
61        (newSource->m)[k]= pCopy( (sourceIdeal->m)[k] );
62    offset= IDELEMS( sourceIdeal );
63    for ( l= IDELEMS( currQuotient )-1; l >= 0; l-- ) {
64        if ( (currQuotient->m)[l] != NULL ) {
65            found= FALSE;
66            for ( k= IDELEMS( sourceIdeal )-1; (k >= 0) && (found == FALSE); k-- )
67                if ( pDivisibleBy( (sourceIdeal->m)[k], (currQuotient->m)[l] ) )
68                    found= TRUE;
69            if ( ! found ) {
70                (newSource->m)[offset]= pCopy( (currQuotient->m)[l] );
71                offset++;
72            }
73        }
74    }
75    idSkipZeroes( newSource );
76    return newSource;
77}
78
79// Has to be called, if currQuotient != NULL, i.e. in qring-case.
80// Gets rid of the elements of result which are contained in
81// currQuotient and skips Zeroes.
82// Assumes that currRing == destRing
83void
84fglmUpdateresult( ideal & result )
85{
86    int k, l;
87    BOOLEAN found;
88    for ( k= IDELEMS( result )-1; k >=0; k-- ) {
89        if ( (result->m)[k] != NULL ) {
90            found= FALSE;
91            for ( l= IDELEMS( currQuotient )-1; (l >= 0) && ( found == FALSE ); l-- )
92                if ( pDivisibleBy( (currQuotient->m)[l], (result->m)[k] ) )
93                    found= TRUE;
94            if ( found ) pDelete( & ((result->m)[k]) );
95        }
96    }
97    idSkipZeroes( result );
98}
99
100// Checks if the two rings sringHdl and dringHdl are compatible enough to
101// be used for the fglm. This means:
102//  1) Same Characteristic, 2) globalOrderings in both rings,
103//  3) Same number of variables, 4) same number of parameters
104//  5) variables in one ring are permutated variables of the other one
105//  6) parameters in one ring are permutated parameters of the other one
106//  7) either both rings are rings or both rings are qrings
107//  8) if they are qrings, the quotientIdeals of both must coincide.
108// vperm must be a vector of length pVariables+1, initialized by 0.
109// If both rings are compatible, it stores the permutation of the
110// variables if mapped from sringHdl to dringHdl.
111// if the rings are compatible, it returns FglmOk.
112// Should be called with currRing= IDRING( sringHdl );
113FglmState
114fglmConsistency( idhdl sringHdl, idhdl dringHdl, int * vperm )
115{
116    int k;
117    FglmState state= FglmOk;
118    ring dring = IDRING( dringHdl );
119    ring sring = IDRING( sringHdl );
120
121    if ( rChar(sring) != rChar(dring) ) {
122        WerrorS( "rings must have same characteristic" );
123        state= FglmIncompatibleRings;
124    }
125    if ( (sring->OrdSgn != 1) || (dring->OrdSgn != 1) ) {
126        WerrorS( "only works for global orderings" );
127        state= FglmIncompatibleRings;
128    }
129    if ( sring->N != dring->N )
130    {
131        WerrorS( "rings must have same number of variables" );
132        state= FglmIncompatibleRings;
133    }
134    if ( rPar(sring) != rPar(dring) )
135    {
136        WerrorS( "rings must have same number of parameters" );
137        state= FglmIncompatibleRings;
138    }
139    if ( state != FglmOk ) return state;
140    // now the rings have the same number of variables resp. parameters.
141    // check if the names of the variables resp. parameters do agree:
142    int nvar = sring->N;
143    int npar = rPar(sring);
144    int * pperm;
145    if ( npar > 0 )
146        pperm= (int *)omAlloc0( (npar+1)*sizeof( int ) );
147    else
148        pperm= NULL;
149    maFindPerm( sring->names, nvar, sring->parameter, npar, 
150                dring->names, nvar, dring->parameter, npar, vperm, pperm, 
151                dring->ch);
152    for ( k= nvar; (k > 0) && (state == FglmOk); k-- )
153        if ( vperm[k] <= 0 ) {
154            WerrorS( "variable names do not agree" );
155            state= FglmIncompatibleRings;
156        }
157    for ( k= npar-1; (k >= 0) && (state == FglmOk); k-- )
158        if ( pperm[k] >= 0 ) {
159            WerrorS( "paramater names do not agree" );
160            state= FglmIncompatibleRings;
161        }
162    if (pperm != NULL) // OB: ????
163      omFreeSize( (ADDRESS)pperm, (npar+1)*sizeof( int ) );
164    if ( state != FglmOk ) return state;
165    // check if both rings are qrings or not
166    if ( sring->qideal != NULL ) {
167        if ( dring->qideal == NULL ) {
168            Werror( "%s is a qring, current ring not", sringHdl->id );
169            return FglmIncompatibleRings;
170        }
171        // both rings are qrings, now check if both quotients define the same ideal.
172        // check if sring->qideal is contained in dring->qideal:
173        rSetHdl( dringHdl, TRUE );
174        //nSetMap( rInternalChar(sring), sring->parameter, npar, sring->minpoly );
175        nSetMap( sring );
176        ideal sqind = idInit( IDELEMS( sring->qideal ), 1 );
177        for ( k= IDELEMS( sring->qideal )-1; k >= 0; k-- )
178            (sqind->m)[k]= pPermPoly( (sring->qideal->m)[k], vperm, sring);
179        ideal sqindred = kNF( dring->qideal, NULL, sqind );
180        if ( ! idIs0( sqindred ) ) {
181            WerrorS( "the quotients do not agree" );
182            state= FglmIncompatibleRings;
183        }
184        idDelete( & sqind );
185        idDelete( & sqindred );
186        rSetHdl( sringHdl, TRUE );
187        if ( state != FglmOk ) return state;
188        // check if dring->qideal is contained in sring->qideal:
189        int * dsvperm = (int *)omAlloc0( (nvar+1)*sizeof( int ) );
190        maFindPerm( dring->names, nvar, NULL, 0, sring->names, nvar, NULL, 0, 
191                    dsvperm, NULL, sring->ch);
192        //nSetMap(rInternalChar(dring), dring->parameter, npar, dring->minpoly);
193        nSetMap(dring);
194        ideal dqins = idInit( IDELEMS( dring->qideal ), 1 );
195        for ( k= IDELEMS( dring->qideal )-1; k >= 0; k-- )
196            (dqins->m)[k]= pPermPoly( (dring->qideal->m)[k], dsvperm, sring);
197        ideal dqinsred = kNF( sring->qideal, NULL, dqins );
198        if ( ! idIs0( dqinsred ) ) {
199            WerrorS( "the quotients do not agree" );
200            state= FglmIncompatibleRings;
201        }
202        idDelete( & dqins );
203        idDelete( & dqinsred );
204        omFreeSize( (ADDRESS)dsvperm, (nvar+1)*sizeof( int ) );
205        if ( state != FglmOk ) return state;
206    }
207    else {
208        if ( dring->qideal != NULL ) {
209            Werror( "current ring is a qring, %s not", sringHdl->id );
210            return FglmIncompatibleRings;
211        }
212    }
213    return FglmOk;
214}
215
216// Checks if the ideal "theIdeal" is zero-dimensional and minimal. It does
217//  not check, if it is reduced.
218// returns FglmOk if we can use theIdeal for CalculateFunctionals (this
219//                 function reports an error if theIdeal is not reduced,
220//                 so this need not to be tested here)
221//         FglmNotReduced if theIdeal is not minimal
222//         FglmNotZeroDim if it is not zero-dimensional
223//         FglmHasOne if 1 belongs to theIdeal
224FglmState
225fglmIdealcheck( const ideal theIdeal )
226{
227    FglmState state = FglmOk;
228    int power;
229    int k;
230    BOOLEAN * purePowers = (BOOLEAN *)omAlloc( pVariables*sizeof( BOOLEAN ) );
231    for ( k= pVariables-1; k >= 0; k-- )
232        purePowers[k]= FALSE;
233
234    for ( k= IDELEMS( theIdeal ) - 1; (state == FglmOk) && (k >= 0); k-- ) {
235        poly p = (theIdeal->m)[k];
236        if ( pIsConstant( p ) ) state= FglmHasOne;
237        else if ( (power= pIsPurePower( p )) > 0 ) {
238            fglmASSERT( 0 < power && power <= pVariables, "illegal power" );
239            if ( purePowers[power-1] == TRUE  ) state= FglmNotReduced;
240            else purePowers[power-1]= TRUE;
241        }
242        for ( int l = IDELEMS( theIdeal ) - 1; state == FglmOk && l >= 0; l-- )
243            if ( (k != l) && pDivisibleBy( p, (theIdeal->m)[l] ) )
244                state= FglmNotReduced;
245    }
246    if ( state == FglmOk ) {
247        for ( k= pVariables-1 ; (state == FglmOk) && (k >= 0); k-- )
248            if ( purePowers[k] == FALSE ) state= FglmNotZeroDim;
249    }
250    omFreeSize( (ADDRESS)purePowers, pVariables*sizeof( BOOLEAN ) );
251    return state;
252}
253
254// The main function for the fglm-Algorithm.
255// Checks the input-data, and calls fglmzero (see fglmzero.cc).
256// Returns the new groebnerbasis or 0 if an error occoured.
257BOOLEAN
258fglmProc( leftv result, leftv first, leftv second )
259{
260    FglmState state = FglmOk;
261
262    idhdl destRingHdl = currRingHdl;
263    ring destRing = currRing;
264    ideal destIdeal = NULL;
265    idhdl sourceRingHdl = (idhdl)first->data;
266    rSetHdl( sourceRingHdl, TRUE );
267    ring sourceRing = currRing;
268
269    int * vperm = (int *)omAlloc0( (pVariables+1)*sizeof( int ) );
270    state= fglmConsistency( sourceRingHdl, destRingHdl, vperm );
271    omFreeSize( (ADDRESS)vperm, (pVariables+1)*sizeof(int) );
272
273    if ( state == FglmOk ) {
274        idhdl ih = currRing->idroot->get( second->Name(), myynest );
275        if ( (ih != NULL) && (IDTYP(ih)==IDEAL_CMD) ) {
276            ideal sourceIdeal;
277            if ( currQuotient != NULL )
278                sourceIdeal= fglmUpdatesource( IDIDEAL( ih ) );
279            else
280                sourceIdeal = IDIDEAL( ih );
281            state= fglmIdealcheck( sourceIdeal );
282            if ( state == FglmOk ) {
283                // Now the settings are compatible with FGLM
284                assumeStdFlag( (leftv)ih );
285                if ( fglmzero( sourceRingHdl, sourceIdeal, destRingHdl, destIdeal, FALSE, (currQuotient != NULL) ) == FALSE )
286                    state= FglmNotReduced;
287            }
288        } else state= FglmNoIdeal;
289    }
290    if ( currRingHdl != destRingHdl )
291        rSetHdl( destRingHdl, TRUE );
292    switch (state) {
293        case FglmOk:
294            if ( currQuotient != NULL ) fglmUpdateresult( destIdeal );
295            break;
296        case FglmHasOne:
297            destIdeal= idInit(1,1);
298            (destIdeal->m)[0]= pOne();
299            state= FglmOk;
300            break;
301        case FglmIncompatibleRings:
302            Werror( "ring %s and current ring are incompatible", first->Name() );
303            destIdeal= idInit(0,0);
304            break;
305        case FglmNoIdeal:
306            Werror( "Can't find ideal %s in ring %s", second->Name(), first->Name() );
307            destIdeal= idInit(0,0);
308            break;
309        case FglmNotZeroDim:
310            Werror( "The ideal %s has to be 0-dimensional", second->Name() );
311            destIdeal= idInit(0,0);
312            break;
313        case FglmNotReduced:
314            Werror( "The ideal %s has to be reduced", second->Name() );
315            destIdeal= idInit(0,0);
316            break;
317        default:
318            destIdeal= idInit(1,1);
319    }
320
321    result->rtyp = IDEAL_CMD;
322    result->data= (void *)destIdeal;
323    setFlag( result, FLAG_STD );
324    return (state != FglmOk);
325}
326
327// fglmQuotProc: Calculate I:f with FGLM methods.
328// Checks the input-data, and calls fglmquot (see fglmzero.cc).
329// Returns the new groebnerbasis if I:f or 0 if an error occoured.
330BOOLEAN
331fglmQuotProc( leftv result, leftv first, leftv second )
332{
333    FglmState state = FglmOk;
334
335    //    STICKYPROT("quotstart\n");
336    ideal sourceIdeal = IDIDEAL( (idhdl)first->data );
337    poly quot = (poly)second->Data();
338    ideal destIdeal = NULL;
339
340    state = fglmIdealcheck( sourceIdeal );
341    if ( state == FglmOk ) {
342      if ( quot == NULL ) state= FglmPolyIsZero;
343      else if ( pIsConstant( quot ) ) state= FglmPolyIsOne;
344    }
345   
346    if ( state == FglmOk ) {
347      assumeStdFlag( first );
348      if ( fglmquot( sourceIdeal, quot, destIdeal ) == FALSE )
349        state= FglmNotReduced;
350    }
351
352    switch (state) {
353        case FglmOk:
354            break;
355        case FglmHasOne:
356            destIdeal= idInit(1,1);
357            (destIdeal->m)[0]= pOne();
358            state= FglmOk;
359            break;
360        case FglmNotZeroDim:
361            Werror( "The ideal %s has to be 0-dimensional", first->Name() );
362            destIdeal= idInit(0,0);
363            break;
364        case FglmNotReduced:
365            Werror( "The poly %s has to be reduced", second->Name() );
366            destIdeal= idInit(0,0);
367            break;
368        case FglmPolyIsOne:
369            int k;
370            destIdeal= idInit( IDELEMS(sourceIdeal), 1 );
371            for ( k= IDELEMS( sourceIdeal )-1; k >=0; k-- )
372              (destIdeal->m)[k]= pCopy( (sourceIdeal->m)[k] );
373            state= FglmOk;
374            break;
375        case FglmPolyIsZero:
376            destIdeal= idInit(1,1);
377            (destIdeal->m)[0]= pOne();
378            state= FglmOk;
379            break;
380        default:
381            destIdeal= idInit(1,1);
382    }
383
384    result->rtyp = IDEAL_CMD;
385    result->data= (void *)destIdeal;
386    setFlag( result, FLAG_STD );
387    // STICKYPROT("quotend\n");
388    return (state != FglmOk);
389} // fglmQuotProt
390
391// The main function for finduni().
392// Checks the input-data, and calls FindUnivariateWrapper (see fglmzero.cc).
393// Returns an ideal containing the univariate Polynomials or 0 if an error
394// has occoured.
395BOOLEAN
396findUniProc( leftv result, leftv first )
397{
398    ideal sourceIdeal;
399    ideal destIdeal = NULL;
400    FglmState state;
401
402    idhdl sourceIdealHdl = (idhdl)first->data;
403    sourceIdeal= IDIDEAL(sourceIdealHdl);
404
405    assumeStdFlag( first );
406    state= fglmIdealcheck( sourceIdeal );
407    if ( state == FglmOk ) {
408        if ( FindUnivariateWrapper( sourceIdeal, destIdeal ) == FALSE )
409            state = FglmNotReduced;
410    }
411    switch (state) {
412        case FglmOk:
413            break;
414        case FglmHasOne:
415            destIdeal= idInit(1,1);
416            (destIdeal->m)[0]= pOne();
417            state= FglmOk;
418            break;
419        case FglmNotZeroDim:
420            Werror( "The ideal %s has to be 0-dimensional", first->Name() );
421            destIdeal= idInit(0,0);
422            break;
423        case FglmNotReduced:
424            Werror( "The ideal %s has to be reduced", first->Name() );
425            destIdeal= idInit(0,0);
426            break;
427        default:
428            destIdeal= idInit(1,1);
429    }
430
431    result->rtyp = IDEAL_CMD;
432    result->data= (void *)destIdeal;
433
434    return FALSE;
435}
436#endif
437// ----------------------------------------------------------------------------
438// Local Variables: ***
439// compile-command: "make Singular" ***
440// page-delimiter: "^\\(\\|//!\\)" ***
441// fold-internal-margins: nil ***
442// End: ***
Note: See TracBrowser for help on using the repository browser.