source: git/kernel/gfan.cc @ d7fe2a2

spielwiese
Last change on this file since d7fe2a2 was d7fe2a2, checked in by Martin Monerjan, 15 years ago
reverseSearch git-svn-id: file:///usr/local/Singular/svn/trunk@11759 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 34.0 KB
Line 
1/*
2Compute the Groebner fan of an ideal
3$Author: monerjan $
4$Date: 2009-04-29 07:22:48 $
5$Header: /exports/cvsroot-2/cvsroot/kernel/gfan.cc,v 1.42 2009-04-29 07:22:48 monerjan Exp $
6$Id: gfan.cc,v 1.42 2009-04-29 07:22:48 monerjan Exp $
7*/
8
9#include "mod2.h"
10
11#ifdef HAVE_GFAN
12
13#include "kstd1.h"
14#include "kutil.h"
15#include "intvec.h"
16#include "polys.h"
17#include "ideals.h"
18#include "kmatrix.h"
19#include "fast_maps.h"  //Mapping of ideals
20#include "maps.h"
21#include "ring.h"
22#include "prCopy.h"
23#include <iostream.h>   //deprecated
24#include <bitset>
25
26/*remove the following at your own risk*/
27#ifndef GMPRATIONAL
28#define GMPRATIONAL
29#endif
30
31//Hacks for different working places
32#define ITWM
33
34#ifdef UNI
35#include "/users/urmel/alggeom/monerjan/cddlib/include/setoper.h" //Support for cddlib. Dirty hack
36#include "/users/urmel/alggeom/monerjan/cddlib/include/cdd.h"
37#endif
38
39#ifdef HOME
40#include "/home/momo/studium/diplomarbeit/cddlib/include/setoper.h"
41#include "/home/momo/studium/diplomarbeit/cddlib/include/cdd.h"
42#endif
43
44#ifdef ITWM
45#include "/u/slg/monerjan/cddlib/include/setoper.h"
46#include "/u/slg/monerjan/cddlib/include/cdd.h"
47#include "/u/slg/monerjan/cddlib/include/cddmp.h"
48#endif
49
50#ifndef gfan_DEBUG
51#define gfan_DEBUG
52#endif
53
54//#include gcone.h
55
56/**
57*\brief Class facet
58*       Implements the facet structure as a linked list
59*
60*/
61class facet
62{
63        private:
64                /** \brief Inner normal of the facet, describing it uniquely up to isomorphism */
65                intvec *fNormal;
66               
67                /** \brief The Groebner basis on the other side of a shared facet
68                 *
69                 * In order not to have to compute the flipped GB twice we store the basis we already get
70                 * when identifying search facets. Thus in the next step of the reverse search we can
71                 * just copy the old cone and update the facet and the gcBasis.
72                 * facet::flibGB is set via facet::setFlipGB() and printed via facet::printFlipGB
73                 */
74                ideal flipGB;           //The Groebner Basis on the other side, computed via gcone::flip
75
76                       
77        public:
78                /** The default constructor. Do I need a constructor of type facet(intvec)? */
79                facet()                 
80                {
81                        // Pointer to next facet.  */
82                        /* Defaults to NULL. This way there is no need to check explicitly */
83                        this->next=NULL; 
84                }
85               
86                /** The default destructor */
87                ~facet(){;}
88               
89                /** Stores the facet normal \param intvec*/
90                void setFacetNormal(intvec *iv)
91                {
92                        this->fNormal = ivCopy(iv);
93                        //return;
94                }
95               
96                /** Hopefully returns the facet normal */
97                intvec *getFacetNormal()
98                {       
99                        //this->fNormal->show();        cout << endl;   
100                        return this->fNormal;
101                }
102               
103                /** Method to print the facet normal*/
104                void printNormal()
105                {
106                        fNormal->show();
107                }
108               
109                /** Store the flipped GB*/
110                void setFlipGB(ideal I)
111                {
112                        this->flipGB=I;
113                }
114               
115                /** Return the flipped GB*/
116                ideal getFlipGB()
117                {
118                        return this->flipGB;
119                }
120               
121                /** Print the flipped GB*/
122                void printFlipGB()
123                {
124                        idShow(this->flipGB);
125                }
126               
127                bool isFlippable;       //flippable facet? Want to have cone->isflippable.facet[i]
128                bool isIncoming;        //Is the facet incoming or outgoing?
129                facet *next;            //Pointer to next facet
130               
131                friend class gcone;     //Bad style
132};
133
134/**
135*\brief Implements the cone structure
136*
137* A cone is represented by a linked list of facet normals
138* @see facet
139*/
140/*class gcone
141finally this should become s.th. like gconelib.{h,cc} to provide an API
142*/
143class gcone
144{
145        private:
146                int numFacets;          //#of facets of the cone
147                ring rootRing;          //good to know this -> generic walk
148                ideal inputIdeal;       //the original
149                ring baseRing;          //the basering of the cone             
150                /* TODO in order to save memory use pointers to rootRing and inputIdeal instead */
151                intvec *ivIntPt;        //an interior point of the cone
152               
153        public:
154                /** \brief Default constructor.
155                *
156                * Initialises this->next=NULL and this->facetPtr=NULL
157                */
158                gcone()
159                {
160                        this->next=NULL;
161                        this->facetPtr=NULL;
162                        this->baseRing=currRing;
163                }
164               
165                /** \brief Constructor with ring and ideal
166                *
167                * This constructor takes the root ring and the root ideal as parameters and stores
168                * them in the private members gcone::rootRing and gcone::inputIdeal
169                */
170                gcone(ring r, ideal I)
171                {
172                        this->next=NULL;
173                        this->facetPtr=NULL;
174                        this->rootRing=r;
175                        this->inputIdeal=I;
176                        this->baseRing=currRing;
177                }
178               
179                /** \brief Copy constructor
180                *
181                * Copies one cone, sets this->gcBasis to the flipped GB and reverses the
182                * direction of the according facet normal
183                */                     
184                gcone(const gcone& gc)         
185                {
186                        this->next=NULL;
187                        this->numVars=gc.numVars;                       
188                        facet *fAct= new facet();                       
189                        this->facetPtr=fAct;
190                       
191                        intvec *ivtmp = new intvec(this->numVars);                                             
192                        ivtmp = gc.facetPtr->getFacetNormal();
193                        ivtmp->show();                 
194                       
195                        ideal gb;
196                        gb=gc.facetPtr->getFlipGB();                   
197                        this->gcBasis=gb;//gc.facetPtr->getFlipGB();    //this cone's GB is the flipped GB
198                        idShow(this->gcBasis);
199                       
200                        /*Reverse direction of the facet normal to make it an inner normal*/                   
201                        for (int ii=0; ii<this->numVars;ii++)
202                        {
203                                (*ivtmp)[ii]=-(*ivtmp)[ii];                             
204                        }
205                        //ivtmp->show(); cout << endl;
206                        fAct->setFacetNormal(ivtmp);
207                        //fAct->printNormal();cout << endl;
208                        //ivtmp->show();cout << endl;
209                }
210               
211                /** \brief Default destructor */
212                ~gcone();               //destructor
213               
214                /** Pointer to the first facet */
215                facet *facetPtr;        //Will hold the adress of the first facet; set by gcone::getConeNormals
216               
217                /** # of variables in the ring */
218                int numVars;            //#of variables in the ring
219               
220                /** Contains the Groebner basis of the cone. Is set by gcone::getGB(ideal I)*/
221                ideal gcBasis;          //GB of the cone, set by gcone::getGB();
222                gcone *next;            //Pointer to *previous* cone in search tree
223               
224                /** \brief Set the interior point of a cone */
225                void setIntPoint(intvec *iv)
226                {
227                        this->ivIntPt=ivCopy(iv);
228                }
229               
230                void getIntPoint()
231                {
232                        ivIntPt->show();
233                }
234               
235                /** \brief Compute the normals of the cone
236                *
237                * This method computes a representation of the cone in terms of facet normals. It takes an ideal
238                * as its input. Redundancies are automatically removed using cddlib's dd_MatrixCanonicalize.
239                * Other methods for redundancy checkings might be implemented later. See Anders' diss p.44.
240                * Note that in order to use cddlib a 0-th column has to be added to the matrix since cddlib expects
241                * each row to represent an inequality of type const+x1+...+xn <= 0. While computing the normals we come across
242                * the set \f$ \partial\mathcal{G} \f$ which we might store for later use. C.f p71 of journal
243                * As a result of this procedure the pointer facetPtr points to the first facet of the cone.
244                *
245                * Optionally, if the parameter bool compIntPoint is set to TRUE the method will also compute
246                * an interior point of the cone.
247                */
248                void getConeNormals(ideal const &I, bool compIntPoint=FALSE)
249                {
250#ifdef gfan_DEBUG
251                        std::cout << "*** Computing Inequalities... ***" << std::endl;
252#endif         
253                        //All variables go here - except ineq matrix and *v, see below
254                        int lengthGB=IDELEMS(I);        // # of polys in the groebner basis
255                        int pCompCount;                 // # of terms in a poly
256                        poly aktpoly;
257                        int numvar = pVariables;        // # of variables in a polynomial (or ring?)
258                        int leadexp[numvar];            // dirty hack of exp.vects
259                        int aktexp[numvar];
260                        int cols,rows;                  // will contain the dimensions of the ineq matrix - deprecated by
261                        dd_rowrange ddrows;
262                        dd_colrange ddcols;
263                        dd_rowset ddredrows;            // # of redundant rows in ddineq
264                        dd_rowset ddlinset;             // the opposite
265                        dd_rowindex ddnewpos;             // all to make dd_Canonicalize happy
266                        dd_NumberType ddnumb=dd_Integer; //Number type
267                        dd_ErrorType dderr=dd_NoError;  //
268                        // End of var declaration
269#ifdef gfan_DEBUG
270                        cout << "The Groebner basis has " << lengthGB << " elements" << endl;
271                        cout << "The current ring has " << numvar << " variables" << endl;
272#endif
273                        cols = numvar;
274               
275                        //Compute the # inequalities i.e. rows of the matrix
276                        rows=0; //Initialization
277                        for (int ii=0;ii<IDELEMS(I);ii++)
278                        {
279                                aktpoly=(poly)I->m[ii];
280                                rows=rows+pLength(aktpoly)-1;
281                        }
282#ifdef gfan_DEBUG
283                        cout << "rows=" << rows << endl;
284                        cout << "Will create a " << rows << " x " << cols << " matrix to store inequalities" << endl;
285#endif
286                        dd_rowrange aktmatrixrow=0;     // needed to store the diffs of the expvects in the rows of ddineq
287                        dd_set_global_constants();
288                        ddrows=rows;
289                        ddcols=cols;
290                        dd_MatrixPtr ddineq;            //Matrix to store the inequalities                     
291                        ddineq=dd_CreateMatrix(ddrows,ddcols+1); //The first col has to be 0 since cddlib checks for additive consts there
292               
293                        // We loop through each g\in GB and compute the resulting inequalities
294                        for (int i=0; i<IDELEMS(I); i++)
295                        {
296                                aktpoly=(poly)I->m[i];          //get aktpoly as i-th component of I
297                                pCompCount=pLength(aktpoly);    //How many terms does aktpoly consist of?
298                                cout << "Poly No. " << i << " has " << pCompCount << " components" << endl;
299               
300                                int *v=(int *)omAlloc((numvar+1)*sizeof(int));
301                                pGetExpV(aktpoly,v);    //find the exp.vect in v[1],...,v[n], use pNext(p)
302                               
303                                //Store leadexp for aktpoly
304                                for (int kk=0;kk<numvar;kk++)
305                                {
306                                        leadexp[kk]=v[kk+1];
307                                        //Since we need to know the difference of leadexp with the other expvects we do nothing here
308                                        //but compute the diff below
309                                }
310               
311                               
312                                while (pNext(aktpoly)!=NULL) //move to next term until NULL
313                                {
314                                        aktpoly=pNext(aktpoly);
315                                        pSetm(aktpoly);         //doesn't seem to help anything
316                                        pGetExpV(aktpoly,v);
317                                        for (int kk=0;kk<numvar;kk++)
318                                        {
319                                                aktexp[kk]=v[kk+1];
320                                                //ineq[aktmatrixrow][kk]=leadexp[kk]-aktexp[kk];        //dito
321                                                dd_set_si(ddineq->matrix[(dd_rowrange)aktmatrixrow][kk+1],leadexp[kk]-aktexp[kk]); //because of the 1st col being const 0
322                                        }
323                                        aktmatrixrow=aktmatrixrow+1;
324                                }//while
325               
326                        } //for
327               
328                        //Maybe add another row to contain the constraints of the standard simplex?
329
330#ifdef gfan_DEBUG
331                        cout << "The inequality matrix is" << endl;
332                        dd_WriteMatrix(stdout, ddineq);
333#endif
334
335                        // The inequalities are now stored in ddineq
336                        // Next we check for superflous rows
337                        ddredrows = dd_RedundantRows(ddineq, &dderr);
338                        if (dderr!=dd_NoError)                  // did an error occur?
339                        {
340                                dd_WriteErrorMessages(stderr,dderr);    //if so tell us
341                        } else
342                        {
343                                cout << "Redundant rows: ";
344                                set_fwrite(stdout, ddredrows);          //otherwise print the redundant rows
345                        }//if dd_Error
346               
347                        //Remove reduntant rows here!
348                        dd_MatrixCanonicalize(&ddineq, &ddlinset, &ddredrows, &ddnewpos, &dderr);
349                        ddrows = ddineq->rowsize;       //Size of the matrix with redundancies removed
350                        ddcols = ddineq->colsize;
351#ifdef gfan_DEBUG
352                        cout << "Having removed redundancies, the normals now read:" << endl;
353                        dd_WriteMatrix(stdout,ddineq);
354                        cout << "Rows = " << ddrows << endl;
355                        cout << "Cols = " << ddcols << endl;
356#endif
357                       
358                        /*Write the normals into class facet*/
359#ifdef gfan_DEBUG
360                        cout << "Creating list of normals" << endl;
361#endif
362                        /*The pointer *fRoot should be the return value of this function*/
363                        facet *fRoot = new facet();     //instantiate new facet
364                        this->facetPtr = fRoot;         //set variable facetPtr of class gcone to first facet
365                        facet *fAct;                    //instantiate pointer to active facet
366                        fAct = fRoot;                   //Seems to do the trick. fRoot and fAct have to point to the same adress!
367                        std::cout << "fRoot = " << fRoot << ", fAct = " << fAct << endl;
368                        for (int kk = 0; kk<ddrows; kk++)
369                        {
370                                intvec *load = new intvec(numvar);      //intvec to store a single facet normal that will then be stored via setFacetNormal
371                                for (int jj = 1; jj <ddcols; jj++)
372                                {
373#ifdef GMPRATIONAL
374                                        double foo;
375                                        foo = mpq_get_d(ddineq->matrix[kk][jj]);
376/*#ifdef gfan_DEBUG
377                                        std::cout << "fAct is " << foo << " at " << fAct << std::endl;
378#endif*/
379                                        (*load)[jj-1] = (int)foo;               //store typecasted entry at pos jj-1 of load
380#endif
381#ifndef GMPRATIONAL
382                                        double *foo;
383                                        foo = (double*)ddineq->matrix[kk][jj];  //get entry from actual position#endif
384/*#ifdef gfan_DEBUG
385                                        std::cout << "fAct is " << *foo << " at " << fAct << std::endl;
386#endif*/
387                                        (*load)[jj-1] = (int)*foo;              //store typecasted entry at pos jj-1 of load
388#endif //GMPRATIONAL                                   
389                       
390
391                                        //(*load)[jj-1] = (int)foo;             //store typecasted entry at pos jj-1 of load
392                                        //check for flipability here
393                                        if (jj<ddcols)                          //Is this facet NOT the last facet? Writing while instead of if is a really bad idea :)
394                                        {
395                                                //fAct->next = new facet();     //If so: instantiate new facet. Otherwise this->next=NULL due to the constructor                                               
396                                        }
397                                }//for (int jj = 1; jj <ddcols; jj++)
398                                /*Quick'n'dirty hack for flippability*/ 
399                                bool isFlippable;                       
400                                for (int jj = 0; jj<this->numVars; jj++)
401                                {                                       
402                                        intvec *ivCanonical = new intvec(this->numVars);
403                                        (*ivCanonical)[jj]=1;                                   
404                                        if (dotProduct(load,ivCanonical)>=0)
405                                        {
406                                                isFlippable=FALSE;                                             
407                                        }
408                                        else
409                                        {
410                                                isFlippable=TRUE;
411                                        }                                       
412                                        delete ivCanonical;
413                                }//for (int jj = 0; jj<this->numVars; jj++)
414                                if (isFlippable==FALSE)
415                                {
416                                        cout << "Ignoring facet";
417                                        load->show();
418                                        //fAct->next=NULL;
419                                }
420                                else
421                                {       /*Now load should be full and we can call setFacetNormal*/
422                                        fAct->setFacetNormal(load);
423                                        fAct->next = new facet();
424                                        //fAct->printNormal();
425                                        fAct=fAct->next;        //this should definitely not be called in the above while-loop :D
426                                }//if (isFlippable==FALSE)
427                                delete load;
428                        }//for (int kk = 0; kk<ddrows; kk++)
429                        /*
430                        Now we should have a linked list containing the facet normals of those facets that are
431                        -irredundant
432                        -flipable
433                        Adressing is done via *facetPtr
434                        */
435                       
436                        if (compIntPoint==TRUE)
437                        {
438                                intvec *iv = new intvec(this->numVars);
439                                interiorPoint(ddineq, *iv);
440                                this->setIntPoint(iv);  //stores the interior point in gcone::ivIntPt
441                                delete iv;
442                        }
443                       
444                        //Clean up but don't delete the return value! (Whatever it will turn out to be)
445                       
446                        dd_FreeMatrix(ddineq);
447                        set_free(ddredrows);
448                        free(ddnewpos);
449                        set_free(ddlinset);
450                        dd_free_global_constants();
451
452                }//method getConeNormals(ideal I)       
453               
454               
455                /** \brief Compute the Groebner Basis on the other side of a shared facet
456                *
457                * Implements algorithm 4.3.2 from Anders' thesis.
458                * As shown there it is not necessary to compute an interior point. The knowledge of the facet normal
459                * suffices. A term \f$ x^\gamma \f$ of \f$ g \f$ is in \f$  in_\omega(g) \f$ iff \f$ \gamma - leadexp(g)\f$
460                * is parallel to \f$ leadexp(g) \f$
461                * Parallelity is checked using basic linear algebra. See gcone::isParallel.
462                * Other possibilities include computing the rank of the matrix consisting of the vectors in question and
463                * computing an interior point of the facet and taking all terms having the same weight with respect
464                * to this interior point.
465                *\param ideal, facet
466                * Input: a marked,reduced Groebner basis and a facet
467                */
468                void flip(ideal gb, facet *f)           //Compute "the other side"
469                {                       
470                        intvec *fNormal = new intvec(this->numVars);    //facet normal, check for parallelity                   
471                        fNormal = f->getFacetNormal();  //read this->fNormal;
472#ifdef gfan_DEBUG
473                        std::cout << "===" << std::endl;
474                        std::cout << "running gcone::flip" << std::endl;
475                        std::cout << "fNormal=";
476                        fNormal->show();
477                        std::cout << std::endl;
478#endif                         
479                        /*1st step: Compute the initial ideal*/
480                        poly initialFormElement[IDELEMS(gb)];   //array of #polys in GB to store initial form
481                        ideal initialForm=idInit(IDELEMS(gb),this->gcBasis->rank);
482                        poly aktpoly;
483                        intvec *check = new intvec(this->numVars);      //array to store the difference of LE and v
484                       
485                        for (int ii=0;ii<IDELEMS(gb);ii++)
486                        {
487                                aktpoly = (poly)gb->m[ii];                                                             
488                                int *v=(int *)omAlloc((this->numVars+1)*sizeof(int));
489                                int *leadExpV=(int *)omAlloc((this->numVars+1)*sizeof(int));
490                                pGetExpV(aktpoly,leadExpV);     //find the leading exponent in leadExpV[1],...,leadExpV[n], use pNext(p)
491                                initialFormElement[ii]=pHead(aktpoly);
492                               
493                                while(pNext(aktpoly)!=NULL)     /*loop trough terms and check for parallelity*/
494                                {
495                                        aktpoly=pNext(aktpoly); //next term
496                                        pSetm(aktpoly);
497                                        pGetExpV(aktpoly,v);           
498                                        /* Convert (int)v into (intvec)check */                 
499                                        for (int jj=0;jj<this->numVars;jj++)
500                                        {
501                                                //cout << "v["<<jj+1<<"]="<<v[jj+1]<<endl;
502                                                //cout << "leadExpV["<<jj+1<<"]="<<leadExpV[jj+1]<<endl;
503                                                (*check)[jj]=v[jj+1]-leadExpV[jj+1];
504                                        }
505#ifdef gfan_DEBUG
506                                        cout << "check=";                       
507                                        check->show();
508                                        cout << endl;
509#endif
510                                        if (isParallel(check,fNormal)) //pass *check when
511                                        {
512                                                cout << "Parallel vector found, adding to initialFormElement" << endl;                 
513                                                initialFormElement[ii] = pAdd(pCopy(initialFormElement[ii]),(poly)pHead(aktpoly));
514                                        }                                               
515                                }//while
516#ifdef gfan_DEBUG
517                                cout << "Initial Form=";                               
518                                pWrite(initialFormElement[ii]);
519                                cout << "---" << endl;
520#endif
521                                /*Now initialFormElement must be added to (ideal)initialForm */
522                                initialForm->m[ii]=initialFormElement[ii];
523                        }//for
524                        //f->setFlipGB(initialForm);    //FIXME PROBABLY WRONG TO STORE HERE SINCE INA!=flibGB                 
525#ifdef gfan_DEBUG
526                        cout << "Initial ideal is: " << endl;
527                        idShow(initialForm);
528                        //f->printFlipGB();
529                        cout << "===" << endl;
530#endif
531                        delete check;
532                       
533                        /*2nd step: lift initial ideal to a GB of the neighbouring cone using minus alpha as weight*/
534                        /*Substep 2.1
535                        compute $G_{-\alpha}(in_v(I))
536                        see journal p. 66
537                        */
538                        ring srcRing=currRing;
539                       
540                        /* copied and modified from ring.cc::rAssureSyzComp */
541                        //ring tmpRing=rCopyAndChangeWeight(srcRing,fNormal);
542                        ring tmpRing=rCopy0(srcRing);
543                        int i=rBlocks(srcRing);
544                        int j;
545                        tmpRing->order=(int *)omAlloc((i+1)*sizeof(int));
546                        /*NOTE This should probably be set, but as of now crashes Singular*/
547                        /*tmpRing->block0=(int *)omAlloc0((i+1)*sizeof(int));
548                        tmpRing->block1=(int *)omAlloc0((i+1)*sizeof(int));*/
549                        tmpRing->wvhdl[0] =( int *)omAlloc((fNormal->length())*sizeof(int)); //found in Singular/ipshell.cc
550                        for(j=i;j>0;j--)
551                        {
552                                tmpRing->order[j]=srcRing->order[j-1];
553                                tmpRing->block0[j]=srcRing->block0[j-1];
554                                tmpRing->block1[j]=srcRing->block1[j-1];
555                                if (srcRing->wvhdl[j-1] != NULL)
556                                {
557                                        tmpRing->wvhdl[j] = (int*) omMemDup(srcRing->wvhdl[j-1]);
558                                }
559                        }
560                        tmpRing->order[0]=ringorder_a;
561                        tmpRing->order[1]=ringorder_dp;
562                        tmpRing->order[2]=ringorder_C;
563                        //tmpRing->wvhdl[0] =( int *)omAlloc((fNormal->length())*sizeof(int)); //found in Singular/ipshell.cc
564                       
565                        for (int ii=0;ii<this->numVars;ii++)
566                        {                               
567                                tmpRing->wvhdl[0][ii]=-(*fNormal)[ii];  //What exactly am I doing here?
568                                //cout << tmpring->wvhdl[0][ii] << endl;
569                        }
570                        rComplete(tmpRing);
571                        rChangeCurrRing(tmpRing);
572                       
573                        rWrite(currRing); cout << endl;
574                        ideal ina;                     
575                        ina=idrCopyR(initialForm,srcRing);                     
576#ifdef gfan_DEBUG
577                        cout << "ina=";
578                        idShow(ina); cout << endl;
579#endif
580                        ideal H;
581                        H=kStd(ina,NULL,isHomog,NULL);  //we know it is homogeneous
582                        idSkipZeroes(H);
583#ifdef gfan_DEBUG
584                        cout << "H="; idShow(H); cout << endl;
585#endif
586                        /*Substep 2.2
587                        do the lifting and mark according to H
588                        */
589                        rChangeCurrRing(srcRing);
590                        ideal srcRing_H;
591                        ideal srcRing_HH;                       
592                        srcRing_H=idrCopyR(H,tmpRing);
593#ifdef gfan_DEBUG
594                        cout << "srcRing_H = ";
595                        idShow(srcRing_H); cout << endl;
596#endif
597                        srcRing_HH=ffG(srcRing_H,this->gcBasis);               
598#ifdef gfan_DEBUG
599                        cout << "srcRing_HH = ";
600                        idShow(srcRing_HH); cout << endl;
601#endif
602                        /*Substep 2.2.1
603                        Mark according to G_-\alpha
604                        Here we have a minimal basis srcRing_HH. In order to turn this basis into a reduced basis
605                        we have to compute an interior point of C(srcRing_HH). For this we need to know the cone
606                        represented by srcRing_HH MARKED ACCORDING TO G_{-\alpha}
607                        Thus we check whether the leading monomials of srcRing_HH and srcRing_H coincide. If not we
608                        compute the difference accordingly
609                        */
610                        dd_set_global_constants();
611                        bool markingsAreCorrect=FALSE;
612                        dd_MatrixPtr intPointMatrix;
613                        int iPMatrixRows=0;
614                        dd_rowrange aktrow=0;                   
615                        for (int ii=0;ii<IDELEMS(srcRing_HH);ii++)
616                        {
617                                poly aktpoly=(poly)srcRing_HH->m[ii];
618                                iPMatrixRows = iPMatrixRows+pLength(aktpoly)-1;
619                        }
620                        /* additionally one row for the standard-simplex and another for a row that becomes 0 during
621                        construction of the differences
622                        */
623                        intPointMatrix = dd_CreateMatrix(iPMatrixRows+2,this->numVars+1);
624                        intPointMatrix->numbtype=dd_Integer;    //NOTE: DO NOT REMOVE OR CHANGE TO dd_Rational
625                       
626                        for (int ii=0;ii<IDELEMS(srcRing_HH);ii++)
627                        {
628                                markingsAreCorrect=FALSE;       //crucial to initialise here
629                                poly aktpoly=srcRing_HH->m[ii];
630                                /*Comparison of leading monomials is done via exponent vectors*/
631                                for (int jj=0;jj<IDELEMS(H);jj++)
632                                {
633                                        int *src_ExpV = (int *)omAlloc((this->numVars+1)*sizeof(int));
634                                        int *dst_ExpV = (int *)omAlloc((this->numVars+1)*sizeof(int));
635                                        pGetExpV(aktpoly,src_ExpV);
636                                        rChangeCurrRing(tmpRing);       //this ring change is crucial!
637                                        pGetExpV(pCopy(H->m[ii]),dst_ExpV);
638                                        rChangeCurrRing(srcRing);
639                                        bool expVAreEqual=TRUE;
640                                        for (int kk=1;kk<=this->numVars;kk++)
641                                        {
642                                                cout << src_ExpV[kk] << "," << dst_ExpV[kk] << endl;
643                                                if (src_ExpV[kk]!=dst_ExpV[kk])
644                                                {
645                                                        expVAreEqual=FALSE;
646                                                }
647                                        }                                       
648                                        //if (*src_ExpV == *dst_ExpV)
649                                        if (expVAreEqual==TRUE)
650                                        {
651                                                markingsAreCorrect=TRUE; //everything is fine
652                                                cout << "correct markings" << endl;
653                                        }//if (pHead(aktpoly)==pHead(H->m[jj])
654                                        delete src_ExpV;
655                                        delete dst_ExpV;
656                                }//for (int jj=0;jj<IDELEMS(H);jj++)
657                               
658                                int *v=(int *)omAlloc((this->numVars+1)*sizeof(int));
659                                int *leadExpV=(int *)omAlloc((this->numVars+1)*sizeof(int));
660                                if (markingsAreCorrect==TRUE)
661                                {
662                                        pGetExpV(aktpoly,leadExpV);
663                                }
664                                else
665                                {
666                                        rChangeCurrRing(tmpRing);
667                                        pGetExpV(pHead(H->m[ii]),leadExpV); //We use H->m[ii] as leading monomial
668                                        rChangeCurrRing(srcRing);
669                                }
670                                /*compute differences of the expvects*/                         
671                                while (pNext(aktpoly)!=NULL)
672                                {
673                                        /*The following if-else-block makes sure the first term (i.e. the wrongly marked term)
674                                        is not omitted when computing the differences*/
675                                        if(markingsAreCorrect==TRUE)
676                                        {
677                                                aktpoly=pNext(aktpoly);
678                                                pGetExpV(aktpoly,v);
679                                        }
680                                        else
681                                        {
682                                                pGetExpV(pHead(aktpoly),v);
683                                                markingsAreCorrect=TRUE;
684                                        }
685
686                                        for (int jj=0;jj<this->numVars;jj++)
687                                        {                               
688                                                /*Store into ddMatrix*/                                                         
689                                                dd_set_si(intPointMatrix->matrix[aktrow][jj+1],leadExpV[jj+1]-v[jj+1]);
690                                        }
691                                        aktrow +=1;
692                                }
693                                delete v;
694                                delete leadExpV;
695                        }//for (int ii=0;ii<IDELEMS(srcRing_HH);ii++)
696                        /*Now we add the constraint for the standard simplex*/
697                        /*NOTE:Might actually work without the standard simplex*/
698                        dd_set_si(intPointMatrix->matrix[aktrow][0],-1);
699                        for (int jj=1;jj<=this->numVars;jj++)
700                        {
701                                dd_set_si(intPointMatrix->matrix[aktrow][jj],1);
702                        }
703                        dd_WriteMatrix(stdout,intPointMatrix);
704                        intvec *iv_weight = new intvec(this->numVars);
705                        interiorPoint(intPointMatrix, *iv_weight);      //iv_weight now contains the interior point
706                        dd_FreeMatrix(intPointMatrix);
707                        dd_free_global_constants();
708                       
709                        /*Step 3
710                        turn the minimal basis into a reduced one
711                        */
712                        ring dstRing=rCopy0(srcRing);
713                        i=rBlocks(srcRing);
714                       
715                        dstRing->order=(int *)omAlloc((i+1)*sizeof(int));
716                        for(j=i;j>0;j--)
717                        {
718                                dstRing->order[j]=srcRing->order[j-1];
719                                dstRing->block0[j]=srcRing->block0[j-1];
720                                dstRing->block1[j]=srcRing->block1[j-1];
721                                if (srcRing->wvhdl[j-1] != NULL)
722                                {
723                                        dstRing->wvhdl[j] = (int*) omMemDup(srcRing->wvhdl[j-1]);
724                                }
725                        }
726                        dstRing->order[0]=ringorder_a;
727                        dstRing->order[1]=ringorder_dp;
728                        dstRing->order[2]=ringorder_C;                 
729                        dstRing->wvhdl[0] =( int *)omAlloc((iv_weight->length())*sizeof(int));
730                       
731                        for (int ii=0;ii<this->numVars;ii++)
732                        {                               
733                                dstRing->wvhdl[0][ii]=(*iv_weight)[ii];                         
734                        }
735                        rComplete(dstRing);
736                        rChangeCurrRing(dstRing);
737#ifdef gfan_DEBUG
738                        rWrite(dstRing); cout << endl;
739#endif
740                        ideal dstRing_I;                       
741                        dstRing_I=idrCopyR(srcRing_HH,srcRing);                 
742                        //validOpts<1>=TRUE;
743#ifdef gfan_DEBUG
744                        idShow(dstRing_I);
745#endif                 
746                        BITSET save=test;
747                        test|=Sy_bit(OPT_REDSB);
748                        test|=Sy_bit(6);        //OPT_DEBUG                                     
749                        dstRing_I=kStd(idrCopyR(this->inputIdeal,this->rootRing),NULL,testHomog,NULL);                                 
750                        kInterRed(dstRing_I);
751                        idSkipZeroes(dstRing_I);
752                        test=save;
753                        /*End of step 3 - reduction*/
754                       
755                        f->setFlipGB(dstRing_I);//store the flipped GB
756#ifdef gfan_DEBUG
757                        cout << "Flipped GB is: " << endl;
758                        f->printFlipGB();
759#endif                 
760                }//void flip(ideal gb, facet *f)
761                               
762                /** \brief Compute the remainder of a polynomial by a given ideal
763                *
764                * Compute \f$ f^{\mathcal{G}} \f$
765                * Algorithm is taken from Cox, Little, O'Shea, IVA 2nd Ed. p 62
766                * However, since we are only interested in the remainder, there is no need to
767                * compute the factors \f$ a_i \f$
768                */
769                //NOTE: Should be replaced by kNF or kNF2
770                poly restOfDiv(poly const &f, ideal const &I)
771                {
772                        cout << "Entering restOfDiv" << endl;
773                        poly p=f;
774                        pWrite(p);
775                        //poly r=kCreateZeroPoly(,currRing,currRing);   //The 0-polynomial, hopefully
776                        poly r=NULL;    //The zero polynomial
777                        int ii;
778                        bool divOccured;
779                       
780                        while (p!=NULL)
781                        {
782                                ii=1;
783                                divOccured=FALSE;
784                               
785                                while( (ii<=IDELEMS(I) && (divOccured==FALSE) ))
786                                {                                       
787                                        if (pDivisibleBy(I->m[ii-1],p)) //does LM(I->m[ii]) divide LM(p) ?
788                                        {
789                                                //cout << "TICK 3" << endl;
790                                                poly step1,step2,step3;
791                                                //cout << "dividing "; pWrite(pHead(p));cout << "by ";pWrite(pHead(I->m[ii-1])); cout << endl;
792                                                step1 = pDivideM(pHead(p),pHead(I->m[ii-1]));
793                                                //cout << "LT(p)/LT(f_i)="; pWrite(step1); cout << endl;
794                                                //cout << "TICK 3.1" << endl;
795                                                step2 = ppMult_qq(step1, I->m[ii-1]);
796                                                //cout << "TICK 3.2" << endl;
797                                                step3 = pSub(pCopy(p), step2);
798                                                //p=pSub(p,pMult( pDivide(pHead(p),pHead(I->m[ii])), I->m[ii]));
799                                                //cout << "TICK 4" << endl;
800                                                //pSetm(p);
801                                                pSort(step3); //must be here, otherwise strange behaviour with many +o+o+o+o+ terms
802                                                p=step3;
803                                                pWrite(p);                                             
804                                                divOccured=TRUE;
805                                        }
806                                        else
807                                        {
808                                                ii += 1;
809                                        }//if (pLmDivisibleBy(I->m[ii],p,currRing))
810                                }//while( (ii<IDELEMS(I) && (divOccured==FALSE) ))
811                                if (divOccured==FALSE)
812                                {
813                                        //cout << "TICK 5" << endl;
814                                        r=pAdd(pCopy(r),pHead(p));
815                                        pSetm(r);
816                                        pSort(r);
817                                        //cout << "r="; pWrite(r); cout << endl;
818                                        //cout << "TICK 6" << endl;
819                                        if (pLength(p)!=1)
820                                        {
821                                                p=pSub(pCopy(p),pHead(p));      //Here it may occur that p=0 instead of p=NULL
822                                        }
823                                        else
824                                        {
825                                                p=NULL; //Hack to correct this situation                                               
826                                        }
827                                        //cout << "TICK 7" << endl;
828                                        //cout << "p="; pWrite(p);
829                                }//if (divOccured==FALSE)
830                        }//while (p!=0)
831                        return r;
832                }//poly restOfDiv(poly const &f, ideal const &I)
833               
834                /** \brief Compute \f$ f-f^{\mathcal{G}} \f$
835                */
836                //NOTE: use kNF or kNF2 instead of restOfDivision
837                ideal ffG(ideal const &H, ideal const &G)
838                {
839                        cout << "Entering ffG" << endl;
840                        int size=IDELEMS(H);
841                        ideal res=idInit(size,1);
842                        poly temp1, temp2, temp3;       //polys to temporarily store values for pSub
843                        for (int ii=0;ii<size;ii++)
844                        {
845                                res->m[ii]=restOfDiv(H->m[ii],G);
846                                //res->m[ii]=kNF(H->m[ii],G);
847                                temp1=H->m[ii];
848                                temp2=res->m[ii];                               
849                                temp3=pSub(temp1, temp2);
850                                res->m[ii]=temp3;
851                                //res->m[ii]=pSub(temp1,temp2); //buggy
852                                //pSort(res->m[ii]);
853                                //pSetm(res->m[ii]);
854                                cout << "res->m["<<ii<<"]=";pWrite(res->m[ii]);                                         
855                        }                       
856                        return res;
857                }
858               
859                /** \brief Compute a Groebner Basis
860                *
861                * Computes the Groebner basis and stores the result in gcone::gcBasis
862                *\param ideal
863                *\return void
864                */
865                void getGB(ideal const &inputIdeal)
866                {
867                        ideal gb;
868                        gb=kStd(inputIdeal,NULL,testHomog,NULL);
869                        idSkipZeroes(gb);
870                        this->gcBasis=gb;       //write the GB into gcBasis
871                }//void getGB
872               
873                /** \brief The Generic Groebner Walk due to FJLT
874                * Needed for computing the search facet
875                */
876                ideal GenGrbWlk(ideal, ideal)
877                {
878                }//GGW
879
880
881                /** \brief Compute the dot product of two intvecs
882                *
883                */
884                int dotProduct(intvec const &iva, intvec const &ivb)                           
885                {
886                        //intvec iva=a;
887                        //intvec ivb=b;
888                        int res=0;
889                        for (int i=0;i<this->numVars;i++)
890                        {
891                                res = res+(iva[i]*ivb[i]);
892                        }
893                        return res;
894                }//int dotProduct
895
896                /** \brief Check whether two intvecs are parallel
897                *
898                * \f$ \alpha\parallel\beta\Leftrightarrow\langle\alpha,\beta\rangle^2=\langle\alpha,\alpha\rangle\langle\beta,\beta\rangle \f$
899                */
900                bool isParallel(intvec const &a, intvec const &b)
901                {                       
902                        int lhs,rhs;
903                        lhs=dotProduct(a,b)*dotProduct(a,b);
904                        rhs=dotProduct(a,a)*dotProduct(b,b);
905                        cout << "LHS="<<lhs<<", RHS="<<rhs<<endl;
906                        if (lhs==rhs)
907                        {
908                                return TRUE;
909                        }
910                        else
911                        {
912                                return FALSE;
913                        }
914                }//bool isParallel
915               
916                /** \brief Compute an interior point of a given cone
917                */
918                void interiorPoint(dd_MatrixPtr const &M, intvec &iv) //no const &M here since we want to remove redundant rows
919                {
920                        dd_LPPtr lp,lpInt;
921                        dd_ErrorType err=dd_NoError;
922                        dd_LPSolverType solver=dd_DualSimplex;
923                        dd_LPSolutionPtr lpSol=NULL;
924                        dd_rowset ddlinset,ddredrows;   //needed for dd_FindRelativeInterior
925                        dd_rowindex ddnewpos;
926                        dd_NumberType numb;     
927                        //M->representation=dd_Inequality;
928                        //M->objective-dd_LPMin;  //Not sure whether this is needed
929                        dd_set_si(M->rowvec[0],1);dd_set_si(M->rowvec[1],1);dd_set_si(M->rowvec[2],1);
930                        //cout << "TICK 1" << endl;
931                                               
932                        //dd_MatrixCanonicalize(&M, &ddlinset, &ddredrows, &ddnewpos, &err);
933                        //if (err!=dd_NoError){cout << "Error during dd_MatrixCanonicalize" << endl;}
934                        //cout << "Tick 2" << endl;
935                        //dd_WriteMatrix(stdout,M);
936                       
937                        lp=dd_Matrix2LP(M, &err);
938                        if (err!=dd_NoError){cout << "Error during dd_Matrix2LP in gcone::interiorPoint" << endl;}                     
939                        if (lp==NULL){cout << "LP is NULL" << endl;}
940                        dd_WriteLP(stdout,lp);
941                        //cout << "Tick 3" << endl;
942                                               
943                        lpInt=dd_MakeLPforInteriorFinding(lp);
944                        if (err!=dd_NoError){cout << "Error during dd_MakeLPForInteriorFinding in gcone::interiorPoint" << endl;}
945                        dd_WriteLP(stdout,lpInt);
946                        //cout << "Tick 4" << endl;
947                       
948                        dd_FindRelativeInterior(M,&ddlinset,&ddredrows,&lpSol,&err);
949                        if (err!=dd_NoError)
950                        {
951                                cout << "Error during dd_FindRelativeInterior in gcone::interiorPoint" << endl;
952                                dd_WriteErrorMessages(stdout, err);
953                        }
954                       
955                        //dd_LPSolve(lpInt,solver,&err);        //This will not result in a point from the relative interior
956                        if (err!=dd_NoError){cout << "Error during dd_LPSolve" << endl;}
957                        //cout << "Tick 5" << endl;
958                                                                       
959                        //lpSol=dd_CopyLPSolution(lpInt);
960                        if (err!=dd_NoError){cout << "Error during dd_CopyLPSolution" << endl;}                 
961                        //cout << "Tick 6" << endl;
962#ifdef gfan_DEBUG
963                        cout << "Interior point: ";
964#endif
965                        for (int ii=1; ii<(lpSol->d)-1;ii++)
966                        {
967#ifdef gfan_DEBUG
968                                dd_WriteNumber(stdout,lpSol->sol[ii]);
969#endif
970                                /* NOTE This works only as long as gmp returns fractions with the same denominator*/
971                                (iv)[ii-1]=(int)mpz_get_d(mpq_numref(lpSol->sol[ii]));  //looks evil, but does the trick
972                        }
973                        dd_FreeLPSolution(lpSol);
974                        dd_FreeLPData(lpInt);
975                        dd_FreeLPData(lp);
976                        set_free(ddlinset);
977                        set_free(ddredrows);                   
978                       
979                }//void interiorPoint(dd_MatrixPtr const &M)
980               
981                ring rCopyAndChangeWeight(ring const r, intvec const *ivw)                             
982                {
983                        ring res=rCopy0(r, FALSE, FALSE);
984                        int i=rBlocks(r);
985                        int j;
986
987                        res->order=(int *)omAlloc((i+1)*sizeof(int));
988                        /*res->block0=(int *)omAlloc0((i+1)*sizeof(int));
989                        res->block1=(int *)omAlloc0((i+1)*sizeof(int));
990                        int ** wvhdl =(int **)omAlloc0((i+1)*sizeof(int**));*/
991                        for(j=i;j>0;j--)
992                        {
993                                res->order[j]=r->order[j-1];
994                                res->block0[j]=r->block0[j-1];
995                                res->block1[j]=r->block1[j-1];
996                                if (r->wvhdl[j-1] != NULL)
997                                {
998                                        res->wvhdl[j] = (int*) omMemDup(r->wvhdl[j-1]);
999                                }
1000                        }
1001                        res->order[0]=ringorder_a;
1002                        res->order[1]=ringorder_dp;
1003                        res->order[2]=ringorder_C;
1004                        //res->wvhdl = wvhdl;
1005                       
1006                        res->wvhdl[0] =( int *)omAlloc((ivw->length())*sizeof(int));
1007                        for (int ii=0;ii<this->numVars;ii++)
1008                        {                               
1009                                res->wvhdl[0][ii]=(*ivw)[ii];                           
1010                        }                       
1011                       
1012                        rComplete(res);
1013                        return res;
1014                }//rCopyAndChange
1015               
1016                void reverseSearch()
1017                {
1018                }//reverseSearch
1019};//class gcone
1020
1021ideal gfan(ideal inputIdeal)
1022{
1023        int numvar = pVariables; 
1024       
1025        #ifdef gfan_DEBUG
1026        cout << "Now in subroutine gfan" << endl;
1027        #endif
1028        ring inputRing=currRing;        // The ring the user entered
1029        ring rootRing;                  // The ring associated to the target ordering
1030        ideal res;     
1031        facet *fRoot;
1032       
1033        /*
1034        1. Select target order, say dp.
1035        2. Compute GB of inputIdeal wrt target order -> newRing, setCurrRing etc...
1036        3. getConeNormals
1037        */
1038       
1039        /* Construct a new ring which will serve as our root
1040        Does not yet work as expected. Will work fine with order dp,Dp but otherwise hangs in getGB
1041        resolved 07.04.2009 MM
1042        */
1043        rootRing=rCopy0(currRing);
1044        rootRing->order[0]=ringorder_lp;
1045        //NOTE: Build ring accordiing to rCopyAndChangeWeight
1046        /*rootRing->order[0]=ringorder_a;
1047        rootRing->order[1]=ringorder_lp;
1048        rootRing->wvhdl[0] =( int *)omAlloc(numvar*sizeof(int));
1049        rootRing->wvhdl[0][1]=1;
1050        rootRing->wvhdl[0][2]=1;*/
1051        rComplete(rootRing);
1052        rChangeCurrRing(rootRing);
1053       
1054        /* Fetch the inputIdeal into our rootRing */
1055        map theMap=(map)idMaxIdeal(1);  //evil hack!
1056        theMap->preimage=NULL;  //neccessary?
1057        ideal rootIdeal;
1058        rootIdeal=fast_map(inputIdeal,inputRing,(ideal)theMap, currRing);
1059#ifdef gfan_DEBUG
1060        cout << "Root ideal is " << endl;
1061        idShow(rootIdeal);
1062        cout << "The root ring is " << endl;
1063        rWrite(rootRing);
1064        cout << endl;
1065#endif 
1066       
1067        //gcone *gcRoot = new gcone();  //Instantiate the sink
1068        gcone *gcRoot = new gcone(rootRing,rootIdeal);
1069        gcone *gcAct;
1070        gcAct = gcRoot;
1071        gcAct->numVars=pVariables;
1072        gcAct->getGB(rootIdeal);        //sets gcone::gcBasis
1073        idShow(gcAct->gcBasis);
1074        gcAct->getConeNormals(gcAct->gcBasis);  //hopefully compute the normals
1075        //gcAct->flip(gcAct->gcBasis,gcAct->facetPtr);
1076        /*Now it is time to compute the search facets, respectively start the reverse search.
1077        But since we are in the root all facets should be search facets. IS THIS TRUE?
1078        NOTE: Check for flippability is not very sophisticated
1079        */
1080        facet *fAct=new facet();
1081        fAct=gcAct->facetPtr;
1082        while(fAct->next!=NULL)
1083        {
1084                gcAct->flip(gcAct->gcBasis,gcAct->facetPtr);
1085                gcone *gcTmp = new gcone(*gcAct);
1086                idShow(gcTmp->gcBasis);
1087                gcTmp->getConeNormals(gcTmp->gcBasis, TRUE);
1088                gcTmp->getIntPoint();
1089                fAct = fAct->next;             
1090        }
1091       
1092        /*As of now extra.cc expects gfan to return type ideal. Probably this will change in near future.
1093        The return type will then be of type LIST_CMD
1094        Assume gfan has finished, thus we have enumerated all the cones
1095        Create an array of size of #cones. Let each entry in the array contain a pointer to the respective
1096        Groebner Basis and merge this somehow with LIST_CMD
1097        => Count the cones!
1098        */
1099        rChangeCurrRing(rootRing);
1100        //res=gcAct->gcBasis;
1101        res=gcRoot->gcBasis;   
1102        return res;
1103        //return GBlist;
1104}
1105/*
1106Since gfan.cc is #included from extra.cc there must not be a int main(){} here
1107*/
1108#endif
Note: See TracBrowser for help on using the repository browser.