STATIC MYBOOL SOS_member_sortlist(SOSgroup *group, int sosindex) /* Routine to (re-)sort SOS member arrays for faster access to large SOSes */ { int i, n; int *list; lprec *lp = group->lp; SOSrec *SOS; #ifdef Paranoia if((sosindex < 0) || (sosindex > group->sos_count)) { report(lp, IMPORTANT, "SOS_member_sortlist: Invalid SOS index %d\n", sosindex); return(FALSE); } #endif if((sosindex == 0) && (group->sos_count == 1)) sosindex = 1; if(sosindex == 0) { for(i = 1; i <= group->sos_count; i++) { if(!SOS_member_sortlist(group, i)) return(FALSE); } } else { SOS = group->sos_list[sosindex-1]; list = SOS->members; n = list[0]; /* Make sure that the arrays are properly allocated and sized */ if(n != group->sos_list[sosindex-1]->size) { allocINT(lp, &SOS->membersSorted, n, AUTOMATIC); allocINT(lp, &SOS->membersMapped, n, AUTOMATIC); group->sos_list[sosindex-1]->size = n; } /* Reload the arrays and do the sorting */ for(i = 1; i <= n; i++) { SOS->membersSorted[i - 1] = list[i]; SOS->membersMapped[i - 1] = i; } sortByINT(SOS->membersMapped, SOS->membersSorted, n, 0, TRUE); } return( TRUE ); }
STATIC int append_SOSrec(SOSrec *SOS, int size, int *variables, REAL *weights) { int i, oldsize, newsize, nn; lprec *lp = SOS->parent->lp; oldsize = SOS->size; newsize = oldsize + size; nn = abs(SOS->type); /* Shift existing active data right (normally zero) */ if(SOS->members == NULL) allocINT(lp, &SOS->members, 1+newsize+1+nn, TRUE); else { allocINT(lp, &SOS->members, 1+newsize+1+nn, AUTOMATIC); for(i = newsize+1+nn; i > newsize+1; i--) SOS->members[i] = SOS->members[i-size]; } SOS->members[0] = newsize; SOS->members[newsize+1] = nn; /* Copy the new data into the arrays */ if(SOS->weights == NULL) allocREAL(lp, &SOS->weights, 1+newsize, TRUE); else allocREAL(lp, &SOS->weights, 1+newsize, AUTOMATIC); for(i = oldsize+1; i <= newsize; i++) { SOS->members[i] = variables[i-oldsize-1]; if((SOS->members[i] < 1) || (SOS->members[i] > lp->columns)) report(lp, IMPORTANT, "append_SOS_rec: Invalid SOS variable definition for index %d\n", SOS->members[i]); else { if(SOS->isGUB) lp->var_type[SOS->members[i]] |= ISGUB; else lp->var_type[SOS->members[i]] |= ISSOS; } if(weights == NULL) SOS->weights[i] = i; /* Follow standard, which is sorted ascending */ else SOS->weights[i] = weights[i-oldsize-1]; SOS->weights[0] += SOS->weights[i]; } /* Sort the new paired lists ascending by weight (simple bubble sort) */ i = sortByREAL(SOS->members, SOS->weights, newsize, 1, TRUE); if(i > 0) report(lp, DETAILED, "append_SOS_rec: Non-unique SOS variable weight for index %d\n", i); /* Define mapping arrays to search large SOS's faster */ allocINT(lp, &SOS->membersSorted, newsize, AUTOMATIC); allocINT(lp, &SOS->membersMapped, newsize, AUTOMATIC); for(i = oldsize+1; i <= newsize; i++) { SOS->membersSorted[i - 1] = SOS->members[i]; SOS->membersMapped[i - 1] = i; } sortByINT(SOS->membersMapped, SOS->membersSorted, newsize, 0, TRUE); /* Confirm the new size */ SOS->size = newsize; return(newsize); }
/* LOCAL HELPER ROUTINE */ int bfp_LUSOLfactorize(lprec *lp, MYBOOL *usedpos, int *rownum, int *singular) { int i, j, nz, deltarows = bfp_rowoffset(lp); INVrec *invB = lp->invB; /* Handle normal, presumed nonsingular case */ if(singular == NULL) { /* Optionally do a symbolic minimum degree ordering; not that slack variables should not be processed */ /*#define UsePreprocessMDO*/ #ifdef UsePreprocessMDO int *mdo; mdo = lp->bfp_createMDO(lp, usedpos, lp->rows, TRUE); if(mdo != NULL) { for(i = 1; i <= lp->rows; i++) lp->set_basisvar(lp, i, mdo[i]); FREE(mdo); } #endif /* Reset the factorization engine */ LUSOL_clear(invB->LUSOL, TRUE); /* Add the basis columns in the original order */ for(i = 1; i <= invB->dimcount; i++) { nz = lp->get_basiscolumn(lp, i, rownum, invB->value); LUSOL_loadColumn(invB->LUSOL, rownum, i, invB->value, nz, 0); if((i > deltarows) && (lp->var_basic[i-deltarows] > lp->rows)) lp->invB->user_colcount++; } /* Factorize */ i = LUSOL_factorize(invB->LUSOL); } /* Handle case where a column may be singular */ else { LLrec *map; /* Reset the factorization engine */ i = bfp_LUSOLidentity(lp, rownum); /* Build map of available columns */ nz = createLink(lp->rows, &map, NULL); for(i = 1; i <= lp->rows; i++) { if(lp->var_basic[i] <= lp->rows) removeLink(map, i); } /* Rebuild the basis, column by column, while skipping slack columns */ j = firstActiveLink(map); for(i = 1; i <= lp->rows; i++) { if(lp->var_basic[i] <= lp->rows) continue; nz = bfp_LUSOLsetcolumn(lp, j+deltarows, lp->var_basic[i]); if(nz == LUSOL_INFORM_LUSUCCESS) lp->invB->user_colcount++; else { nz = bfp_LUSOLsetcolumn(lp, j+deltarows, i); lp->set_basisvar(lp, i, i); } j = nextActiveLink(map, j); } /* Sort the basis list */ MEMCOPY(rownum, lp->var_basic, lp->rows+1); sortByINT(lp->var_basic, rownum, lp->rows, 1, TRUE); } return( i ); }