source: git/kernel/gfan.cc @ 798f721

jengelh-datetimespielwiese
Last change on this file since 798f721 was 798f721, checked in by Martin Monerjan, 14 years ago
Started work on facet::flip(ideal I, facet *f) method to compute the groebner basis on the other side of a flippable facet. Is there a kernel implementation to check the rank of a matrix? git-svn-id: file:///usr/local/Singular/svn/trunk@11608 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 13.0 KB
Line 
1/*
2Compute the Groebner fan of an ideal
3$Author: monerjan $
4$Date: 2009-03-31 09:59:14 $
5$Header: /exports/cvsroot-2/cvsroot/kernel/gfan.cc,v 1.25 2009-03-31 09:59:14 monerjan Exp $
6$Id: gfan.cc,v 1.25 2009-03-31 09:59:14 monerjan Exp $
7*/
8
9#include "mod2.h"
10
11#ifdef HAVE_GFAN
12
13#include "kstd1.h"
14#include "intvec.h"
15#include "polys.h"
16#include "ideals.h"
17#include "kmatrix.h"
18#include "fast_maps.h"  //Mapping of ideals
19#include "maps.h"
20#include "iostream.h"   //deprecated
21
22//Hacks for different working places
23#define ITWM
24
25#ifdef UNI
26#include "/users/urmel/alggeom/monerjan/cddlib/include/setoper.h" //Support for cddlib. Dirty hack
27#include "/users/urmel/alggeom/monerjan/cddlib/include/cdd.h"
28#endif
29
30#ifdef HOME
31#include "/home/momo/studium/diplomarbeit/cddlib/include/setoper.h"
32#include "/home/momo/studium/diplomarbeit/cddlib/include/cdd.h"
33#endif
34
35#ifdef ITWM
36#include "/u/slg/monerjan/cddlib/include/setoper.h"
37#include "/u/slg/monerjan/cddlib/include/cdd.h"
38#endif
39
40#ifndef gfan_DEBUG
41#define gfan_DEBUG
42#endif
43
44//#include gcone.h
45
46/**
47*\brief Class facet
48*       Implements the facet structure as a linked list
49*
50*/
51class facet
52{
53        private:
54                /** inner normal, describing the facet uniquely up to isomorphism */
55                intvec *fNormal;               
56        public:
57                /** The default constructor. Do I need a constructor of type facet(intvec)? */
58                facet()                 
59                {
60                        // Pointer to next facet.  */
61                        /* Defaults to NULL. This way there is no need to check explicitly */
62                        this->next=NULL; 
63                }
64               
65                /** The default destructor */
66                ~facet(){;}
67               
68                /** Stores the facet normal \param intvec*/
69                void setFacetNormal(intvec *iv){
70                        fNormal = iv;
71                        //return;
72                }
73               
74                /** Method to print the facet normal*/
75                void printNormal()
76                {
77                        fNormal->show();
78                }
79               
80                /** \brief The Groebner basis on the other side of a shared facet
81                *
82                * In order not to have to compute the flipped GB twice we store the basis we already get
83                * when identifying search facets. Thus in the next step of the reverse search we can
84                * just copy the old cone and update the facet and the gcBasis
85                */
86                ideal flibGB;           //The Groebner Basis on the other side, computed via gcone::flip
87               
88                bool isFlippable;       //flippable facet? Want to have cone->isflippable.facet[i]
89                bool isIncoming;        //Is the facet incoming or outgoing?
90                facet *next;            //Pointer to next facet
91};
92
93/**
94*\brief Implements the cone structure
95*
96* A cone is represented by a linked list of facet normals
97* @see facet
98*/
99/*class gcone
100finally this should become s.th. like gconelib.{h,cc} to provide an API
101*/
102class gcone
103{
104        private:
105                int numFacets;          //#of facets of the cone
106
107        public:
108                /** \brief Default constructor.
109                *
110                * Initialises this->next=NULL and this->facetPtr=NULL
111                */
112                gcone()
113                {
114                        this->next=NULL;
115                        this->facetPtr=NULL;
116                }
117                ~gcone();               //destructor
118                /** Pointer to the first facet */
119                facet *facetPtr;        //Will hold the adress of the first facet
120                poly gcMarkedTerm;      //marked terms of the cone's Groebner basis
121                ideal gcBasis;          //GB of the cone
122                gcone *next;            //Pointer to *previous* cone in search tree
123                /** \brief Compute the normals of the cone
124                *
125                * This method computes a representation of the cone in terms of facet normals. It takes an ideal
126                * as its input. Redundancies are automatically removed using cddlib's dd_MatrixCanonicalize.
127                * Other methods for redundancy checkings might be implemented later. See Anders' diss p.44.
128                * Note that in order to use cddlib a 0-th column has to be added to the matrix since cddlib expects
129                * each row to represent an inequality of type const+x1+...+xn <= 0
130                * As a result of this procedure the pointer facetPtr points to the first facet of the cone.
131                */
132                void getConeNormals(ideal I)
133                {
134#ifdef gfan_DEBUG
135                        cout << "*** Computing Inequalities... ***" << endl;
136#endif         
137                        //All variables go here - except ineq matrix and *v, see below
138                        int lengthGB=IDELEMS(I);        // # of polys in the groebner basis
139                        int pCompCount;                 // # of terms in a poly
140                        poly aktpoly;
141                        int numvar = pVariables;        // # of variables in a polynomial (or ring?)
142                        int leadexp[numvar];            // dirty hack of exp.vects
143                        int aktexp[numvar];
144                        int cols,rows;                  // will contain the dimensions of the ineq matrix - deprecated by
145                        dd_rowrange ddrows;
146                        dd_colrange ddcols;
147                        dd_rowset ddredrows;            // # of redundant rows in ddineq
148                        dd_rowset ddlinset;             // the opposite
149                        dd_rowindex ddnewpos;           // all to make dd_Canonicalize happy
150                        dd_NumberType ddnumb=dd_Real;   //Number type
151                        dd_ErrorType dderr=dd_NoError;  //
152                        // End of var declaration
153#ifdef gfan_DEBUG
154                        cout << "The Groebner basis has " << lengthGB << " elements" << endl;
155                        cout << "The current ring has " << numvar << " variables" << endl;
156#endif
157                        cols = numvar;
158               
159                        //Compute the # inequalities i.e. rows of the matrix
160                        rows=0; //Initialization
161                        for (int ii=0;ii<IDELEMS(I);ii++)
162                        {
163                                aktpoly=(poly)I->m[ii];
164                                rows=rows+pLength(aktpoly)-1;
165                        }
166#ifdef gfan_DEBUG
167                        cout << "rows=" << rows << endl;
168                        cout << "Will create a " << rows << " x " << cols << " matrix to store inequalities" << endl;
169#endif
170                        dd_rowrange aktmatrixrow=0;     // needed to store the diffs of the expvects in the rows of ddineq
171                        dd_set_global_constants();
172                        ddrows=rows;
173                        ddcols=cols;
174                        dd_MatrixPtr ddineq;            //Matrix to store the inequalities
175                        ddineq=dd_CreateMatrix(ddrows,ddcols+1); //The first col has to be 0 since cddlib checks for additive consts there
176               
177                        // We loop through each g\in GB and compute the resulting inequalities
178                        for (int i=0; i<IDELEMS(I); i++)
179                        {
180                                aktpoly=(poly)I->m[i];          //get aktpoly as i-th component of I
181                                pCompCount=pLength(aktpoly);    //How many terms does aktpoly consist of?
182                                cout << "Poly No. " << i << " has " << pCompCount << " components" << endl;
183               
184                                int *v=(int *)omAlloc((numvar+1)*sizeof(int));
185                                pGetExpV(aktpoly,v);    //find the exp.vect in v[1],...,v[n], use pNext(p)
186                               
187                                //Store leadexp for aktpoly
188                                for (int kk=0;kk<numvar;kk++)
189                                {
190                                        leadexp[kk]=v[kk+1];
191                                        //Since we need to know the difference of leadexp with the other expvects we do nothing here
192                                        //but compute the diff below
193                                }
194               
195                               
196                                while (pNext(aktpoly)!=NULL) //move to next term until NULL
197                                {
198                                        aktpoly=pNext(aktpoly);
199                                        pSetm(aktpoly);         //doesn't seem to help anything
200                                        pGetExpV(aktpoly,v);
201                                        for (int kk=0;kk<numvar;kk++)
202                                        {
203                                                aktexp[kk]=v[kk+1];
204                                                //ineq[aktmatrixrow][kk]=leadexp[kk]-aktexp[kk];        //dito
205                                                dd_set_si(ddineq->matrix[(dd_rowrange)aktmatrixrow][kk+1],leadexp[kk]-aktexp[kk]); //because of the 1st col being const 0
206                                        }
207                                        aktmatrixrow=aktmatrixrow+1;
208                                }//while
209               
210                        } //for
211               
212                        //Maybe add another row to contain the constraints of the standard simplex?
213
214#ifdef gfan_DEBUG
215                        cout << "The inequality matrix is" << endl;
216                        dd_WriteMatrix(stdout, ddineq);
217#endif
218
219                        // The inequalities are now stored in ddineq
220                        // Next we check for superflous rows
221                        ddredrows = dd_RedundantRows(ddineq, &dderr);
222                        if (dderr!=dd_NoError)                  // did an error occur?
223                        {
224                                dd_WriteErrorMessages(stderr,dderr);    //if so tell us
225                        } else
226                        {
227                                cout << "Redundant rows: ";
228                                set_fwrite(stdout, ddredrows);          //otherwise print the redundant rows
229                        }//if dd_Error
230               
231                        //Remove reduntant rows here!
232                        dd_MatrixCanonicalize(&ddineq, &ddlinset, &ddredrows, &ddnewpos, &dderr);
233                        ddrows = ddineq->rowsize;       //Size of the matrix with redundancies removed
234                        ddcols = ddineq->colsize;
235#ifdef gfan_DEBUG
236                        cout << "Having removed redundancies, the normals now read:" << endl;
237                        dd_WriteMatrix(stdout,ddineq);
238                        cout << "Rows = " << ddrows << endl;
239                        cout << "Cols = " << ddcols << endl;
240#endif
241                        /*Write the normals into class facet*/
242#ifdef gfan_DEBUG
243                        cout << "Creating list of normals" << endl;
244#endif
245                        /*The pointer *fRoot should be the return value of this function*/
246                        facet *fRoot = new facet();             //instantiate new facet with intvec with numvar rows, one column and initial values all 0
247                        facetPtr = fRoot;               //set variable facetPtr of class gcone to first facet
248                        facet *fAct;                    //instantiate pointer to active facet
249                        fAct = fRoot;           //This does not seem to do the trick. fRoot and fAct have to point to the same adress!
250                        std::cout << "fRoot = " << fRoot << ", fAct = " << fAct << endl;
251                        for (int kk = 0; kk<ddrows; kk++)
252                        {
253                                intvec *load = new intvec(numvar);      //intvec to store a single facet normal that will then be stored via setFacetNormal
254                                for (int jj = 1; jj <ddcols; jj++)
255                                {
256                                        double *foo;
257                                        foo = (double*)ddineq->matrix[kk][jj];  //get entry from actual position
258#ifdef gfan_DEBUG
259                                        std::cout << "fAct is " << *foo << " at " << fAct << std::endl;
260#endif 
261                                        (*load)[jj-1] = (int)*foo;              //store typecasted entry at pos jj-1 of load
262                                        //check for flipability here
263                                        if (jj<ddcols)                          //Is this facet NOT the last facet? Writing while instead of if is a really bad idea :)
264                                        {
265                                                fAct->next = new facet();       //If so: instantiate new facet. Otherwise this->next=NULL due to the constructor
266                                                fAct = fAct->next;              //scary :)
267                                        }
268                                }//for jj<ddcols
269                                /*Now load should be full and we can call setFacetNormal*/
270                                fAct->setFacetNormal(load);
271                                fAct->printNormal();
272                        }
273                        /*
274                        Now we should have a linked list containing the facet normals of those facets that are
275                        -irredundant
276                        -flipable
277                        Adressing is done via *facetPtr
278                        */
279                       
280                        //Clean up but don't delete the return value! (Whatever it will turn out to be)
281                        dd_FreeMatrix(ddineq);
282                        set_free(ddredrows);
283                        free(ddnewpos);
284                        set_free(ddlinset);
285                        dd_free_global_constants();
286
287                }//method getConeNormals(ideal I)       
288               
289                /** \brief Compute the Groebner Basis on the other side of a shared facet
290                *
291                * Implements algorithm 4.3.2 from Anders' thesis.
292                * As shown there it is not necessary to compute an interior point. The knowledge of the facet normal
293                * suffices. A term \f$ x^\gamma \f$ of \f$ g \f$ is in \f$  in_\omega(g) \f$ iff \f$ \gamma - leadexp(g)\f$
294                * is parallel to \f$ leadexp(g) \f$
295                * Checking for parallelity is done by computing the rank of the matrix consisting of the vectors in question.
296                * Another possibility would be to compute an interior point of the facet and taking all terms having the same
297                * weight with respect to this interior point.
298                *\param ideal, facet
299                */
300                void flip(ideal I, facet *f)            //Compute "the other side"
301                {
302                        /*1st step: Compute the initial ideal*/
303                        map mapping;
304                        idhdl h;
305                        ideal image;
306                        mapping=IDMAP(h);
307                        image=idInit(1,1);
308                        image=maGetPreimage(currRing,mapping,image);                   
309                }
310                               
311                /** \brief Compute a Groebner Basis
312                *
313                * Computes the Groebner basis and stores the result in this->gcBasis
314                *\param ideal
315                *\return void
316                */
317                void getGB(ideal inputIdeal)
318                {
319                        ideal gb;
320                        gb=kStd(inputIdeal,NULL,testHomog,NULL);
321                        idSkipZeroes(gb);
322                        this->gcBasis=gb;       //write the GB into gcBasis
323                }
324               
325                ideal GenGrbWlk(ideal, ideal);  //Implementation of the Generic Groebner Walk. Needed for a) Computing the sink and b) finding search facets
326               
327
328};//class gcone
329
330/*
331function getGB incorporated into class gcone with rev 1.24
332*/
333
334//DEPRECATED since rev 1.24 with existence of gcone::getConeNormals(ideal I);
335//Kept for unknown reasons ;)
336facet *getConeNormals(ideal I)
337{
338        return NULL;
339}
340
341ideal gfan(ideal inputIdeal)
342{
343        int numvar = pVariables; 
344       
345        #ifdef gfan_DEBUG
346        cout << "Now in subroutine gfan" << endl;
347        #endif
348        ring inputRing=currRing;        // The ring the user entered
349        ring rootRing;                  // The ring associated to the target ordering
350        ideal res;
351        //matrix ineq;                  //Matrix containing the boundary inequalities
352        facet *fRoot;
353       
354        /*
355        1. Select target order, say dp.
356        2. Compute GB of inputIdeal wrt target order -> newRing, setCurrRing etc...
357        3. getConeNormals
358        */
359
360       
361        /* Construct a new ring which will serve as our root
362        Does not yet work as expected. Will work fine with order dp,Dp but otherwise hangs in getGB
363        */
364        rootRing=rCopy0(currRing);
365        rootRing->order[0]=ringorder_dp;
366        rComplete(rootRing);
367        rChangeCurrRing(rootRing);
368        ideal rootIdeal;
369        /* Fetch the inputIdeal into our rootRing */
370        map m=(map)idInit(IDELEMS(inputIdeal),0);
371        rootIdeal=fast_map(inputIdeal,inputRing,(ideal)m, currRing);
372#ifdef gfan_DEBUG
373        cout << "Root ideal is " << endl;
374        idPrint(rootIdeal);
375        cout << "The current ring is " << endl;
376        rWrite(rootRing);
377        cout << endl;
378#endif 
379       
380        gcone *gcRoot = new gcone();    //Instantiate the sink
381        gcone *gcAct;
382        gcAct = gcRoot;
383        gcAct->getGB(inputIdeal);
384        gcAct->getConeNormals(gcAct->gcBasis);  //hopefully compute the normals
385       
386        /*Now it is time to compute the search facets, respectively start the reverse search.
387        But since we are in the root all facets should be search facets. IS THIS TRUE?
388        MIND: AS OF NOW, THE LIST OF FACETS IS NOT PURGED OF NON-FLIPPAPLE FACETS
389        */
390       
391        /*As of now extra.cc expects gfan to return type ideal. Probably this will change in near future.
392        The return type will then be of type LIST_CMD
393        Assume gfan has finished, thus we have enumerated all the cones
394        Create an array of size of #cones. Let each entry in the array contain a pointer to the respective
395        Groebner Basis and merge this somehow with LIST_CMD
396        => Count the cones!
397        */
398       
399        res=gcAct->gcBasis;
400        //cout << fRoot << endl;
401        return res;
402        //return GBlist;
403}
404/*
405Since gfan.cc is #included from extra.cc there must not be a int main(){} here
406*/
407#endif
Note: See TracBrowser for help on using the repository browser.