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

spielwiese
Last change on this file since 798f721 was 798f721, checked in by Martin Monerjan, 15 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
RevLine 
[b3e45f]1/*
[6623f3]2Compute the Groebner fan of an ideal
[fc4f9a]3$Author: monerjan $
[798f721]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 $
[b3e45f]7*/
8
[d3398c]9#include "mod2.h"
[34fcf8]10
11#ifdef HAVE_GFAN
12
[d3398c]13#include "kstd1.h"
[50ab25a]14#include "intvec.h"
[2c6535]15#include "polys.h"
16#include "ideals.h"
[198a339]17#include "kmatrix.h"
[90adba8]18#include "fast_maps.h"  //Mapping of ideals
[798f721]19#include "maps.h"
[aba53c]20#include "iostream.h"   //deprecated
[fc4f9a]21
22//Hacks for different working places
[54248e]23#define ITWM
[fc4f9a]24
25#ifdef UNI
[c5d8dd]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"
[fc4f9a]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
[aba53c]36#include "/u/slg/monerjan/cddlib/include/setoper.h"
37#include "/u/slg/monerjan/cddlib/include/cdd.h"
[fc4f9a]38#endif
[d3398c]39
[b3e45f]40#ifndef gfan_DEBUG
41#define gfan_DEBUG
42#endif
[9f9b142]43
44//#include gcone.h
45
[fe919c]46/**
47*\brief Class facet
[53e33d9]48*       Implements the facet structure as a linked list
[fe919c]49*
50*/
[8bdaab]51class facet
52{
53        private:
[90adba8]54                /** inner normal, describing the facet uniquely up to isomorphism */
[54248e]55                intvec *fNormal;               
[8bdaab]56        public:
[fe919c]57                /** The default constructor. Do I need a constructor of type facet(intvec)? */
58                facet()                 
[fc4f9a]59                {
[fe919c]60                        // Pointer to next facet.  */
61                        /* Defaults to NULL. This way there is no need to check explicitly */
62                        this->next=NULL; 
[fc4f9a]63                }
64               
[fe919c]65                /** The default destructor */
66                ~facet(){;}
67               
[54248e]68                /** Stores the facet normal \param intvec*/
69                void setFacetNormal(intvec *iv){
[aba53c]70                        fNormal = iv;
[54248e]71                        //return;
72                }
73               
74                /** Method to print the facet normal*/
75                void printNormal()
76                {
77                        fNormal->show();
[fc4f9a]78                }
79               
[798f721]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               
[18765e]88                bool isFlippable;       //flippable facet? Want to have cone->isflippable.facet[i]
89                bool isIncoming;        //Is the facet incoming or outgoing?
[aba53c]90                facet *next;            //Pointer to next facet
[8bdaab]91};
92
[fe919c]93/**
[90adba8]94*\brief Implements the cone structure
95*
96* A cone is represented by a linked list of facet normals
97* @see facet
[fe919c]98*/
[8bdaab]99/*class gcone
100finally this should become s.th. like gconelib.{h,cc} to provide an API
101*/
102class gcone
103{
[18765e]104        private:
105                int numFacets;          //#of facets of the cone
106
107        public:
[90adba8]108                /** \brief Default constructor.
109                *
110                * Initialises this->next=NULL and this->facetPtr=NULL
111                */
[54248e]112                gcone()
113                {
114                        this->next=NULL;
115                        this->facetPtr=NULL;
116                }
[fc4f9a]117                ~gcone();               //destructor
[53e33d9]118                /** Pointer to the first facet */
[54248e]119                facet *facetPtr;        //Will hold the adress of the first facet
[aba53c]120                poly gcMarkedTerm;      //marked terms of the cone's Groebner basis
[18765e]121                ideal gcBasis;          //GB of the cone
122                gcone *next;            //Pointer to *previous* cone in search tree
[90adba8]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)
[03de21]133                {
[90adba8]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;
[198a339]158               
[90adba8]159                        //Compute the # inequalities i.e. rows of the matrix
160                        rows=0; //Initialization
161                        for (int ii=0;ii<IDELEMS(I);ii++)
[03de21]162                        {
[90adba8]163                                aktpoly=(poly)I->m[ii];
164                                rows=rows+pLength(aktpoly)-1;
[03de21]165                        }
[90adba8]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?
[c5d8dd]213
[90adba8]214#ifdef gfan_DEBUG
215                        cout << "The inequality matrix is" << endl;
216                        dd_WriteMatrix(stdout, ddineq);
217#endif
[e2fb7a]218
[90adba8]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;
[aba53c]235#ifdef gfan_DEBUG
[90adba8]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;
[aba53c]240#endif
[90adba8]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++)
[aba53c]252                        {
[90adba8]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();
[aba53c]272                        }
[90adba8]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               
[798f721]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                }
[90adba8]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               
[e2fb7a]327
[90adba8]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;
[2c6535]339}
340
341ideal gfan(ideal inputIdeal)
342{
[54248e]343        int numvar = pVariables; 
344       
[b3e45f]345        #ifdef gfan_DEBUG
[fc4f9a]346        cout << "Now in subroutine gfan" << endl;
[b3e45f]347        #endif
[90adba8]348        ring inputRing=currRing;        // The ring the user entered
349        ring rootRing;                  // The ring associated to the target ordering
[b3e45f]350        ideal res;
[90adba8]351        //matrix ineq;                  //Matrix containing the boundary inequalities
[9f9b142]352        facet *fRoot;
353       
[90adba8]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
[9f9b142]360       
[90adba8]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        */
[9f9b142]364        rootRing=rCopy0(currRing);
[53e33d9]365        rootRing->order[0]=ringorder_dp;
[9f9b142]366        rComplete(rootRing);
367        rChangeCurrRing(rootRing);
[90adba8]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);
[9f9b142]375        cout << "The current ring is " << endl;
376        rWrite(rootRing);
[90adba8]377        cout << endl;
378#endif 
379       
[9f9b142]380        gcone *gcRoot = new gcone();    //Instantiate the sink
381        gcone *gcAct;
382        gcAct = gcRoot;
[90adba8]383        gcAct->getGB(inputIdeal);
384        gcAct->getConeNormals(gcAct->gcBasis);  //hopefully compute the normals
[798f721]385       
[90adba8]386        /*Now it is time to compute the search facets, respectively start the reverse search.
[798f721]387        But since we are in the root all facets should be search facets. IS THIS TRUE?
[90adba8]388        MIND: AS OF NOW, THE LIST OF FACETS IS NOT PURGED OF NON-FLIPPAPLE FACETS
389        */
[9f9b142]390       
[90adba8]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!
[fc4f9a]397        */
[90adba8]398       
399        res=gcAct->gcBasis;
400        //cout << fRoot << endl;
[b3e45f]401        return res;
[90adba8]402        //return GBlist;
[d3398c]403}
[9f9b142]404/*
405Since gfan.cc is #included from extra.cc there must not be a int main(){} here
406*/
[34fcf8]407#endif
Note: See TracBrowser for help on using the repository browser.