source: git/kernel/gfan.cc @ f9db28

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