Annotation of OpenXM_contrib/TiGERS_0.9/gset.c, Revision 1.1
1.1 ! maekawa 1: /*
! 2: ** gset.c Birk Huber, 4/99
! 3: ** -- definitions and basic operations on gsets
! 4: **
! 5: **
! 6: ** TiGERS, Toric Groebner Basis Enumeration by Reverse Search
! 7: ** copyright (c) 1999 Birk Huber
! 8: **
! 9: */
! 10: #include<stdio.h>
! 11: #include<stdlib.h>
! 12: #include "utils.h"
! 13: #include "gset.h"
! 14: #include "matrices.h"
! 15: #include "Rsimp.h"
! 16:
! 17: /* uncomment the following to cause use sainity checks (not fully tested)*/
! 18: /*
! 19: #define GTEST 0
! 20: #include "gtesting.h"
! 21: */
! 22:
! 23: /*
! 24: ** create an empty gset, initialize all its pointers to null.
! 25: */
! 26: gset gset_new(){
! 27: gset g=0;
! 28: if ((g=(gset)malloc(sizeof(struct gset_tag)))==0){
! 29: fprintf(stderr,"gset_new(): malloc failed\n");
! 30: return 0;
! 31: }
! 32: gset_first(g)=0;
! 33: gset_cache_vtx(g)=0;
! 34: gset_cache_edge(g)=0;
! 35: return g;
! 36: }
! 37:
! 38: /*
! 39: ** delete a gset and all binomials in it.
! 40: */
! 41: void gset_free(gset g){
! 42: binomial b;
! 43: while((b=gset_first(g))!=0){
! 44: gset_first(g)=binomial_next(b);
! 45: binomial_free(b);
! 46: }
! 47: free((void *)g);
! 48: }
! 49:
! 50:
! 51: /*
! 52: ** read a gset from an input stream
! 53: ** (return TRUE if gset read in )
! 54: */
! 55: int gset_read(FILE *is,gset g){
! 56: char c;
! 57: binomial b;
! 58:
! 59: eatwhite(is);
! 60: c=getc(is);
! 61: if (c!='{') return FALSE;
! 62: c=',';
! 63: while(c==','){
! 64: b=binomial_new();
! 65: binomial_read(is,b);
! 66: gset_insert(g,b);
! 67: eatwhite(is);
! 68: c=getc(is);
! 69: }
! 70: if (c!='}'){
! 71: fprintf(stderr,"gset_read(): gset should end with a '}'\n");
! 72: return FALSE;
! 73: }
! 74: ungetc(c,is);
! 75: return TRUE;
! 76: }
! 77:
! 78: /*
! 79: ** Display a gset
! 80: */
! 81: void gset_print(FILE *of,gset g){
! 82: binomial b;
! 83:
! 84: fprintf(of,"{");
! 85: for(b=g->bottom;b!=0;b=b->next){
! 86: binomial_print(of,b);
! 87: if (b->next!=0) fprintf(of,", ");
! 88: }
! 89: fprintf(of,"}");
! 90: }
! 91:
! 92: /*
! 93: ** Display a gsets initial ideal
! 94: */
! 95: void gset_init_print(FILE *of,gset g){
! 96: binomial b;
! 97: fprintf(of,"{");
! 98: for(b=g->bottom;b!=0;b=b->next){
! 99: print_monomial(of,binomial_lead(b));
! 100: if (b->next!=0) fprintf(of,", ");
! 101: }
! 102: fprintf(of,"}");
! 103: }
! 104:
! 105: /*
! 106: ** Display a facet binomials
! 107: */
! 108: void gset_facet_print(FILE *of,gset g){
! 109: binomial b;
! 110: int tog=0;
! 111: fprintf(of,"{");
! 112: for(b=g->bottom;b!=0;b=b->next){
! 113: if (b->ff==FACET){
! 114: if (tog==1) fprintf(of,",");
! 115: else tog=1;
! 116: binomial_print(of,b);
! 117: }
! 118: }
! 119: fprintf(of,"}");
! 120: }
! 121:
! 122: /*
! 123: ** place binomial in gset in decreasing lexicographic order.
! 124: ** (using binomial_compair(,) to determine reletive order or
! 125: ** binomials)
! 126: */
! 127: void gset_insert(gset g, binomial b){
! 128: binomial t1,t2;
! 129: if (gset_first(g)==0 || binomial_compair(gset_first(g),b)==FALSE){
! 130: binomial_next(b)=gset_first(g);
! 131: gset_first(g)=b;
! 132: }
! 133: else{
! 134: t1=gset_first(g);
! 135: while(t1!=0){
! 136: t2=binomial_next(t1);
! 137: if (t2==0 || binomial_compair(t2,b)==FALSE){
! 138: binomial_next(t1)=b;
! 139: binomial_next(b)=t2;
! 140: break;
! 141: }
! 142: t1=t2;
! 143: }
! 144: }
! 145: }
! 146:
! 147: /*
! 148: ** return first facet binomial which is mis-marked
! 149: */
! 150: binomial gset_downedge(gset g){
! 151: binomial ptr=0;
! 152: for(ptr=gset_first(g);ptr!=0;ptr=binomial_next(ptr)){
! 153: if (binomial_ordered(ptr)==FALSE && gset_isfacet(g,ptr)==TRUE)break;
! 154: }
! 155: return ptr;
! 156: }
! 157:
! 158:
! 159: /*
! 160: ++void bmprint(FILE *of,binomial B, binomial M):
! 161: ++ simple output function for a generating set consisting of a binomial and
! 162: ++ a list of monomials --- usefull mainly for debugging. -- gset output
! 163: ++ routing may be modified in such a way as to use code which could double
! 164: ++ for this purpose.
! 165: ++
! 166: */
! 167: void bmprint(FILE *of,binomial B, binomial M){
! 168: fprintf(of,"{ ");
! 169: if (B!=0) binomial_print(of,B);
! 170: while(M!=0){
! 171: fprintf(of,",");
! 172: binomial_print(of,M);
! 173: M=binomial_next(M);
! 174: }
! 175: fprintf(of,"}\n");
! 176: }
! 177:
! 178: /*
! 179: **binomial bmleadreduce(binomial m1, binomial B, binomial mlist):
! 180: ** "lift" monomial m1 to a binomial using bmlist B,mlist.
! 181: */
! 182: binomial bmleadreduce(binomial m1, binomial B, binomial mlist){
! 183: binomial res,ptr;
! 184: /* case 1: the binomial is used in the decomp:*/
! 185: if (monomial_divides(binomial_lead(B),binomial_lead(m1))==TRUE){
! 186: res=binomial_new();
! 187: binomial_copy(B,res);
! 188: binomial_bumpto(res,m1);
! 189:
! 190: /* now reduce by lt(b) as many times as possible */
! 191: while(monomial_divides(binomial_lead(B),binomial_trail(res))==TRUE){
! 192: reducetrail(res,B);
! 193: }
! 194:
! 195: /* now find a monomial deviding whats left and reduce by it*/
! 196: for(ptr=mlist;ptr!=0;ptr=ptr->next){
! 197: if (monomial_divides(binomial_lead(ptr),binomial_trail(res))==TRUE){
! 198: reducetrail(res,ptr);
! 199: return res;
! 200: }
! 201: }
! 202: }
! 203: else { /* case 2 -- our monomial is a multiple of some monomial*/
! 204: for(ptr=mlist;ptr!=0;ptr=ptr->next){
! 205: if (monomial_divides(binomial_lead(ptr),binomial_lead(m1))==TRUE){
! 206: res=binomial_new();
! 207: binomial_copy(ptr,res);
! 208: binomial_set(res);
! 209: binomial_bumpto(res,m1);
! 210: return res;
! 211: }
! 212: }
! 213: }
! 214: fprintf(stderr, "Warning BMreduce does not get to zero\n");
! 215: }
! 216:
! 217:
! 218:
! 219: /*
! 220: ++ binomial find_divisor(binomial S,binomial L):
! 221: ++ search list starting at L for a monomial dividing S
! 222: ++ return this binomial or zero if no such binomial exists on list.
! 223: ++
! 224: */
! 225: binomial find_divisor(binomial S,binomial L){
! 226: binomial ptr;
! 227: for(ptr=L;ptr!=0;ptr=ptr->next){
! 228: if(ptr!=S&&monomial_divides(binomial_lead(ptr),binomial_lead(S))==TRUE){
! 229: break;
! 230: }
! 231: }
! 232: return ptr;
! 233: }
! 234:
! 235:
! 236: /*
! 237: ++ void remove_multiples(binomial S, binomial *L):
! 238: ++ Pass through list starting at *L, removing all multiples of *S
! 239: ++ encountered (except S if it is on the list).
! 240: ++
! 241: */
! 242: void remove_multiples(binomial S, binomial *L){
! 243: binomial tlist=*L,ptr;
! 244: *L=0;
! 245: while(tlist!=0){
! 246: ptr=tlist; tlist=tlist->next; ptr->next=0; /* pop tlist*/
! 247: if (S==ptr || monomial_divides(binomial_lead(S),binomial_lead(ptr))==FALSE) {
! 248: ptr->next=*L; /* push L */
! 249: *L=ptr;
! 250: }
! 251: else binomial_free(ptr);
! 252: }
! 253: }
! 254:
! 255: /*
! 256: ** void bmrgb(binomial B, binomial *ms):
! 257: ** transform a marked binomial and a list of monomials into the
! 258: ** reduced grobner basis for the ideal the generate.
! 259: **
! 260: */
! 261: void bmrgb(binomial B, binomial *ms){
! 262: int i,jk;
! 263: binomial DL,SL,tlist,S,tmp,ptr;
! 264: int szero;
! 265:
! 266: DL=*ms;
! 267: SL=0;
! 268:
! 269: while(DL!=0){
! 270: tmp=DL; DL=DL->next; /* pop DL */
! 271: tmp->next=SL; SL=tmp; /* push SL */
! 272:
! 273: /* calculate normal form of S pair with respect to {B}*/
! 274: S=monomial_spair(B,binomial_lead(tmp));
! 275:
! 276: /* check if anything on DL or on SL divides S*/
! 277: if (find_divisor(S,SL)!=0||find_divisor(S,DL)!=0)binomial_free(S);
! 278: else {
! 279: remove_multiples(S,&SL); /* remove any multiples of S from SL*/
! 280: remove_multiples(S,&DL); /* remove any multiples of S from DL*/
! 281: S->next=DL; DL=S; /* finally push S onto DL */
! 282: }
! 283: }
! 284:
! 285: remove_multiples(B,&SL); /* now that we have a grobner basis
! 286: we can remove multiples of lead(B)
! 287: from the monomial list */
! 288:
! 289: // replace list bottom pointer
! 290: *ms=SL;
! 291:
! 292: }
! 293:
! 294: /*
! 295: ** gset gset_flip(gset g1, binomial b):
! 296: ** Take a gset and one of its facet binomials and produce the new gset
! 297: ** corresponding to the grobner cone which shares the given facet binomial.
! 298: **
! 299: */
! 300: gset gset_flip(gset g1, binomial b){
! 301: binomial old=0,new=0,tmp,ptr,B,Bold;
! 302: gset gres=0, gtest=0;
! 303:
! 304: /* sainity check -- remove eventually*/
! 305: #ifdef GTEST
! 306: if (lp_isfacet(g1,b)!=FACET){
! 307: fprintf(stdout,"WARNING flip asked to flip non-binomial\n");
! 308: }
! 309: #endif
! 310:
! 311: /* copy all binomials of g's list ecept b to old and new lists*/
! 312: for(ptr=gset_first(g1);ptr!=0;ptr=ptr->next){
! 313: if (ptr!=b){
! 314: tmp=binomial_new();
! 315: binomial_copy(ptr,tmp);
! 316: monomial_set(tmp);
! 317: binomial_next(tmp)=new;
! 318: new=tmp;
! 319: tmp=binomial_new();
! 320: binomial_copy(ptr,tmp);
! 321: monomial_set(tmp);
! 322: binomial_next(tmp)=old;
! 323: old=tmp;
! 324: }
! 325: }
! 326: Bold=binomial_new();
! 327: binomial_copy(b,Bold);
! 328:
! 329: /* make fliped copy of b*/
! 330: B=binomial_new();
! 331: binomial_copy(b,B);
! 332: binomial_flip(B);
! 333:
! 334: /* calculate the reduced GB of the binomial b and the monomials in M */
! 335: bmrgb(B,&new);
! 336:
! 337: /* create new gset and insert flipped copy of b */
! 338: gres=gset_new();
! 339: gset_insert(gres,B);
! 340:
! 341: /* do lifting of elements in mlist and add them to new gset*/
! 342: while((tmp=new)!=0){
! 343: new=new->next;
! 344: ptr=bmleadreduce(tmp,Bold,old);
! 345: gset_insert(gres,ptr);
! 346: binomial_free(tmp);
! 347: }
! 348:
! 349: /* sainity check -- remove eventually*/
! 350: #ifdef GTEST
! 351: if (gset_is_gb(gres)==FALSE){
! 352: fprintf(stderr,"flipped failed to find grobner basis \n");
! 353: fprintf(stderr,"g1=");gset_print(stderr,g1);fprintf(stderr,"\n");
! 354: fprintf(stderr,"b=");binomial_print(stderr,b);fprintf(stderr,"\n");
! 355: exit(1);
! 356: }
! 357: #endif
! 358:
! 359: binomial_free(Bold);
! 360: while(old!=0){
! 361: ptr=old;
! 362: old=old->next;
! 363: binomial_free(ptr);
! 364: }
! 365:
! 366: gset_autoreduce(gres);
! 367:
! 368: /* sainity check -- remove eventually */
! 369: #ifdef GTEST
! 370: if ( gset_is_reduced(gres)==FALSE){
! 371: fprintf(stderr,"flipped failed to find reduced grobner basis \n");
! 372: fprintf(stderr,"g1=");gset_print(stderr,g1);fprintf(stderr,"\n");
! 373: fprintf(stderr,"b=");binomial_print(stderr,b);fprintf(stderr,"\n");
! 374: exit(1);
! 375: }
! 376: #endif
! 377:
! 378: return gres;
! 379: }
! 380:
! 381:
! 382: /*
! 383: ** void gset_autoreduce(gset g):
! 384: ** autoreduce g according to its marking
! 385: */
! 386: void gset_autoreduce(gset g){
! 387: binomial b1,b2;
! 388: int changed;
! 389:
! 390: /* First remove redundant elements from the grobner basis*/
! 391: while(find_divisor(gset_first(g),gset_first(g))!=0){
! 392: gset_first(g)=(b1=gset_first(g))->next;
! 393: binomial_free(b1);
! 394: }
! 395: b1=gset_first(g);
! 396: while(b1!=0 && binomial_next(b1)!=0){
! 397: if (find_divisor(binomial_next(b1),gset_first(g))!=0) {
! 398: b2=binomial_next(b1);
! 399: binomial_next(b1)=binomial_next(b2);
! 400: binomial_free(b2);
! 401: }
! 402: else b1=binomial_next(b1);
! 403: }
! 404:
! 405: /* now reduce trailing terms */
! 406: b1=gset_first(g);
! 407: while(b1!=0){
! 408: changed=1;
! 409: while(changed==1){
! 410: changed=0;
! 411: b2=gset_first(g);
! 412: while(b2!=0){
! 413: if (b2!=b1 &&
! 414: monomial_divides(binomial_lead(b2),binomial_trail(b1))==TRUE){
! 415: reducetrail(b1,b2);
! 416: changed=1;
! 417: }
! 418: b2=binomial_next(b2);
! 419: }
! 420: }
! 421: b1=binomial_next(b1);
! 422: }
! 423:
! 424: /* now reinsert terms to ensure list is in order */
! 425: b1=gset_first(g);
! 426: gset_first(g)=0;
! 427: while((b2=b1)!=0) {
! 428: b1=binomial_next(b1);
! 429: gset_insert(g,b2);
! 430: }
! 431:
! 432: }
! 433:
! 434: /*
! 435: ** void gset_rgb(gset g, int (*comp)(monomial,monomial))
! 436: ** Use buchberger's algorithm to transform g into groebner basis
! 437: ** wrt the term order implemented by comp
! 438: */
! 439: #define ordered(b) ((comp(binomial_lead(b),binomial_trail(b))>=0)?TRUE:FALSE)
! 440: int changed;
! 441: void gset_rgb(gset g, int (*comp)(monomial,monomial)){
! 442: void process_pair(binomial,binomial,binomial,binomial,binomial *,int (*comp)());
! 443: binomial ptr,b,DL=0,SL=0,NL=0;
! 444: int passes=0;
! 445:
! 446: do{
! 447: DL=0; SL=0; NL=0;
! 448: changed=FALSE;
! 449:
! 450: /* reorient g and put binomial list on DL*/
! 451: ptr=gset_first(g);
! 452: while((b=ptr)!=0){
! 453: ptr=binomial_next(ptr);
! 454: if (ordered(b)==FALSE) binomial_flip(b);
! 455: binomial_next(b)=DL;
! 456: DL=b;
! 457: }
! 458:
! 459: /* */
! 460: while(DL!=0){
! 461: NL=0;
! 462: b=DL; DL=DL->next; /* pop DL*/
! 463: b->next=SL; SL=b; /* push ptr onto SL*/
! 464: for(ptr=SL;ptr!=0;ptr=binomial_next(ptr)) process_pair(b,ptr,DL,SL,&NL,comp);
! 465: for(ptr=DL;ptr!=0;ptr=binomial_next(ptr)){
! 466: process_pair(b,ptr,DL,SL,&NL,comp);
! 467: if (binomial_next(ptr)==0){ binomial_next(ptr)=NL; NL=0;}
! 468: }
! 469: }
! 470:
! 471: /* reinsert elements in SL into gset */
! 472: ptr=SL;
! 473: gset_first(g)=0;
! 474: while(ptr!=0){
! 475: ptr=(b=ptr)->next;
! 476: gset_insert(g,b);
! 477: }
! 478:
! 479:
! 480: gset_autoreduce(g);
! 481:
! 482: if (passes>1){
! 483: if (changed==TRUE ){fprintf(stderr,"looping pass (%d)\n",passes);}
! 484: else {fprintf(stderr,"stopping after %d passes\n",passes);}
! 485: }
! 486: passes++;
! 487: }while(changed==TRUE);
! 488:
! 489: }
! 490:
! 491: /*
! 492: -- process_pair(b1,b2,DL,SL,NL,comp):
! 493: -- process spair defined by binomials b1 and b2.
! 494: -- taking spair wrt union of DL SL and *NL lists
! 495: -- if non-zero add result to NL list.
! 496: -- comp is a monomial compairison function used throuout.
! 497: */
! 498: void process_pair(binomial b1,binomial b2,binomial DL,binomial SL,binomial *NL,
! 499: int (*comp)(monomial,monomial)){
! 500: binomial S,ptr,find_divisor(binomial,binomial);
! 501: int i,tmp;
! 502:
! 503: /* test is lead terms are rel prime [buchberger's first criterion]*/
! 504: if (monomial_rel_prime(binomial_lead(b1),binomial_lead(b2))==TRUE)return;
! 505:
! 506: /* buchberger's second criterion ?*/
! 507:
! 508:
! 509: S=binomial_new();
! 510: binomial_copy(b1,S);
! 511: if (binomial_spair(S,b2)==TRUE){
! 512: binomial_free(S);
! 513: return;
! 514: }
! 515: if (ordered(S)==FALSE) binomial_flip(S);
! 516: while(((ptr=find_divisor(S,DL))!=0)||
! 517: ((ptr=find_divisor(S,SL))!=0)||
! 518: ((ptr=find_divisor(S,*NL))!=0)){
! 519: if (binomial_spair(S,ptr)==TRUE){
! 520: binomial_free(S);
! 521: return;
! 522: }
! 523: if (ordered(S)==FALSE) binomial_flip(S);
! 524: }
! 525: changed=TRUE;
! 526: binomial_next(S)=*NL;
! 527: *NL=S;
! 528: }
! 529:
! 530: /*
! 531: ** void gset_setfacets(gset g):
! 532: ** Use repeated calls to gset_isfacet to ensure that all facet flags
! 533: ** are set.
! 534: ** Also sets nfacets, nelts and deg counters (these contain garbage except
! 535: ** right after a call to set facets).
! 536: **
! 537: ** NOTE 4/20 the deg counter was just added and the code to load it is
! 538: ** cludged in here -- logically it should be part of the
! 539: ** binomial.c file -- for now it is here.
! 540: */
! 541: #define max(a,b) (((a)>(b))?(a):(b))
! 542: void gset_setfacets(gset g){
! 543: binomial b;
! 544: monomial ml,mt;
! 545: int i,d=0,dl,dt;
! 546: gset_nfacets(g)=0;
! 547: gset_nelts(g)=0;
! 548: for(b=gset_first(g);b!=0;b=binomial_next(b)){
! 549: if (gset_isfacet(g,b)==FACET) gset_nfacets(g)++;
! 550: gset_nelts(g)++;
! 551: ml=binomial_lead(b); dl=0;
! 552: mt=binomial_trail(b); dt=0;
! 553: for(i=0;i<ring_N;i++){ dl+=ml[i]; dt+=mt[i];}
! 554: d=max(d,max(dl,dt));
! 555: }
! 556: gset_deg(g)=d;
! 557: }
! 558:
! 559: /*
! 560: ** int gset_isfacet(gset g,binomial b):
! 561: ** check whether b is known to be a facet or not. if not call lp_isfacet()
! 562: ** to use a linear program to set b's facet flag.
! 563: **
! 564: */
! 565: int lptest=1; /* 1 test only LP, 2 test only flipability, 3 test both */
! 566: int gset_isflippable(gset g,binomial b);
! 567: int gset_isfacet(gset g,binomial b){
! 568: int rval=UNKNOWN;
! 569: rval=b->ff;
! 570: if (rval!=FACET && rval!=NONFACET){
! 571: switch(lptest){
! 572: case 1: rval=(b->ff=lp_isfacet(g,b));
! 573: break;
! 574: case 2: if (gset_isflippable(g,b)==FALSE) rval=(b->ff=NONFACET);
! 575: else rval=(b->ff=FACET);
! 576: break;
! 577: case 3: if (gset_isflippable(g,b)==FALSE) rval=(b->ff=NONFACET);
! 578: else rval=(b->ff=lp_isfacet(g,b));
! 579: break;
! 580: default: fprintf(stderr,"Warning lptest has invalid value in gset_isflippable()\n");
! 581: exit(4);
! 582: }
! 583: }
! 584: return rval;
! 585: }
! 586:
! 587: /*
! 588: **
! 589: */
! 590: int gset_isflippable(gset g,binomial b){
! 591: int ctg=0,ctn=1,val=TRUE;
! 592: binomial new=0,tmp,ptrg,ptrn,btmp;
! 593: /* copy all binomials of g's list ecept b to old and new lists*/
! 594: for(ptrg=gset_first(g);ptrg!=0;ptrg=ptrg->next){
! 595: ctg++;
! 596: if (ptrg!=b){
! 597: tmp=binomial_new();
! 598: binomial_copy(ptrg,tmp);
! 599: monomial_set(tmp);
! 600: binomial_next(tmp)=new;
! 601: new=tmp;
! 602: }
! 603: }
! 604: btmp=binomial_new();
! 605: binomial_copy(b,btmp);
! 606:
! 607:
! 608: /* calculate the reduced GB of the binomial b and the monomials in M */
! 609: bmrgb(btmp,&new);
! 610:
! 611: /* test if new and old have same leading terms */
! 612: for(ptrn=new ;ptrn!=0;ptrn=ptrn->next) ctn++;
! 613: if (ptrn!=ptrg) val=FALSE; /* initial ideals have diferent numbers of generators */
! 614: else {
! 615: for(ptrn=new;ptrn!=0;ptrn=ptrn->next){
! 616: for(ptrg=gset_first(g);ptrg!=0;ptrg=ptrg->next){
! 617: if (monomial_equal(binomial_lead(ptrn),binomial_lead(ptrg))==TRUE)break;
! 618: }
! 619: if (ptrg==0)break; /* no match found */
! 620: }
! 621: if (ptrn!=0)val=FALSE; /* not all terms had matches found */
! 622: }
! 623:
! 624: /* clean up */
! 625: binomial_free(btmp);
! 626: while(new!=0){
! 627: ptrn=new;
! 628: new=new->next;
! 629: binomial_free(ptrn);
! 630: }
! 631:
! 632: return val;
! 633: }
! 634:
! 635: /*
! 636: ** int lp_isfacet(gset g,binomial b):
! 637: ** set up and run linear program to set b's facet flag.
! 638: **
! 639: */
! 640: int lp_isfacet(gset g,binomial b){
! 641: binomial ptr;
! 642: int D=ring_N,M=0;
! 643: int idx=0,i;
! 644: double dtmp0,dtmp;
! 645:
! 646: /* need cheeper way to determine the size of g */
! 647: for(ptr=gset_first(g);ptr!=0;ptr=binomial_next(ptr)){
! 648: if (ptr->ff!=NONFACET)M++;
! 649: }
! 650:
! 651: /* make sure the lp structures have enough space for the program*/
! 652: LP_get_space(M,D+2*M);
! 653:
! 654: /* Set up linear program. */
! 655: ptr=gset_first(g);
! 656: idx=0;
! 657: while(ptr!=0){
! 658: if (ptr->ff!=NONFACET){
! 659: for(i=0;i<D;i++){ /* make sure supports of trail and lead disjoint? */
! 660: LP_A(idx,i)=binomial_lead(ptr)[i]-binomial_trail(ptr)[i];
! 661: }
! 662: for(i=0;i<M;i++){
! 663: LP_A(idx,D+i)=0;
! 664: LP_A(idx,D+M+i)=0;
! 665: }
! 666: if (ptr==b) {for(i=0;i<D;i++) LP_A(idx,i)*=-1;}
! 667: LP_A(idx,D+M+idx)=1;
! 668: LP_A(idx,D+idx)=-1;
! 669: LP_B[idx]=1;
! 670: idx++;
! 671: }
! 672: ptr=ptr->next;
! 673: }
! 674: for(i=0;i<D+M;i++){
! 675: LP_C[i]=0;
! 676: LP_X[i]=0;
! 677: LP_NonBasis[i]=i;
! 678: }
! 679: for(i=0;i<M;i++){
! 680: LP_Basis[i]=D+M+i;
! 681: LP_X[D+M+i]=1;
! 682: LP_C[D+M+i]=1;
! 683: }
! 684:
! 685: /* Run simplex algorithm */
! 686: Rsimp(LP_M,LP_N,LP_A,LP_B,LP_C,LP_X,LP_Basis,LP_NonBasis,
! 687: LP_R,LP_Q,LP_t1,LP_t2);
! 688:
! 689: /* use results to determine if the b is a facet*/
! 690: b->ff=FACET;
! 691: for(i=0;i<M;i++) if (LP_Basis[i]>=M+D) {b->ff=NONFACET;break;}
! 692:
! 693: return b->ff;
! 694: }
! 695:
! 696:
! 697:
! 698:
! 699:
! 700:
! 701:
! 702:
! 703:
! 704:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>