source: git/Singular/fglm.cc @ 907274

spielwiese
Last change on this file since 907274 was 811826, checked in by Olaf Bachmann <obachman@…>, 25 years ago
* maFindPerm: no permutation from Fq parameter to other vars/parameter (if they have the same name) -- r->ch new argument to maFindPerm. git-svn-id: file:///usr/local/Singular/svn/trunk@2894 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 13.3 KB
Line 
1// emacs edit mode for this file is -*- C++ -*-
2// $Id: fglm.cc,v 1.17 1999-03-09 12:28:45 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 "mmemory.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};
45
46// Has to be called, if currQuotient != NULL. ( i.e. qring-case )
47// Then a new ideal is build, consisting of the generators of sourceIdeal
48// and the generators of currQuotient, which are completely reduced by
49// the sourceIdeal. This means: If sourceIdeal is reduced, then the new
50// ideal will be reduced as well.
51// Assumes that currRing == sourceRing
52ideal fglmUpdatesource( const ideal sourceIdeal )
53{
54    int k, l, offset;
55    BOOLEAN found;
56    ideal newSource= idInit( IDELEMS( sourceIdeal ) + IDELEMS( currQuotient ), 1 );
57    for ( k= IDELEMS( sourceIdeal )-1; k >=0; k-- )
58        (newSource->m)[k]= pCopy( (sourceIdeal->m)[k] );
59    offset= IDELEMS( sourceIdeal );
60    for ( l= IDELEMS( currQuotient )-1; l >= 0; l-- ) {
61        if ( (currQuotient->m)[l] != NULL ) {
62            found= FALSE;
63            for ( k= IDELEMS( sourceIdeal )-1; (k >= 0) && (found == FALSE); k-- )
64                if ( pDivisibleBy( (sourceIdeal->m)[k], (currQuotient->m)[l] ) )
65                    found= TRUE;
66            if ( ! found ) {
67                (newSource->m)[offset]= pCopy( (currQuotient->m)[l] );
68                offset++;
69            }
70        }
71    }
72    idSkipZeroes( newSource );
73    return newSource;
74}
75
76// Has to be called, if currQuotient != NULL, i.e. in qring-case.
77// Gets rid of the elements of result which are contained in
78// currQuotient and skips Zeroes.
79// Assumes that currRing == destRing
80void
81fglmUpdateresult( ideal & result )
82{
83    int k, l;
84    BOOLEAN found;
85    for ( k= IDELEMS( result )-1; k >=0; k-- ) {
86        if ( (result->m)[k] != NULL ) {
87            found= FALSE;
88            for ( l= IDELEMS( currQuotient )-1; (l >= 0) && ( found == FALSE ); l-- )
89                if ( pDivisibleBy( (currQuotient->m)[l], (result->m)[k] ) )
90                    found= TRUE;
91            if ( found ) pDelete( & ((result->m)[k]) );
92        }
93    }
94    idSkipZeroes( result );
95}
96
97// Checks if the two rings sringHdl and dringHdl are compatible enough to
98// be used for the fglm. This means:
99//  1) Same Characteristic, 2) globalOrderings in both rings,
100//  3) Same number of variables, 4) same number of parameters
101//  5) variables in one ring are permutated variables of the other one
102//  6) parameters in one ring are permutated parameters of the other one
103//  7) either both rings are rings or both rings are qrings
104//  8) if they are qrings, the quotientIdeals of both must coincide.
105// vperm must be a vector of length pVariables+1, initialized by 0.
106// If both rings are compatible, it stores the permutation of the
107// variables if mapped from sringHdl to dringHdl.
108// if the rings are compatible, it returns FglmOk.
109// Should be called with currRing= IDRING( sringHdl );
110FglmState
111fglmConsistency( idhdl sringHdl, idhdl dringHdl, int * vperm )
112{
113    int k;
114    FglmState state= FglmOk;
115    ring dring = IDRING( dringHdl );
116    ring sring = IDRING( sringHdl );
117
118    if ( rChar(sring) != rChar(dring) ) {
119        WerrorS( "rings must have same characteristic" );
120        state= FglmIncompatibleRings;
121    }
122    if ( (sring->OrdSgn != 1) || (dring->OrdSgn != 1) ) {
123        WerrorS( "only works for global orderings" );
124        state= FglmIncompatibleRings;
125    }
126    if ( sring->N != dring->N )
127    {
128        WerrorS( "rings must have same number of variables" );
129        state= FglmIncompatibleRings;
130    }
131    if ( rPar(sring) != rPar(dring) )
132    {
133        WerrorS( "rings must have same number of parameters" );
134        state= FglmIncompatibleRings;
135    }
136    if ( state != FglmOk ) return state;
137    // now the rings have the same number of variables resp. parameters.
138    // check if the names of the variables resp. parameters do agree:
139    int nvar = sring->N;
140    int npar = rPar(sring);
141    int * pperm;
142    if ( npar > 0 )
143        pperm= (int *)Alloc0( (npar+1)*sizeof( int ) );
144    else
145        pperm= NULL;
146    maFindPerm( sring->names, nvar, sring->parameter, npar, 
147                dring->names, nvar, dring->parameter, npar, vperm, pperm, 
148                dring->ch);
149    for ( k= nvar; (k > 0) && (state == FglmOk); k-- )
150        if ( vperm[k] <= 0 ) {
151            WerrorS( "variable names do not agree" );
152            state= FglmIncompatibleRings;
153        }
154    for ( k= npar-1; (k >= 0) && (state == FglmOk); k-- )
155        if ( pperm[k] >= 0 ) {
156            WerrorS( "paramater names do not agree" );
157            state= FglmIncompatibleRings;
158        }
159    Free( (ADDRESS)pperm, (npar+1)*sizeof( int ) );
160    if ( state != FglmOk ) return state;
161    // check if both rings are qrings or not
162    if ( sring->qideal != NULL ) {
163        if ( dring->qideal == NULL ) {
164            Werror( "%s is a qring, current ring not", sringHdl->id );
165            return FglmIncompatibleRings;
166        }
167        // both rings are qrings, now check if both quotients define the same ideal.
168        // check if sring->qideal is contained in dring->qideal:
169        rSetHdl( dringHdl, TRUE );
170        nSetMap( rInternalChar(sring), sring->parameter, npar, sring->minpoly );
171        ideal sqind = idInit( IDELEMS( sring->qideal ), 1 );
172        for ( k= IDELEMS( sring->qideal )-1; k >= 0; k-- )
173            (sqind->m)[k]= pPermPoly( (sring->qideal->m)[k], vperm, sring);
174        ideal sqindred = kNF( dring->qideal, NULL, sqind );
175        if ( ! idIs0( sqindred ) ) {
176            WerrorS( "the quotients do not agree" );
177            state= FglmIncompatibleRings;
178        }
179        idDelete( & sqind );
180        idDelete( & sqindred );
181        rSetHdl( sringHdl, TRUE );
182        if ( state != FglmOk ) return state;
183        // check if dring->qideal is contained in sring->qideal:
184        int * dsvperm = (int *)Alloc0( (nvar+1)*sizeof( int ) );
185        maFindPerm( dring->names, nvar, NULL, 0, sring->names, nvar, NULL, 0, 
186                    dsvperm, NULL, sring->ch);
187        nSetMap(rInternalChar(dring), dring->parameter, npar, dring->minpoly);
188        ideal dqins = idInit( IDELEMS( dring->qideal ), 1 );
189        for ( k= IDELEMS( dring->qideal )-1; k >= 0; k-- )
190            (dqins->m)[k]= pPermPoly( (dring->qideal->m)[k], dsvperm, sring);
191        ideal dqinsred = kNF( sring->qideal, NULL, dqins );
192        if ( ! idIs0( dqinsred ) ) {
193            WerrorS( "the quotients do not agree" );
194            state= FglmIncompatibleRings;
195        }
196        idDelete( & dqins );
197        idDelete( & dqinsred );
198        Free( (ADDRESS)dsvperm, (nvar+1)*sizeof( int ) );
199        if ( state != FglmOk ) return state;
200    }
201    else {
202        if ( dring->qideal != NULL ) {
203            Werror( "current ring is a qring, %s not", sringHdl->id );
204            return FglmIncompatibleRings;
205        }
206    }
207    return FglmOk;
208}
209
210// Checks if the ideal "theIdeal" is zero-dimensional and minimal. It does
211//  not check, if it is reduced.
212// returns FglmOk if we can use theIdeal for CalculateFunctionals (this
213//                 function reports an error if theIdeal is not reduced,
214//                 so this need not to be tested here)
215//         FglmNotReduced if theIdeal is not minimal
216//         FglmNotZeroDim if it is not zero-dimensional
217//         FglmHasOne if 1 belongs to theIdeal
218FglmState
219fglmIdealcheck( const ideal theIdeal )
220{
221    FglmState state = FglmOk;
222    int power;
223    int k;
224    BOOLEAN * purePowers = (BOOLEAN *)Alloc( pVariables*sizeof( BOOLEAN ) );
225    for ( k= pVariables-1; k >= 0; k-- )
226        purePowers[k]= FALSE;
227
228    for ( k= IDELEMS( theIdeal ) - 1; (state == FglmOk) && (k >= 0); k-- ) {
229        poly p = (theIdeal->m)[k];
230        if ( pIsConstant( p ) ) state= FglmHasOne;
231        else if ( (power= pIsPurePower( p )) > 0 ) {
232            fglmASSERT( 0 < power && power <= pVariables, "illegal power" );
233            if ( purePowers[power-1] == TRUE  ) state= FglmNotReduced;
234            else purePowers[power-1]= TRUE;
235        }
236        for ( int l = IDELEMS( theIdeal ) - 1; state == FglmOk && l >= 0; l-- )
237            if ( (k != l) && pDivisibleBy( p, (theIdeal->m)[l] ) )
238                state= FglmNotReduced;
239    }
240    if ( state == FglmOk ) {
241        for ( k= pVariables-1 ; (state == FglmOk) && (k >= 0); k-- )
242            if ( purePowers[k] == FALSE ) state= FglmNotZeroDim;
243    }
244    Free( (ADDRESS)purePowers, pVariables*sizeof( BOOLEAN ) );
245    return state;
246}
247
248// The main function for the fglm-Algorithm.
249// Checks the input-data, and calls fglmzero (see fglmzero.cc).
250// Returns the new groebnerbasis or 0 if an error occoured.
251BOOLEAN
252fglmProc( leftv result, leftv first, leftv second )
253{
254    FglmState state = FglmOk;
255
256    idhdl destRingHdl = currRingHdl;
257    ring destRing = currRing;
258    ideal destIdeal = NULL;
259    idhdl sourceRingHdl = (idhdl)first->data;
260    rSetHdl( sourceRingHdl, TRUE );
261    ring sourceRing = currRing;
262
263    int * vperm = (int *)Alloc0( (pVariables+1)*sizeof( int ) );
264    state= fglmConsistency( sourceRingHdl, destRingHdl, vperm );
265    Free( (ADDRESS)vperm, (pVariables+1)*sizeof(int) );
266
267    if ( state == FglmOk ) {
268        idhdl ih = currRing->idroot->get( second->Name(), myynest );
269        if ( (ih != NULL) && (IDTYP(ih)==IDEAL_CMD) ) {
270            ideal sourceIdeal;
271            if ( currQuotient != NULL )
272                sourceIdeal= fglmUpdatesource( IDIDEAL( ih ) );
273            else
274                sourceIdeal = IDIDEAL( ih );
275            state= fglmIdealcheck( sourceIdeal );
276            if ( state == FglmOk ) {
277                // Now the settings are compatible with FGLM
278                assumeStdFlag( (leftv)ih );
279                if ( fglmzero( sourceRingHdl, sourceIdeal, destRingHdl, destIdeal, FALSE, (currQuotient != NULL) ) == FALSE )
280                    state= FglmNotReduced;
281            }
282        } else state= FglmNoIdeal;
283    }
284    if ( currRingHdl != destRingHdl )
285        rSetHdl( destRingHdl, TRUE );
286    switch (state) {
287        case FglmOk:
288            if ( currQuotient != NULL ) fglmUpdateresult( destIdeal );
289            break;
290        case FglmHasOne:
291            destIdeal= idInit(1,1);
292            (destIdeal->m)[0]= pOne();
293            state= FglmOk;
294            break;
295        case FglmIncompatibleRings:
296            Werror( "ring %s and current ring are incompatible", first->Name() );
297            destIdeal= idInit(0,0);
298            break;
299        case FglmNoIdeal:
300            Werror( "Can't find ideal %s in ring %s", second->Name(), first->Name() );
301            destIdeal= idInit(0,0);
302            break;
303        case FglmNotZeroDim:
304            Werror( "The ideal %s has to be 0-dimensional", second->Name() );
305            destIdeal= idInit(0,0);
306            break;
307        case FglmNotReduced:
308            Werror( "The ideal %s has to be reduced", second->Name() );
309            destIdeal= idInit(0,0);
310            break;
311        default:
312            destIdeal= idInit(1,1);
313    }
314
315    result->rtyp = IDEAL_CMD;
316    result->data= (void *)destIdeal;
317    setFlag( result, FLAG_STD );
318    return (state != FglmOk);
319}
320
321// The main function for finduni().
322// Checks the input-data, and calls FindUnivariateWrapper (see fglmzero.cc).
323// Returns an ideal containing the univariate Polynomials or 0 if an error
324// has occoured.
325BOOLEAN
326findUniProc( leftv result, leftv first )
327{
328    ideal sourceIdeal;
329    ideal destIdeal = NULL;
330    FglmState state;
331
332    idhdl sourceIdealHdl = (idhdl)first->data;
333    sourceIdeal= IDIDEAL(sourceIdealHdl);
334
335    assumeStdFlag( first );
336    state= fglmIdealcheck( sourceIdeal );
337    if ( state == FglmOk ) {
338        if ( FindUnivariateWrapper( sourceIdeal, destIdeal ) == FALSE )
339            state = FglmNotReduced;
340    }
341    switch (state) {
342        case FglmOk:
343            break;
344        case FglmHasOne:
345            destIdeal= idInit(1,1);
346            (destIdeal->m)[0]= pOne();
347            state= FglmOk;
348            break;
349        case FglmNotZeroDim:
350            Werror( "The ideal %s has to be 0-dimensional", first->Name() );
351            destIdeal= idInit(0,0);
352            break;
353        case FglmNotReduced:
354            Werror( "The ideal %s has to be reduced", first->Name() );
355            destIdeal= idInit(0,0);
356            break;
357        default:
358            destIdeal= idInit(1,1);
359    }
360
361    result->rtyp = IDEAL_CMD;
362    result->data= (void *)destIdeal;
363
364    return FALSE;
365}
366#endif
367// ----------------------------------------------------------------------------
368// Local Variables: ***
369// compile-command: "make Singular" ***
370// page-delimiter: "^\\(\\|//!\\)" ***
371// fold-internal-margins: nil ***
372// End: ***
Note: See TracBrowser for help on using the repository browser.