////////////////////////////////////////////////// // resizable buf ////////////////////////////////////////////////// void sBuf_init(sBuf* self) { self->mBuf = (char*)MMALLOC(sizeof(char)*64); self->mSize = 64; self->mLen = 0; *(self->mBuf) = '\0'; }
static char *mqreply_mmalloc(char *sbuffer, int bsz, int pid, char *req_sz) { size_t msz; size_t *ptr; if (req_sz) { msz = atol(req_sz); ptr = MMALLOC(msz); } else { ptr = (void *)NULL; } snprintf(sbuffer, bsz, "0x%lx", (long)ptr); printf("0x%lx = mmalloc(%lu)\n", (long)ptr, msz); mqrc_reply(sbuffer, pid); return(NULL); }
void frame_setname_ext(framestruc *fr, char *nm1, char *nm2, char *ext) { char *buf; if (nm1 || nm2) { buf = MMALLOC(((nm1?strlen(nm1):0)+(nm2?strlen(nm2):0)+3)*sizeof(buf[0])); if (nm1) strcpy(buf,nm1); else buf[0] = 0; if (nm2) strcat(buf,nm2); if (FRNAME(fr)) FREE(FRNAME(fr)); FRNAME(fr) = buf; } if (ext) { if (FREXTENS(fr)) FREE(FREXTENS(fr)); FREXTENS(fr) = MSTRDUP(ext); } }
optionstruc* new_comoption_ext(char *nm, int oc, int cont) { optionstruc *op; int i; if (!nm) {PROGERROR("The option name must be given!");} if (oc<0 || oc>1) {PROGERROR("Invalid option/command flag %d!",oc);} op = MMALLOC(sizeof(op[0])); /* creates the option with its name */ OPTNAME(op) = (nm?MSTRDUP(nm):NULL); OPTCOM(op) = oc; OPTCONTINUED(op) = (cont>0? cont:0); /* a "continued" option flag - for continuing a long list of option values */ OPTINDEX(op) = -1; OPTPARSG(op) = 0; pfield_setzeroexp(&OPTPAREX(op)); for (i=0; i<MAXOPTPARAMS; i++) { /* nulls the option parameters (values) */ OPTPARAM(op,i) = NULL; OPTNPARAM(op,i) = OPTNOPARAM; } OPTPARNUM(op) = 0; fr_aloptions++; return op; }
int ematrix_printmore_flats(ematrix *rf, int rk, int wh) { static long *save=NULL, sl=0,si; ematrix *rrf; long l; int i,j,k, r = 1; if (wh!=1) if (!save || !sl) {PROGERROR("must be initialized first!"); return 0;} if (wh==1) { sl = 1000; save = MMALLOC(sl*sizeof(save[0])); } else if (wh==-1) { FREE(save); save = NULL; si = sl = 0; } else { if (si>=sl-4) save = MREALLOC(save,(sl*=2)*sizeof(save[0])); rrf = REFMAT(rf); /** * The previously allowed flats are stored as set bitmaps to the list * save, and the new flat given by rf is compared against all saved * ones bit by bit. * If it equals, or it is just by the rank difference bigger, to saved * one, the new flat is rejected (and not stored). **/ for (i=0,l=0; i<ROWSM(rf)+COLSM(rf); i++) l |= 1l<<(i<ROWSM(rf)? GETREFMROW(rf,i): GETREFMCOL(rf,i-ROWSM(rf))+ROWSM(rrf)); for (i=0; i<si/2 && r>=0; i++) { for (j=k=0; j<ROWSM(rrf)+COLSM(rrf); j++) k += ((l&(1l<<j))!=(save[2*i]&(1l<<j))); if ((k==1 && rk==save[2*i+1]) || (k==0 && rk!=save[2*i+1])) {PROGERROR("something wrong with the saved flats... (k=%d, %d~%ld)",k,rk,save[2*i+1]);} if (k<=rk-save[2*i+1]) r = -1; } if (r>=0) { save[si] = l; save[si+1] = rk; si += 2; } } return r; }
framestruc* new_frame(framestruc *parent) { framestruc *fr; fr = MMALLOC(sizeof(fr[0])); FRMAGICSET(fr); /* (a magic number is used to test correct access to frames) */ FRNAME(fr) = FREXTENS(fr) = FRCOMMENT(fr) = NULL; FRSONS(fr) = NULL; FRNUMSONS(fr) = 0; FRPARENT(fr) = NULL; frame_setson(fr,parent); /* adds to the parent's list of sons */ FRMATRIX(fr) = NULL; /* clears all important values in this frame */ FRPFINDEX(fr) = FRPFINDEX_SAVE(fr) = -1; FRMATRIXROWS(fr) = FRMATRIXCOLS(fr) = 0; FRVALUESIG(fr) = 0; pfield_setzeroexp(&FRVALUEEXP(fr)); FRNUMBER(fr) = 0; FROPTIONS(fr) = NULL; FRCOMMANDS(fr) = NULL; FRLASTOPTI(fr) = -1; /* the "index" of the last added option */ FRDELMARK(fr) = FRTREEMARK(fr) = 0; fr_alframes++; return fr; }
int grepr_generate_ext(int ch, ematrix *eg, int xpfd, ematrix ***lout) { ematrix *ee,*re,**rel=NULL, **elo=NULL,**x, ***epl=NULL; int i,k,p,br, ro,co, step, xp=-1, ret=0; char *s, buf[100]; if (!eg) {PROGERROR("the matrix eg must be given!"); return -1;} ro = ROWSM(eg); co = COLSM(eg); if (ro<=0 || co<=0) {PROGERROR("the matrix eg has wrong size!"); return -1;} if (lout?*lout:0) {PROGERROR("the list lout must be given empty (null)"); return -1;} xp = pfield_curindex(); s = pfield_curname(); if (xpfd>=0) pfield_switchto_fast(xpfd); DEBUG(CURDLEV-1,"Generating representation(s) of a %s matrix %p[%.12s] (%dx%d) over %s...\n", pfield_curname(),eg,EMNAME(eg)?EMNAME(eg):"",ro,co,s); EMATDEBUG(CURDLEV+0,eg,"\t:\t"); if (xpfd>=0 && xp>=0) pfield_switchto_fast(xp); /** * We allocate working data, and we prepare the submatrices rel[] * of the matrix eg which display how the generated representation * grows line by line (total step=ro steps). * We should find a more clever order of added lines for faster * computation... **/ step = (ro>co? ro: co); rel = MMALLOC((step+2)*sizeof(rel[0])); if (step==ro) re = ematrix_refer(eg,-1,-1,0,co); else re = ematrix_refer(eg,0,ro,-1,-1); for (i=0; i<step; i++) { if (step==ro) ematrix_refadd_row(re,i); else ematrix_refadd_col(re,i); rel[i] = ematrix_copy(re); } dispose_ematrix(re); epl = MMALLOC((step+2)*sizeof(epl[0])); for (i=0; i<step+1; i++) epl[i] = NULL; /** * Here is the main backtracking code of this function. * At each level k (0..step-1), we keep in epl[k] the list of * partial matrices generated at this level (matching rel[k]); * and we collect the full representations found in elo. * At each step, we call grepr_addline() to add one more line * (row) to the previous partial matrices. **/ k = br = 0; while (k>=0) { if (k>=step) {PROGERROR("cannot get here!");} if (alist_getlength(epl[k])>0) {PROGERROR("cannot get nonempty list here!");} DEBUG(CURDLEV+2,"%*s calling GREPR at k=%d, left %d\n",2*k,"",k,(k>0?alist_getlength_part(epl[k-1]):-1)); if (k>0) { ee = *epl[k-1]; if (!ee || br) { dispose_alist_mats(epl[k-1]); epl[k-1] = NULL; if (--k<=0) break; else continue; } else epl[k-1]++; } else ee = NULL; p = grepr_addline(ee,rel[k],-1,xpfd,epl+k); if (p<=0) continue; /** * When some partial representations are generated in grepr_addline(), * we store them for use in the next step; or in the result list elo. * We are finished with the first representation(s) if ch<=1. **/ if (k<step-1) { ++k; continue; } ret += p; if (ch<=1) br = 1; DEBUG(CURDLEV,"Found %d (%d tot) representations of %p[%.12s] (%dx%d) over %s here.\n", alist_getlength(epl[k]),ret,eg,EMNAME(eg)?EMNAME(eg):"",ro,co,pfield_curname()); EMATDEBUGS(CURDLEV+2,*epl[k],"\t\t.=.\t"); elo = alist_applist(elo,epl[k]); epl[k]= NULL; } #ifndef FASTPROG if (xp!=pfield_curindex()) {PROGERROR("The current pfield has changed!");} if (ret>0 && alist_getlength(elo)<=0) {PROGERROR("Where is the generated representation?!");} DEBUG(CURDLEV-1-(ret>0),"Generated total %d representations of a matrix %p[%.12s] (%dx%d) over %s...\n", ret,eg,EMNAME(eg)?EMNAME(eg):"",ro,co,pfield_curname()); if (IFRANDDEBUGLESS(222) && ch>=0) { if (xpfd>=0) pfield_switchto_fast(xpfd); ee = ematrix_copydual(eg); for (i=0; i<4 && i<ro && i<co; i++) if (SIGNM(ee,i,i)!=0) ematrix_pivot(ee,i,i); if (xpfd>=0 && xp>=0) pfield_switchto_fast(xp); p = grepr_generate_ext(-1,ee,xpfd,NULL); if ((p>0)!=(ret>0)) {PROGERROR("Wrong result of a recursive call! %d!=%d",p,ret);} } #endif if (ch==1 || ch>=3) OUTPUT("There %s %s-representation of the matroid [%.18s] (%dx%d).\n", (ret>0?"+IS+ a":"is -NO-"),pfield_curname(),EMNAME(eg)?EMNAME(eg):"",ro,co); if (ret>0 && ch>=3) OUTPUT(" Generated total %d representations of the matroid [%.18s] (%dx%d) over %s.\n", ret,EMNAME(eg)?EMNAME(eg):"",ro,co,pfield_curname()); if (ret>0 && ch>=4) for (x=elo; x?*x:0; x++) { snprintf(buf,80,"%sr%d\t",printoutpref,(int)(x-elo)+1); EMATOUTPUTS(*x,buf); } if (rel) FREE(rel); if (epl) FREE(epl); if (lout) *lout = (*lout? alist_applist(*lout,elo): elo); else if (elo) dispose_alist_mats(elo); return ret; }
int read_fasta_fastq(struct read_info** ri,struct parameters* param,FILE *file) { int park_pos = -1; char line[MAX_LINE]; int i;//,j; int seq_p = 0; int set = 0; int len = 0; int size = 0; ri = clear_read_info(ri, param->num_query); while(fgets(line, MAX_LINE, file)){ if((line[0] == '@' && !set)|| (line[0] == '>' && !set)){ //set sequence length of previous read //check if there is still space.... //if(param->num_query == size){ // fseek (file , - strlen(line) , SEEK_CUR); // return size; //} park_pos++; len = 0; seq_p = 1; for(i = 1;i < MAX_LINE;i++){ len++; if(iscntrl((int)line[i])){ break; } } //ri[park_pos]->hits[0] = 0; //ri[park_pos]->strand[0] = 0; MMALLOC(ri[park_pos]->name,sizeof(unsigned char)* (len+1)); for(i = 1;i < MAX_LINE;i++){ if(iscntrl((int)line[i])){ ri[park_pos]->name[i-1] = 0; break; } if(isspace((int)line[i])){ ri[park_pos]->name[i-1] = ';'; } ri[park_pos]->name[i-1] = line[i]; } //fprintf(stderr,"LEN:%d %s\n",len,ri[park_pos]->name); set = 1; size++; //get ready to read quality if present }else if(line[0] == '+' && !set){ seq_p = 0; set = 1; //reading sequence or quality }else{ if(set){ if(seq_p){ len = 0; for(i = 0;i < MAX_LINE;i++){ len++; if(iscntrl((int)line[i])){ break; } } //fprintf(stderr,"SEQ LEN:%d %s\n",len,line); MMALLOC(ri[park_pos]->seq,sizeof(unsigned char)* (len+1)); MMALLOC(ri[park_pos]->labels, sizeof(unsigned char)* (len+1)); for(i = 0;i < MAX_LINE;i++){ if(iscntrl((int)line[i])){ ri[park_pos]->seq[i] = 0; ri[park_pos]->labels[i] = 0; break; } ri[park_pos]->seq[i] = nuc_code[(int)line[i]]; ri[park_pos]->labels[i] = 0; } ri[park_pos]->len = len-1; }else{ len = 0; for(i = 0;i < MAX_LINE;i++){ len++; if(iscntrl((int)line[i])){ break; } } if(len-1 != ri[park_pos]->len ){ sprintf(param->buffer,"ERROR: Length of sequence and base qualities differ!.\n"); param->messages = append_message(param->messages, param->buffer); free_param(param); exit(EXIT_FAILURE); } //fprintf(stderr,"QUAL LEN:%d\n",len); MMALLOC(ri[park_pos]->qual,sizeof(unsigned char)* (len+1)); for(i = 0;i < MAX_LINE;i++){ if(iscntrl((int)line[i])){ ri[park_pos]->qual[i] = 0; break; } ri[park_pos]->qual[i] = line[i]; } } } set = 0; } if(param->num_query == size ){//here I know I am in the last entry AND filled the quality... if(!param->fasta && ri[park_pos]->qual){ return size; } if(param->fasta && ri[park_pos]->seq){ return size; } } } return size; }
int read_sam_chunk(struct read_info** ri,struct parameters* param,FILE* file) { //char line[MAX_LINE]; int column = 0; int i,j,g,tmp; int c = 0; ri = clear_read_info(ri, param->num_query); char *line = NULL; size_t len = 0; ssize_t read; while ((read = getline(&line, &len, file)) != -1) { //while(fgets(line, MAX_LINE, file)){ if(line[0] != '@'){ column = 1; //<QNAME> tmp = 0; for(j = 0;j < read;j++){ tmp++; if(isspace((int)line[j])){ break; } } MMALLOC(ri[c]->name,sizeof(unsigned char)* tmp); for(j = 0;j < read;j++){ if(isspace((int)line[j])){ ri[c]->name[j] = 0; break; } ri[c]->name[j] = line[j]; } for(i = 0; i < read;i++){ if(line[i] == '\n'){ break; } if(isspace((int)line[i])){ column++; switch(column){ case 2: // <FLAG> tmp = atoi(line+i+1); ri[i]->strand = (tmp & 0x10); //WARNING - read should be reverse complemented if mapped to negative strand before tagdusting... /*tmp = atoi(line+i+1); ri[c]->strand[hit] = (tmp & 0x10); if(tmp == 4){ ri[c]->hits[hit] = 0; }else{ ri[c]->hits[hit] = 1; } hit++;*/ break; case 3: // <RNAME> break; case 4: // <POS> break; case 5: // <MAPQ> ri[c]->mapq = atof(line +i +1); break; case 6: // <CIGAR> tmp = 0; for(j = i+1;j < read;j++){ tmp++; if(isspace((int)line[j])){ break; } } ri[c]->cigar = malloc(sizeof(unsigned char)* tmp); g = 0; for(j = i+1;j < read;j++){ if(isspace((int)line[j])){ ri[c]->cigar[g] = 0; break; } ri[c]->cigar[g] = line[j]; g++; } break; case 7: // <MRNM> break; case 8: // <MPOS> break; case 9: // <ISIZE> break; case 10: // <SEQ> tmp = 0; for(j = i+1;j < read;j++){ tmp++; if(isspace((int)line[j])){ break; } } MMALLOC(ri[c]->seq,sizeof(unsigned char)* tmp); MMALLOC(ri[c]->labels,sizeof(unsigned char)* tmp); g = 0; for(j = i+1;j < read;j++){ if(isspace((int)line[j])){ ri[c]->seq[g] = 0; ri[c]->labels[g] = 0; break; } ri[c]->seq[g] = nuc_code[(int)line[j]]; ri[c]->labels[g] = 0; g++; } ri[c]->len = g; break; case 11: // <QUAL> tmp = 0; for(j = i+1;j < read;j++){ tmp++; if(isspace((int)line[j])){ break; } } g= 0; MMALLOC(ri[c]->qual,sizeof(unsigned char)* tmp); for(j = i+1;j < read;j++){ if(isspace((int)line[j])){ ri[c]->qual[g] = 0; break; } ri[c]->qual[g] = line[j]; g++; } break; default: i = (int) read; break; } } } tmp = byg_end("NM:i:", line ); if(tmp){ ri[c]->errors = atoi(line+tmp); //if(ri[c]->errors > 20){ ///fprintf(stderr,"%s\n,%c,%c,%c,%d\n",line, *(line +tmp), *(line +tmp+1),*(line +tmp+2), ri[c]->errors); //} }else{ ri[c]->errors = -1; } tmp = byg_end("MD:Z:", line ); if(tmp){ g = 0; for(j = tmp ;j < read;j++){ g++; if(isspace((int)line[j])){ break; } } ri[c]->md = malloc(sizeof(unsigned char)* g); g = 0; for(j = tmp ;j < read;j++){ if(isspace((int)line[j])){ ri[c]->md[g] = 0; break; } ri[c]->md[g] = line[j]; g++; } } //ri[c]->hits[hit] = 0xFFFFFFFFu; c++; if(c == param->num_query){ MFREE(line); return c; } } } MFREE(line); return c; }
void ematrix_printbasecirc_ext(ematrix *e, int whp, int lev, int *cix, char *bto, int mx) { ematrix **bas, **be, *ee; int i=0,j,jj,k,n, ro,co, blen,clen; long l, *crc=NULL; if (bto) {PROGERROR("Not implemented yet!"); return;} if (!e) return; if (lev>0 && !bto) SOUTPUT("\n"); if (whp>1) if (ROWSM(e)>EM_MAXTOPRINT || COLSM(e)>EM_MAXTOPRINT) { OUTPUT("Too big matroid for extended printing, sorry.\n"); return; } ee = ematrix_copy(e); ro = ROWSM(ee); co = COLSM(ee); if (ematrix_checkid(ee)<0 || ematrix_checkid(ee)>EM_MAXTOPRINT) { ematrix_resetid(ee); SOUTPUT("\t\tResetting line id's in the matrix!!!\n"); } bas = ematrix_getbases(ee); blen = alist_getlength(bas); if (!bto) OUTPUT("Number of matroid [%.25s] bases: %d\n",EMNAME(e)?EMNAME(e):"",blen); if (cix && !bto) for (i=0; i<ro+co && cix[i]!=0; i++) { if (i==0) OUTPUT("Listing all matroid [%.25s] %s containing elements (id): ",EMNAME(e)?EMNAME(e):"",whp<=10?"bases":"circuits"); //if (cix[i]<-2*EM_MAXTOPRINT || cix[i]>2*EM_MAXTOPRINT) cix[i] = 0; SOUTPUT(" %d,",cix[i]); } if (cix && !bto && i>0) SOUTPUT("\n"); /** * This part is used to print all bases (by their line ids). * We test that the (possible) required elements from cix[] are there. **/ if (whp<=10) for (be=bas,k=0; be?*be:0; be++) { if (cix) for (i=0; cix[i]; i++) { for (j=0; j<ro; j++) if (ROWSID(*be,j)==cix[i]) break; if (j>=ro) break; } if (cix?cix[i]:0) continue; SOUTPUT(" ~\t - base (%d)\t{",++k); for (j=0; j<ro; j++) SOUTPUT(" %d%s",ROWSID(*be,j),(j<ro-1?",":"")); SOUTPUT(" }\n"); } /** * This part is used to print all circuits (by their line ids). * We test that the (possible) required elements from cix[] are there. * Then we test that the same circuit (as a set) has not been printed * out before - we store all printed circuits as bitmaps in crc[]. **/ if (whp>=10) { if (!cix) OUTPUT("Listing all matroid [%.25s] circuits:\n",EMNAME(e)?EMNAME(e):""); crc = MMALLOC(blen*co*sizeof(crc[0])); clen = 0; for (be=bas,k=0; be?*be:0; be++) for (jj=0; jj<co; jj++) { if (cix) for (i=0; cix[i]; i++) { for (j=0; j<ro; j++) if (SIGNM(*be,j,jj) && ROWSID(*be,j)==cix[i]) break; if (j>=ro && COLSID(*be,jj)!=cix[i]) break; } if (cix?cix[i]:0) continue; /* preventing duplicated circuits (stored as bitmaps here) */ l = 1l<<(COLSID(*be,jj)+EM_MAXTOPRINT); for (i=0; i<ro; i++) if (SIGNM(*be,i,jj)) l |= 1l<<(ROWSID(*be,i)+EM_MAXTOPRINT); for (j=0; j<clen; j++) if (l==crc[j]) break; if (j<clen) continue; crc[clen++] = l; n = 0; /* printing... */ SOUTPUT(" ~\t - circuit (%d)\t{",++k); for (i=0; i<ro; i++) if (SIGNM(*be,i,jj)) { n++; SOUTPUT(" %d,",ROWSID(*be,i)); } SOUTPUT(" %d } \tlen %d,\n",COLSID(*be,jj),n+1); }} if (lev>1 && !bto) SOUTPUT("\n"); if (crc) FREE(crc); if (bas) dispose_alist_mats(bas); dispose_ematrix(ee); }
long ematrix_printmore_ext(ematrix *e, int lev, char *bto, int mx) { ematrix **bas,**flt,**sep, **x, *ee,*xe; int i,ii, j,jj,k,kk, a,ro,co, *li,*basi,**basii, *orb=NULL,*orbx, *ses=NULL, bbm,bbl; long hash = 0, *flts=NULL; if (bto) bto[0] = 0; bbm = mx; bbl=0; if (!e) return -1; if (lev>0) if (ROWSM(e)*COLSM(e)>EM_MAXTOPRINTSQ || ROWSM(e)>EM_MAXTOPRINT || COLSM(e)>EM_MAXTOPRINT) { OUTPUT("Too big matroid for extended printing, sorry.\n"); return -1; } ee = ematrix_copy(e); ro = ROWSM(ee); co = COLSM(ee); basi = MMALLOC(2*(ro+co+2)*sizeof(basi[0])); li = basi+ro+co; basii = malloc_twodim(sizeof(basii[0][0]),ro+co,ro+co); for (i=0; i<ro+co; i++) basi[i] = 0; for (i=0; i<ro+co; i++) for (ii=0; ii<ro+co; ii++) basii[i][ii] = 0; flts = MMALLOC((ro+co+2)*sizeof(flts[0])); if (lev>0 && !bto) SOUTPUT("\n"); hash = ro+10*co; hash = 90909l*hash+111l*hash*hash*hash; /** * Here we collect and print all bases - their total number, and numbers * per elements (basi[]) and per element pairs (basii[][]). * The bases are given as refering square submatrices of ee (not pivoted!). * We add the numbers to the matroid hash value in a symmetric way. * ....... more to be added to the hash value - small flatlines??? * * The bases are also used later, and they are freed at the end. **/ bas = ematrix_getbases_sq(ee); hash += alist_getlength(bas)*10101l; for (x=bas; x?*x:0; x++) { xe = ematrix_refextract_xrow(ee,*x); if (ROWSM(xe)+COLSM(xe)!=ro) {PROGERROR("Something wrong with the basis size!");} for (i=0; i<ROWSM(xe); i++) li[i] = GETREFMROW(xe,i); for (i=0; i<COLSM(xe); i++) li[i+ROWSM(xe)] = GETREFMCOL(xe,i)+ro; for (i=0; i<ro; i++) { basi[li[i]]++; for (ii=0; ii<ro; ii++) basii[li[i]][li[ii]]++; } dispose_ematrix(xe); } for (i=0; i<ro+co; i++) { hash += 505l*basi[i]+7l*basi[i]*basi[i]; for (ii=0; ii<i; ii++) hash += 13l*basii[i][ii]+1l*basii[i][ii]*basii[i][ii]; if (basii[i][ii]!=basii[ii][i]) {PROGERROR("Something wrong - nonsymmetric basis pairs!");} } //************* adding small flatlines to the hash value? - here, not below, since the element // magic below is slow to compute and not computed always(!) if (lev>=0) { if (!bto) OUTPUT("Number of matroid [%.25s] bases: %d\n",EMNAME(e)?EMNAME(e):"",alist_getlength(bas)); else SNPRINTF(bto,bbl,bbm,"Matroid %d x %d [%.25s], %d bases.\n",ro,co,EMNAME(e)?EMNAME(e):"",alist_getlength(bas)); } if (lev>0 && !bto) { OUTPUT(" - per elements "); for (i=0; i<ro+co; i++) SOUTPUT(" [%d: %d]%s",LIID(ee,i),basi[i],i%6==5?"\n\t\t\t":""); SOUTPUT("\n"); } if (lev>4 && !bto) { SOUTPUT("\n"); OUTPUT(" - per element pairs\n"); for (i=0,a=1; i<ro+co; i++) { if (a) SOUTPUT(" ~\t "); a = 0; for (ii=0; ii<ro+co; ii++) if (basii[i][ii]>0) { a = 1; SOUTPUT("[%2d'%2d: %-3d]",LIID(ee,i),LIID(ee,ii),basii[i][ii]); } if (a) SOUTPUT("\n"); } } /** * Here we (try to) distinguish matroid elements up to isomorphism. * We either compute "magic values" for the elements - faster, * or we rigorously compute the orbits of the automorphism group. * For the orbits, we use the numbers of bases in basi[] and the * flatline values flts[] for rough distinction, and then we use * strmag_isautmap() to see which pairs of elements are really * mapped to each other by the aut group. **/ if (lev>0) { strmag_flatlines_pr(ee,flts); /* (flts[] is globally allocated) */ for (i=0; i<ro+co; i++) flts[i] += 7*basi[i]; } if (lev>0 && lev<=2 && !bto) { OUTPUT(" - elem magic "); for (i=0; i<ro+co; i++) SOUTPUT(" [%d: %ld]%s",LIID(ee,i),flts[i],i%6==5?"\n\t\t\t":""); SOUTPUT("\n"); } if (lev>2 && ro>0) { if (ro+co>6) DEBUG(CURDLEV-3,"Warning - aut orbit computation may take very long.\n"); if (!bto) OUTPUT("Aut group orbits of [%.25s] are (via first elem id):\n",EMNAME(e)?EMNAME(e):""); else SNPRINTF(bto,bbl,bbm,"Aut group orbits "); if (ematrix_checkid(ee)<0 && !bto) { ematrix_resetid(ee); SOUTPUT("\t\tResetting line id's in the matrix!!!\n"); } orb = MMALLOC(2*(ro+co+2)*sizeof(orb[0])); orbx = orb+(ro+co+1); for (i=0; i<ro+co; i++) orbx[i] = 1; if (!bto) { for (i=0; i<ro; i++) orb[i] = ROWSID(ee,i); for (i=ro; i<ro+co; i++) orb[i] = COLSID(ee,i-ro); } else for (i=0; i<ro+co; i++) orb[i] = i; /* (we print elem ids on output, but their indices to bto...) */ if (!bto) SOUTPUT("\t\t(%d",orb[0]); else SNPRINTF(bto,bbl,bbm,"[%d",orb[0]); kk = ro+co; for (i=1; i<ro+co; i++) { for (j=0; j<i; j++) if (orbx[j]) { if (basi[i]!=basi[j] || flts[i]!=flts[j]) continue; //********** may we efficiently use basii[][] here??? if (!strmag_isautmap_h(e,i,j,flts)) continue; orb[i] = orb[j]; orbx[i] = 0; kk--; } if (!bto) SOUTPUT(",%s %d",i==ro?" ":"",orb[i]); else SNPRINTF(bto,bbl,bbm,",%s %d",i==ro?" ":"",orb[i]); } if (!bto) SOUTPUT(") =%d\n",kk); else SNPRINTF(bto,bbl,bbm,"] %d.\n",kk); FREE(orb); } /** * Here we list all nontrivial flats of the matroid up to rank * depending on lev, or up to the first flats found. * See also ematrix_printmore_flats() below. * (We currently do not use information about the printed flats * in the matroid hash-value since the flats are expensive to compute. * Also, the flat comp implementation works only for bounded size!) **/ ematrix_printmore_flats(NULL,0,1); if (lev>0) for (k=0,a=1; k<lev+a && k<ro; k++) { flt = ematrix_submatrices_sub(ee,k); for (x=flt,i=0; x?*x:0; x++) { xe = ematrix_closure(ee,*x); kk = ematrix_setrank(ee,xe); if (kk>k) {PROGERROR("something wrong with the flat rank %d>%d",kk,k);} if (ROWSM(xe)+COLSM(xe)>k && k==kk) if (ematrix_printmore_flats(xe,k,0)>=0) { if (i==0 && lev>1 && !bto) SOUTPUT("\n"); if (i==0 && !bto) OUTPUT("Listing all (nontrivial) flats in [%.25s] of rank %d:\n", EMNAME(e)?EMNAME(e):"",k); if (i==0 && bto) SNPRINTF(bto,bbl,bbm,"Flats of rank %d:",k); i++; if (i%5==0 && bto) SNPRINTF(bto,bbl,bbm,"\n"); if (!bto) { SOUTPUT(" ~\t - rank-%d flat (%d)\t{",k,i); for (j=0; j<ROWSM(xe); j++) SOUTPUT(" %d,",ROWSID(xe,j)); for (j=0; j<COLSM(xe); j++) SOUTPUT("%c %d",!j?' ':',',COLSID(xe,j)); SOUTPUT(" }\n"); } else { SNPRINTF(bto,bbl,bbm," %df{",i); for (j=0; j<ROWSM(xe); j++) SNPRINTF(bto,bbl,bbm,"%d,",GETREFMROW(xe,j)); for (j=0; j<COLSM(xe); j++) SNPRINTF(bto,bbl,bbm,"%c%d",!j?' ':',',GETREFMCOL(xe,j)+ro); SNPRINTF(bto,bbl,bbm,"}"); } } dispose_ematrix(xe); } if (i==0 && k==0 && lev>1 && !bto) SOUTPUT("\n"); if (i==0 && !bto) OUTPUT("There are -NO- (nontrivial) flats in [%.25s] of rank %d.\n",EMNAME(e)?EMNAME(e):"",k); if (i>0 && bto) SNPRINTF(bto,bbl,bbm,"\n"); if (flt) dispose_alist_mats(flt); if (i!=0 && bto && k>=3) break; if (i==0 && k>0) a++; } ematrix_printmore_flats(NULL,0,-1); /** * Here we list all nontrivial separations of the matroid up to lambda * depending on lev, or up to the first separations found. * (We currently do not use these information in the hash-value.) **/ if (lev>1 && !bto) { sep = ematrix_submatrices_all(ee); ii = sep? alist_getlength(sep):0; ses = MMALLOC((ii+2)*sizeof(ses[0])); for (x=sep; x?*x:0; x++) ses[x-sep] = ematrix_whatsep(ee,*x); for (k=0,a=-1; k<lev+a && k<ro; k++) { for (jj=i=0; jj<ii; jj++) if (ses[jj]==k) { xe = sep[jj]; if (ROWSM(xe)+COLSM(xe)<=k || ROWSM(xe)+COLSM(xe)>(ro+co)/2) continue; if (i==0 && lev>1) SOUTPUT("\n"); if (i==0) OUTPUT("Listing all exact separations in [%.25s] of lambda %d:\n", EMNAME(e)?EMNAME(e):"",k+1); SOUTPUT(" ~\t - %d-separation (%d)\t(",k+1,++i); for (j=0; j<ROWSM(xe); j++) SOUTPUT(" %d,",ROWSID(xe,j)); SOUTPUT(" "); for (j=0; j<COLSM(xe); j++) SOUTPUT(" %d,",COLSID(xe,j)); SOUTPUT(" )\n"); } if (i==0 && k==0) SOUTPUT("\n"); if (i==0) OUTPUT("There are -NO- exact separations in [%.25s] of lambda %d.\n",EMNAME(e)?EMNAME(e):"",k+1); if (i==0 && k>0) a++; } if (sep) dispose_alist_mats(sep); FREE(ses); } #ifndef FASTPROG /* paranoic testing of the hash-value computation: */ if (lev>=0 && IFRANDDEBUGLESS(111)) { for (ii=0; ii<4; ii++) { /* extra testing hash with pivoted matrix */ i = RANDOM()%ROWSM(ee); j = RANDOM()%COLSM(ee); if (SIGNM(ee,i,j)!=0) ematrix_pivot(ee,i,j); } if (hash!=ematrix_printmore_ext(ee,-1,NULL,0)) {PROGERROR("incorrect computation of matroid hash, ret=%ld",hash);} } /* (ee is modified here !!!) */ #endif if (bas) dispose_alist_mats(bas); if (flts) FREE(flts); if (basi) FREE(basi); if (basii) FREE(basii); /** * Some other final characteristics are printed here. * Representability is surveyed for some basic fields, depending on lev. * Among them the matroid hash-value is printed out and always returned. * So far, the matroid hash-value collects information about rank, * number of bases, numbers of bases per each element and each pair of elements. * You must update the version number if you change the collected information! **/ if (lev>0 && !bto) { SOUTPUT("\n"); k = 0; OUTPUT("Matroid [%.25s] connectivity is %d", EMNAME(e)?EMNAME(e):"",kk=struct_iconnectivity(e,&k)); if (kk==3 && k) SOUTPUT(" (internally %d-connected).\n",kk+1); else SOUTPUT(".\n"); OUTPUT("Matroid [%.25s] girth (shortest cycle) is %d.\n", EMNAME(e)?EMNAME(e):"",struct_matgirth(e)); } if (lev>0 && bto) { SNPRINTF(bto,bbl,bbm,"Connectivity %d, girth (shortest cycle) %d.\n", struct_connectivity(e),struct_matgirth(e)); } if (lev>2) { char *xx_fields[] = {"GF(2)","GF(3)","GF(4)","GF(5)","GF(7)","GF(8)","GF(9)"}; if (!bto) OUTPUT("Matroid [%.25s] representability:",EMNAME(e)?EMNAME(e):""); else SNPRINTF(bto,bbl,bbm,"Representability over:"); for (j=0; j<(int)(sizeof(xx_fields)/sizeof(xx_fields[0])); j++) { ii = pfield_curindex(); pfield_switchto(xx_fields[j]); /* (we expect all the fields defined!) */ a = grepr_isrepresented(ee,ii)>0; if (!bto) SOUTPUT(" %c%s%c",a?'+':'-',xx_fields[j],a?'+':'-'); else SNPRINTF(bto,bbl,bbm," %c%s%c",a?'+':'-',xx_fields[j],a?'+':'-'); pfield_switchto_fast(ii); } if (!bto) SOUTPUT("\n\n"); else SNPRINTF(bto,bbl,bbm,"\n"); } if (lev>=0 && !bto) OUTPUT("Overall matroid [%.25s] hash-value (version %s): %ld\n", EMNAME(e)?EMNAME(e):"",EM_HASHVER,hash); dispose_ematrix(ee); return hash; }
int struct_connorder_ext(ematrix *e, int tr, int *cor, int *cp, int *cxp, int **cadj) { int i,ii,j,k, r,c, cornul=0, *ud,udstack[30]; if (!tr) ematrix_transpose(e); if (COLSM(e)<14) ud = udstack; else ud = MMALLOC((2*COLSM(e)+2)*sizeof(ud[0])); if (cxp && cor) {PROGERROR("not allowed to use cxp[] with cor[] !!"); cxp=NULL;} if (cor==NULL) { cornul = 1; cor = ud+COLSM(e); } for (j=0; j<COLSM(e); j++) ud[j] = cor[j] = 0; if (cxp) for (j=0; j<ROWSM(e); j++) cxp[j] = 0; if (cadj) for (i=0; i<COLSM(e); i++) for (ii=0; ii<COLSM(e); ii++) cadj[i][ii] = -1; /** * We simply search the columns of e, for each one looking at the rows it * has nonzero, and adding other columns which have nonzeros in this row. * ud[ii] marks columns that were already reached, starting from ud[0]. * If k>j happens, that means we ran out of connected columns to continue * the search, and we start with the first next component. * (This happens always in the first run.) **/ j = -1; c = 0; r = 1; for (k=0; k<COLSM(e); k++) { if (k>j) { for (ii=0; ii<COLSM(e) && ud[ii]; ii++) ; if (ii>=COLSM(e) || k>j+1) {PROGERROR("must find another component here!"); break;} cor[++j] = ii; ud[ii] = ++c; if (k>0) r = 0; /* next component reached in the graph -> disconnected */ } for (i=0; i<ROWSM(e); i++) if (SIGNM(e,i,cor[k])!=0) for (ii=0; ii<COLSM(e); ii++) if (SIGNM(e,i,ii)!=0 && ii!=cor[k]) { if (!ud[ii]) { /* next column reached in the graph */ cor[++j] = ii; ud[ii] = c; } if (cadj) /* record adjacency between the columns */ cadj[cor[k]][ii] = cadj[ii][cor[k]] = i; } if (j+1>=COLSM(e) && !cadj) break; } /** * Additional data: Store component indices for the columns and the rows * of (transposed?) matrix e. * These are indexed in the same way as cor[] if given (only for cp[]), * or by absolute matrix line indices otherwise. **/ if (cp) for (j=0; j<COLSM(e); j++) { if (!cornul) cp[j] = ud[cor[j]]; else cp[j] = ud[j]; } if (cxp) for (i=0; i<ROWSM(e); i++) { for (j=0; j<COLSM(e) && !SIGNM(e,i,j); j++) ; if (j<COLSM(e)) cxp[i] = ud[j]; } #ifndef FASTPROG if (DEBUGLEV>=CURDLEV+2) { DEBUG(CURDLEV+2,"Found%s connected col order: ",r?"":" -NO-"); for (ii=0; ii<COLSM(e); ii++) SDEBUG(CURDLEV+2,"%d, ",cor[ii]); SDEBUG(CURDLEV+2,"\n"); EMATDEBUG(CURDLEV+4,e,"\t\t\t<\t"); } if (cadj && DEBUGLEV>=CURDLEV+2) { EMATDEBUGS(CURDLEV+2,e,"\t\tconn\t"); DEBUG(CURDLEV+2," - cadj[][] adjacencies (-1 for no adj):\n"); for (i=0; i<ROWSM(e); i++) for (j=0; j<COLSM(e); j++) SDEBUG(CURDLEV+2,"%s% d%c",j==0?"\t\t":"",cadj[i][j],j==COLSM(e)-1?'\n':'\t'); } if (j+1>=COLSM(e) && IFRANDDEBUG(33)) for (ii=0; ii<COLSM(e); ii++) if (!ud[ii]) {PROGERROR("wrong computation of a connected order!");} if (j+1<COLSM(e) && IFRANDDEBUGLESS(333)) { for (i=0; i<COLSM(e); i++) for (ii=i+1; ii<COLSM(e); ii++) if (ud[i]!=ud[ii]) for (j=0; j<ROWSM(e); j++) if (SIGNM(e,j,i)!=0 && SIGNM(e,j,ii)!=0) {PROGERROR("wrong computation of a (dis-)connected order!");} } #endif if (ud && ud!=udstack) FREE(ud); if (!tr) ematrix_transpose(e); return (r?1:-1); }
int struct_hasfan_ext(int ch, ematrix *e, ematrix *ec, int tr, int lo, int fan) { ematrix *ee, *eec; char buf[1000]; int i,k,kk, st,tt1,tt2,tt,ttm=0, br, ret, lf, *fn=NULL,*fnm, fnstack[104]; if (ec) if (!ISREFMAT(ec) || REFMAT(ec)!=e || ISTRANSPM(e)!=ISTRANSPM(ec)) { PROGERROR("When using ec, it must refer to e in the same transpose state"); ec = NULL; } if (ec && tr>=0) { PROGERROR("When using ec, do not use tr>=0"); tr = -1; } if (fan>=0 && fan<3) { PROGERROR("What is fan of length %d <3 ??",fan); fan = 3; } if (lo<0) lo = tr? COLSM(e)-1:ROWSM(e)-1; buf[0] = 0; kk = 0; #ifndef FASTPROG DEBUG(CURDLEV+(ch<0),"Looking for %d-fans in %p [%s] %dx%d (tr=%d, lo=%d%s)...\n", fan,e,EMNAME(e)?EMNAME(e):"",ROWSM(e),COLSM(e),tr,lo,ec?", ec":""); EMATDEBUGS(CURDLEV+1,e,"\t\tf\t"); if (ec) EMATDEBUGS(CURDLEV+1+(ch<0),ec,"\t\t\t-\t"); if (ch>=0 && tr>=0 && IFRANDDEBUGLESS(555)) { /* (debug-check for 3-connectivity without lo) */ ee = ematrix_copy(e); ematrix_remove_rc(ee,tr,lo); if (!struct_isconnected(ee,3)) {PROGERROR("wrong - not 3-connected without lo=%d",lo); EMATDEBUG(0,ee,"!!\t");} dispose_ematrix(ee); } #endif if (fan>ROWSM(e)+COLSM(e)) return 0; if (ch>2) { OUTPUT("Looking for %d%s in the matroid [%s] %dx%d...\n", fan,fan<0?" the longest fan":"-fans",EMNAME(e)?EMNAME(e):"",ROWSM(e),COLSM(e)); if (tr>=0 || ec) DEBUG(0,"Do not call fan printing with tr=%d>=0 or ec=%p.\n",tr,ec); if (fan<0) DEBUG(CURDLEV-3,"Do not call all fan printing with fan=%d<0 (max fan).\n",fan); } if (ROWSM(e)+COLSM(e)<50) fn = fnstack; else fn = MMALLOC((ROWSM(e)+COLSM(e)+2)*2*sizeof(fn[0])); fnm = fn+ROWSM(e)+COLSM(e)+2; if (tr<0) { /* no last line for the fan given - trying everything */ st = 0; tt1 = 0; tt2 = 1; } else { /* the last fan line is given, also determines tt by 3-connectivity */ st = 1; tt1 = tt2 = tr? 1:0; fn[0] = tr? ROWSM(e)+lo:lo; DEBUG(CURDLEV+2,".. hasfan pre-determined %s fn[0] = %d, tt=%d\n",tr?"col":"row",lo,tt1); } /** * We cycle all choices of k lines and starting tt values (triad 0/triangle 1), * beginning with a choice of fn[st], where st and tt1,tt2 depend on the input. * One choice is a row for <ROWSM and a column +ROWSM otherwise. * We record the longest fan length in lf, and the fan itself in fnm[]. * If we look only for a fan longer than the given value, we stop immediately * after we find it, otherwise we search through all fans to find the longest one. * As we generate our choice, we test the consecutive triples for being * triangles/triads (by tt). **/ ret = lf = 0; for (tt=tt1; tt<=tt2 && !ret; tt+=(ret?0:1)) { k = st; fn[k] = -1; while (k>=st && !ret) { /* the value of fn[k] is the current choice - row for <ROWSM, column+ROWSM otherwise */ if (++fn[k]>=ROWSM(e)+COLSM(e)) { --k; continue; /* (no more choices at this level) */ } for (i=0; i<k; i++) if (fn[i]==fn[k]) break; if (i<k) continue; /* (if fn[k] was already chosen previously) */ if (ec) { if (fn[k]<ROWSM(e)) for (i=ROWSM(ec)-1; i>=0 && GETREFMROW(ec,i)!=fn[k]; i--) ; else for (i=COLSM(ec)-1; i>=0 && GETREFMCOL(ec,i)!=fn[k]-ROWSM(e); i--) ; if (i<0) continue; /* (if fn[k] does not belong to ec if given) */ } DEBUG(CURDLEV+2,"%*s. hasfan(%d) trying choice %s fn[%d] = %d (%d) for %s\n",2*k,"",fan, fn[k]<ROWSM(e)?"row":"col",k,fn[k]<ROWSM(e)?fn[k]:fn[k]-ROWSM(e),fn[k]<ROWSM(e)?ROWSID(e,fn[k]):COLSID(e,fn[k]-ROWSM(e)),(k+tt)%2?"triang":"triad"); if (k>=2) { /* looking for a triangle ((k+tt)%2==1) or triad ((k+tt)%2==0) at this level */ br = struct_hasfan_triax((ch<-3?-1:0),e,(k+tt)%2,fn[k-2],fn[k-1],fn[k],1); if (br<=0) continue; /* if there was no triaxx, then cycle other choices */ } if (++k>lf) { /* records the longest fan found so far */ lf = k; ttm = tt; for (i=0; i<k; i++) fnm[i] = fn[i]; DEBUG(CURDLEV+2,"-%*s. hasfan(%d) found longer = %d\n",2*k,"",fan,lf); } if (k<fan || fan<0) { /* to the next choice of line */ fn[k] = -1; continue; } if (k>ROWSM(e)+COLSM(e)) {PROGERROREXIT("Out of index range looking for a fan");} fn[k] = 11111; /* fan of given length found here, plus printing */ if (ch>=2 || CURDLEV-1+(ch<0)<=printlev) { sprintf(buf,"fan: (%s+..) ",ttm?"triangle":"triad"); for (i=0; i<lf; i++) snprintf((buf[800]=0,buf+strlen(buf)),50,"%s%d(%d), ", fn[i]<ROWSM(e)?"r":"c",fn[i]<ROWSM(e)?fn[i]:fn[i]-ROWSM(e),fn[i]<ROWSM(e)?ROWSID(e,fn[i]):COLSID(e,fn[i]-ROWSM(e))); } if (ch>2) OUTPUT("\t[%s]#%d %s\n",EMNAME(e)?EMNAME(e):"",++kk,buf); else ret = 1; /* (this breaks the cycle, unless all printing is required) */ }} /** * If fan>0, then the fans of this length are recorded above, and they are * all printed out if ch>2 is requested. * On the other hand, fan<0 the longest fan is printed out below, separately. * The return value is the longest fan, or the requested fan length, or 0. **/ if (fan<=0) ret = (lf>=3? lf:0); else ret = (lf>=fan? fan:0); if (fan<0) if (ch>=2 || CURDLEV-1+(ch<0)<=printlev) { sprintf(buf,"longest fan: (%s+..) ",ttm?"triangle":"triad"); for (i=0; i<lf; i++) snprintf((buf[800]=0,buf+strlen(buf)),50,"%s%d(%d), ", fnm[i]<ROWSM(e)?"r":"c",fnm[i]<ROWSM(e)?fnm[i]:fnm[i]-ROWSM(e),fnm[i]<ROWSM(e)?ROWSID(e,fnm[i]):COLSID(e,fnm[i]-ROWSM(e))); } if (ch==2 || (ch>=2 && fan<0)) OUTPUT("\t[%s] %s\n",EMNAME(e)?EMNAME(e):"",buf); ee = eec = NULL; #ifndef FASTPROG DEBUG(CURDLEV-1+(!ret)+(ch<0),"- hasfan(%d) test for %p [%s] (l %d, tr=%d%s) found max %d %s.\n", fan,e,EMNAME(e)?EMNAME(e):"",lo,tr,ec?", ec":"",lf,fan>0?"":(ret?"+HAS+":"NO fan")); SDEBUG(CURDLEV-1+(!ret)+(ch<0),"\t\t\t -> %s\n",buf); /* (debug-testing the full-test for diff basis of e) */ if (ch>=0 && tr<0 && IFRANDDEBUG(222)) { ee = ematrix_copy(e); EMSETNAME(ee,"rec-test"); for (eec=ec, tt=0; tt<5; tt++) { i = random()%ROWSM(ee); k = random()%COLSM(ee); if (SIGNM(ee,i,k)==0) continue; if (ec!=NULL) { /* (not to interfere with the matrix ec if given) */ for (tt1=ROWSM(ec)-1; tt1>=0 && GETREFMROW(ec,tt1)!=i; tt1--) ; for (tt2=COLSM(ec)-1; tt2>=0 && GETREFMCOL(ec,tt2)!=k; tt2--) ; if (tt1>=0 && tt2>=0) ematrix_pivot(ee,i,k); } else ematrix_pivot(ee,i,k); } if (ec) { eec = ematrix_refer_all(ec); ematrix_rerefer(eec,ee); } else if (random()%2==1) ematrix_transpose(ee); if (ret!=(kk=struct_hasfan_ext(-1,ee,eec,-1,-1,fan))) {PROGERROR("The result must be the same after pivoting (transpose)! ret=%d != %d",ret,kk);} if (ec) dispose_ematrix(eec); dispose_ematrix(ee); } #endif if (fn && fn!=fnstack) FREE(fn); return ret; }
int struct_hasbwidth3_ext(int ch, ematrix *em, char **decomp, int *ldecomp) { ematrix *ee, *ex,*e1,*e2, *eu, *ef,*eff; ematrix **list, **lpair, **lln,*llnst[30], **x,**y; int i,j,k, a,b, r, msz; char buf[400]; if (ldecomp!=NULL) {PROGERROR("return ldecomp[] is not implemented yet!"); ldecomp = NULL;} if (!em) {PROGERROR("the matrix must be given here"); return -1;} ee = ematrix_copy(em); msz = ROWSM(ee)+COLSM(ee); #ifndef FASTPROG if (msz<10 || (msz<14 && IFRANDDEBUGLESS(22)) || IFRANDDEBUGLESS(222)) { if (!struct_isconnected(ee,3)) {PROGERROR("Can correctly test branch-width 3 only for 3-connected matrices!");} } DEBUG(CURDLEV,"Testing branch-width 3 for the matroid %p [%s]...\n",ee,EMNAME(em)?EMNAME(em):""); #endif lln = (msz<28?llnst: MMALLOC((msz+2)*sizeof(lln[0]))); list = ematrix_submatrices_sub(ee,1); if (alist_getlength(list)!=msz) {PROGERROR("wrong list of singletons generated here ?!?");} for (x=list; x?*x:0; x++) { snprintf(buf,5," %d ",(ROWSM(*x)>0?ROWSID(*x,0):COLSID(*x,0))); EMSETNAME(*x,buf); lln[GETREFMLINE(ee,*x,0)] = *x; } /** * We start with an initial partition list of the matroid into singletons. * Then we cycle the next procedure until the list has one part only. * Trivial cases are sorted first - a matroid on <=6 elements always * has bw <=3, and if only <=3 singletons remain besides one larger * part, then we are done as well. * The supplementary array refers to those parts in list that are * still singletons (by their row/column indices in ee). **/ while (alist_getlength(list)>1) { DEBUG(CURDLEV+2," new cycle for list %d\n",alist_getlength(list)); lpair = NULL; eu = e1 = e2 = NULL; r = 0; for (x=list, a=b=0,y=NULL; *x && a<2 && b<7; x++,b++) if (ROWSM(*x)+COLSM(*x)>1) { a++; y = x; } if (a==0 && b<=6) { e1 = ematrix_refer_all(ee); eu = ematrix_refer_all(ee); r = 1; } else if (a==1 && b<=4) { e1 = *y; e2 = ematrix_refextract_xall(ee,*y); eu = ematrix_refer_all(ee); r = 2; } /** * Here we try all pairs of parts in list. * If their union is 3-separating, and not both are singletons, * then we have a new part for replacement. **/ for (x=list; *x && !r; x++) for (y=x+1; *y && !r; y++) { if ((a=ROWSM(*x)+COLSM(*x))>1 || (b=ROWSM(*y)+COLSM(*y))>1) { eu = ematrix_union(*x,*y); if (ematrix_whatsep(ee,eu)<3) { if (a>=b) { e1 = *x; e2 = *y; } else { e1 = *y; e2 = *x; } r = 3; } else { dispose_ematrix(eu); } /** * If both in the pair are singletons, then we save this pair for * later testing, and we try our luck with the line-(co)closure. * If the closure has >=4 elements among singletons, then it forms * a new part. * We save a possible closure triple for later testing, but only * if the third element is in the middle of the pair. **/ } else { ef = ematrix_union(*x,*y); lpair = alist_append(lpair,ef); for (k=0; k<2 && !r; k++) { eff = ematrix_closure_tr(ee,ef,k); a = 1; for (i=ROWSM(eff)+COLSM(eff)-1; i>=0; i--) { j = GETREFMLINE(ee,eff,i); if (lln[j]==NULL) { if (i<ROWSM(eff)) ematrix_remove_row(eff,i); else ematrix_remove_col(eff,i-ROWSM(eff)); } else { a = a && (j==GETREFMLINE(ee,*x,0) || j==GETREFMLINE(ee,*y,0) || (j>GETREFMLINE(ee,*x,0) && j>GETREFMLINE(ee,*y,0))); } } if (ROWSM(eff)+COLSM(eff)>3) { e1 = eff; eu = ematrix_refer_all(eff); r = 1; } else if (a && ROWSM(eff)+COLSM(eff)==3) { lpair = alist_append(lpair,eff); } else dispose_ematrix(eff); } } DEBUG(CURDLEV+3," cycle x=%d, y=%d, r=%d, pair %d\n",(int)(x-list),(int)(y-list),r,alist_getlength(lpair)); } /** * Then we have to try all pairs that take one non-singleton part * and the other as one of the above pairs or triples, * or two disjoint above pairs or triples. * Again, we look at their union whether it is 3-separating. **/ for (x=list; *x && !r; x++) if (ROWSM(*x)+COLSM(*x)>1) { for (y=lpair; (y?*y:0) && !r; y++) { eu = ematrix_union(*x,*y); if (ematrix_whatsep(ee,eu)<3) { e1 = *x; e2 = ematrix_refer_all(*y); r = 2; } else dispose_ematrix(eu); } } for (x=lpair; (x?*x:0) && !r; x++) { if (ROWSM(*x)+COLSM(*x)>3) {PROGERROR("only pairs and triples should be here");} for (y=x+1; *y && !r; y++) if (ematrix_isdisjoint(*x,*y)) { eu = ematrix_union(*x,*y); if (ematrix_whatsep(ee,eu)<3) { e1 = ematrix_refer_all(*x); e2 = ematrix_refer_all(*y); r = 1; } else dispose_ematrix(eu); } } if (lpair) dispose_alist_mats(lpair); /** * Finally, if we have found a union (in eu) for the new part (r>0), * then we have to remove the current parts of the union, * print this new branch for records, and store the union into the list. **/ if (r<=0) break; buf[0] = 0; for (k=0, ex=e1; ex && k<2; k++, ex=e2) { if (r>k+1) { snprintf(buf+strlen(buf),180,"(%s)",EMNAME(ex)); list = alist_delete_val(list,ex); } else { for (i=ROWSM(ex)+COLSM(ex)-1, a=0; i>=0; i--) { j = GETREFMLINE(ee,ex,i); ef = lln[j]; lln[j] = NULL; if (!ef) {PROGERROR("should find only singleton elements here"); continue;} if (!a++) snprintf(buf+strlen(buf),3,"("); if (strlen(buf)<380) snprintf(buf+strlen(buf),5,"%s",EMNAME(ef)); list = alist_delete_val(list,ef); dispose_ematrix(ef); } if (a>0) snprintf(buf+strlen(buf),3,")"); } dispose_ematrix(ex); } DEBUG(CURDLEV+1," - new branch found %s\n",buf); EMSETNAME(eu,buf); list = alist_append(list,eu); } /** * Here we prepare the return values and possible debug printing. * We also try the result recursively on an equivalent dual matrix. **/ if (alist_getlength(list)<=1) { r = 1; if (decomp && list[0]) *decomp = MSTRDUP(EMNAME(list[0])); if (ch>1) OUTPUT("A width-3 branch decomposition of [%s] is: %s\n",EMNAME(em)?EMNAME(em):"",EMNAME(list[0])); } else { r = -1; if (ch>1) OUTPUT("There is NO width-3 branch decomposition of [%s].\n",EMNAME(em)?EMNAME(em):""); } #ifndef FASTPROG if (r>=0 && ch>=0) { DEBUG(CURDLEV-1,"Found a width 3 branch-decomposition of %p [%s] here\n\t\t\t\t\t%s.\n", ee,EMNAME(em)?EMNAME(em):"",list[0]?EMNAME(list[0]):""); if (msz>1 && (list[0]?ROWSM(list[0])+COLSM(list[0])!=msz:1)) {PROGERROR("wrong final partition in computation of branch-width 3");} } else if (ch>=0) { DEBUG(CURDLEV-1,"NO width 3 branch-decomposition of %p [%s] exists.\n",ee,EMNAME(em)?EMNAME(em):""); for (x=list,a=0; x?*x:0; x++) a += ROWSM(*x)+COLSM(*x); if (a!=msz) {PROGERROR("lost or extra elements in the partition list! %d!=%d",msz,a);} } if (IFRANDDEBUGLESS(222) && ch>=0) { ematrix_transpose(ee); /* extra debug testing with pivoted dual matrix */ for (k=0; k<4; k++) { i = RANDOM()%ROWSM(ee); j = RANDOM()%COLSM(ee); if (SIGNM(ee,i,j)!=0) ematrix_pivot(ee,i,j); } k = struct_hasbwidth3_ext(-1,ee,NULL,NULL); if (k!=r) {PROGERROR("wrong result when recursivly calling r%d o%d !",k,r); EMATDEBUG(0,ee," !r!\t"); EMATDEBUG(0,em," !o!\t");} } /* (ee is modified here!!!) */ #endif dispose_alist_mats(list); dispose_ematrix(ee); if (lln && lln!=llnst) FREE(lln); return r; }
void frame_printtree_ext(FILE *fout, char *buf, framestruc *fr, int verb, char *pref, int maxbuf, int maxson, int maxdepth) { framestruc *ff, ***yr; ematrix *ffem; int *ir,*lr, ii,k,l, maxsl,maxsl2; char bpr[100]; if (!fout && !buf) {PROGERROR("a file or a buffer must be given!"); return;} if (maxbuf<0 && buf) {PROGERROR("maxbuf limit must be given when printing to a buffer!"); maxbuf=10;} if (maxdepth<0) maxdepth = PTREE_MAXDEPTH; if (maxson<0) maxson = PTREE_MAXSONS; maxsl = maxson/2; maxsl2 = maxson/3; if (maxsl<2) maxsl = 2; if (buf) buf[0] = 0; yr = MMALLOC((maxdepth+2)*sizeof(yr[0])); ir = MMALLOC(2*(maxdepth+2)*sizeof(ir[0])); lr = ir+maxdepth+2; /** * Here we print the subtree of given fr: * We start a depth-first search in the tree of fr, * and we print each frame when it is reached the first time. * The array yr[] is used to keep the current list of sons * at each level of the search - incremented along the way. * The array ir[] counts the printed sons, and lr[] keeps * the lengths of the whole son lists. **/ yr[0] = NULL; for (k=0; k>=0; ) { if (yr[k]==NULL) { yr[k] = (k<=0?&fr: FRSONS(*yr[k-1])); ir[k] = 0; lr[k] = (k<=0?1: alist_getlength(yr[k])); if (lr[k]<=0) { k--; continue; } } else { if (k>0) yr[k]++; if (k<=0 || *yr[k]==NULL) { k--; continue; } } /** * We print the actual frame *yr[k]=ff, according to buf and verb. * However, if the list of sons is longer than the given limit maxson, * then only first half and last third of them is printed which * is indicated by a printed message. * Printed format depends on buf/fout and on verb. **/ ff = *yr[k]; ii = ++ir[k]; if (lr[k]>maxson && maxsl<lr[k]-maxsl2 && verb<=1) { if (ii==maxsl) { if (!buf) fprintf(fout,"%s%s%*s(%d.%d-%d) \t... skipping sons in a long list ...\n%s", (verb>0?"\n":""),pref,2*k,"",k+1,maxsl,lr[k]-maxsl2,(verb>0?"\n":"")); else if ((int)strlen(buf)<maxbuf-99-2*k) snprintf(buf+strlen(buf),90+2*k,"%s%s%*s(%d.%d-%d) ... skipping sons in a long list ...\n%s", (verb>0?"\n":""),pref,2*k,"",k+1,maxsl,lr[k]-maxsl2,(verb>0?"\n":"")); } if (ii>=maxsl && ii<=lr[k]-maxsl2) continue; } ffem = FRMATRIX(ff); if (!ffem) bpr[0] = 0; else snprintf(bpr,80,"m%dx%d",ROWSM(ffem),COLSM(ffem)); if (buf) { l = strlen(buf); if (l<maxbuf-5) snprintf(buf+l,maxbuf-l-4,"%*s(%d.%d)fr [%.15s] %s \"%.*s\"\n", 2*k,"",k+1,ii,FRNAME(ff),bpr,44-3*k,FRCOMMENT(ff)?FRCOMMENT(ff):""); buf[maxbuf-1] = 0; } else if (verb<=1) { fprintf(fout,"%s%*s(%d.%d)fr [%.15s] %s \"%.*s\"\n",pref,2*k,"", k+1,ii,FRNAME(ff),bpr,55-3*k,FRCOMMENT(ff)?FRCOMMENT(ff):""); } else { if (verb>2) fprintf(fout,"\n"); snprintf(bpr,80,"%s%*s(%d.%d) ",pref,3*k,"",k+1,ii); frame_print_ext(fout,ff,verb-1,(verb>3),bpr); } /** * We dive deeper in the tree here (after printing the frame), * unless the maximal given bound maxdepth is reached. * Deeper frames in the tree are simply skipped. **/ if (k<maxdepth) yr[++k] = NULL; else if (FRSONS(*yr[k])!=NULL) { if (!buf) fprintf(fout,"%s%s%*s(%d.x) \t... skipping too deeply nested frames ...\n%s", (verb>0?"\n":""),pref,2*k+2,"",k+2,(verb>0?"\n":"")); else if ((int)strlen(buf)<maxbuf-99-2*k) snprintf(buf+strlen(buf),90+2*k,"%s%s%*s(%d.x) \t... skipping too deeply nested frames ...\n%s", (verb>0?"\n":""),pref,2*k+2,"",k+2,(verb>0?"\n":"")); } } if (fout && verb>2) fprintf(fout,"\n"); FREE(yr); FREE(ir); }