Esempio n. 1
0
MYBOOL crash_basis(lprec *lp)
{
  int     i;
  MATrec  *mat = lp->matA;
  MYBOOL  ok = TRUE;

  /* Initialize basis indicators */
  if(lp->basis_valid)
    lp->var_basic[0] = FALSE;
  else
    default_basis(lp);

  /* Set initial partial pricing blocks */
  if(lp->rowblocks != NULL)
    lp->rowblocks->blocknow = 1;
  if(lp->colblocks != NULL)
    lp->colblocks->blocknow = ((lp->crashmode == CRASH_NONE) || (lp->colblocks->blockcount == 1) ? 1 : 2);

  /* Construct a basis that is in some measure the "most feasible" */
  if((lp->crashmode == CRASH_MOSTFEASIBLE) && mat_validate(mat)) {
    /* The logic here follows Maros */
    LLrec   *rowLL = NULL, *colLL = NULL;
    int     ii, rx, cx, ix, nz;
    REAL    wx, tx, *rowMAX = NULL, *colMAX = NULL;
    int     *rowNZ = NULL, *colNZ = NULL, *rowWT = NULL, *colWT = NULL;
    REAL    *value;
    int     *rownr, *colnr;

    report(lp, NORMAL, "crash_basis: 'Most feasible' basis crashing selected\n");

    /* Tally row and column non-zero counts */
    ok = allocINT(lp,  &rowNZ, lp->rows+1,     TRUE) &&
         allocINT(lp,  &colNZ, lp->columns+1,  TRUE) &&
         allocREAL(lp, &rowMAX, lp->rows+1,    FALSE) &&
         allocREAL(lp, &colMAX, lp->columns+1, FALSE);
    if(!ok)
      goto Finish;

    nz = mat_nonzeros(mat);
    rownr = &COL_MAT_ROWNR(0);
    colnr = &COL_MAT_COLNR(0);
    value = &COL_MAT_VALUE(0);
    for(i = 0; i < nz;
        i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {
      rx = *rownr;
      cx = *colnr;
      wx = fabs(*value);
      rowNZ[rx]++;
      colNZ[cx]++;
      if(i == 0) {
        rowMAX[rx] = wx;
        colMAX[cx] = wx;
        colMAX[0]  = wx;
      }
      else {
        SETMAX(rowMAX[rx], wx);
        SETMAX(colMAX[cx], wx);
        SETMAX(colMAX[0],  wx);
      }
    }
    /* Reduce counts for small magnitude to preserve stability */
    rownr = &COL_MAT_ROWNR(0);
    colnr = &COL_MAT_COLNR(0);
    value = &COL_MAT_VALUE(0);
    for(i = 0; i < nz;
        i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {
      rx = *rownr;
      cx = *colnr;
      wx = fabs(*value);
#ifdef CRASH_SIMPLESCALE
      if(wx < CRASH_THRESHOLD * colMAX[0]) {
        rowNZ[rx]--;
        colNZ[cx]--;
      }
#else
      if(wx < CRASH_THRESHOLD * rowMAX[rx])
        rowNZ[rx]--;
      if(wx < CRASH_THRESHOLD * colMAX[cx])
        colNZ[cx]--;
#endif
    }

    /* Set up priority tables */
    ok = allocINT(lp, &rowWT, lp->rows+1, TRUE);
    createLink(lp->rows,    &rowLL, NULL);
    ok &= (rowLL != NULL);
    if(!ok)
      goto Finish;
    for(i = 1; i <= lp->rows; i++) {
      if(get_constr_type(lp, i)==EQ)
        ii = 3;
      else if(lp->upbo[i] < lp->infinite)
        ii = 2;
      else if(fabs(lp->rhs[i]) < lp->infinite)
        ii = 1;
      else
        ii = 0;
      rowWT[i] = ii;
      if(ii > 0)
        appendLink(rowLL, i);
    }
    ok = allocINT(lp, &colWT, lp->columns+1, TRUE);
    createLink(lp->columns, &colLL, NULL);
    ok &= (colLL != NULL);
    if(!ok)
      goto Finish;
    for(i = 1; i <= lp->columns; i++) {
      ix = lp->rows+i;
      if(is_unbounded(lp, i))
        ii = 3;
      else if(lp->upbo[ix] >= lp->infinite)
        ii = 2;
      else if(fabs(lp->upbo[ix]-lp->lowbo[ix]) > lp->epsmachine)
        ii = 1;
      else
        ii = 0;
      colWT[i] = ii;
      if(ii > 0)
        appendLink(colLL, i);
    }

    /* Loop over all basis variables */
    for(i = 1; i <= lp->rows; i++) {

      /* Select row */
      rx = 0;
      wx = -lp->infinite;
      for(ii = firstActiveLink(rowLL); ii > 0; ii = nextActiveLink(rowLL, ii)) {
        tx = rowWT[ii] - CRASH_SPACER*rowNZ[ii];
        if(tx > wx) {
          rx = ii;
          wx = tx;
        }
      }
      if(rx == 0)
        break;
      removeLink(rowLL, rx);

      /* Select column */
      cx = 0;
      wx = -lp->infinite;
      for(ii = mat->row_end[rx-1]; ii < mat->row_end[rx]; ii++) {

        /* Update NZ column counts for row selected above */
        tx = fabs(ROW_MAT_VALUE(ii));
        ix = ROW_MAT_COLNR(ii);
#ifdef CRASH_SIMPLESCALE
        if(tx >= CRASH_THRESHOLD * colMAX[0])
#else
        if(tx >= CRASH_THRESHOLD * colMAX[ix])
#endif
          colNZ[ix]--;
        if(!isActiveLink(colLL, ix) || (tx < CRASH_THRESHOLD * rowMAX[rx]))
          continue;

        /* Now do the test for best pivot */
        tx = my_sign(lp->orig_obj[ix]) - my_sign(ROW_MAT_VALUE(ii));
        tx = colWT[ix] + CRASH_WEIGHT*tx - CRASH_SPACER*colNZ[ix];
        if(tx > wx) {
          cx = ix;
          wx = tx;
        }
      }
      if(cx == 0)
        break;
      removeLink(colLL, cx);

      /* Update row NZ counts */
      ii = mat->col_end[cx-1];
      rownr = &COL_MAT_ROWNR(ii);
      value = &COL_MAT_VALUE(ii);
      for(; ii < mat->col_end[cx];
          ii++, rownr += matRowColStep, value += matValueStep) {
        wx = fabs(*value);
        ix = *rownr;
#ifdef CRASH_SIMPLESCALE
        if(wx >= CRASH_THRESHOLD * colMAX[0])
#else
        if(wx >= CRASH_THRESHOLD * rowMAX[ix])
#endif
          rowNZ[ix]--;
      }

      /* Set new basis variable */
      set_basisvar(lp, rx, lp->rows+cx);
    }

    /* Clean up */
Finish:
    FREE(rowNZ);
    FREE(colNZ);
    FREE(rowMAX);
    FREE(colMAX);
    FREE(rowWT);
    FREE(colWT);
    freeLink(&rowLL);
    freeLink(&colLL);
  }

  /* Construct a basis that is in some measure the "least degenerate" */
  else if((lp->crashmode == CRASH_LEASTDEGENERATE) && mat_validate(mat)) {
    /* The logic here follows Maros */
    LLrec   *rowLL = NULL, *colLL = NULL;
    int     ii, rx, cx, ix, nz, *merit = NULL;
    REAL    *value, wx, hold, *rhs = NULL, *eta = NULL;
    int     *rownr, *colnr;

    report(lp, NORMAL, "crash_basis: 'Least degenerate' basis crashing selected\n");

    /* Create temporary arrays */
    ok = allocINT(lp,  &merit, lp->columns + 1, FALSE) &&
         allocREAL(lp, &eta, lp->rows + 1, FALSE) &&
         allocREAL(lp, &rhs, lp->rows + 1, FALSE);
    createLink(lp->columns, &colLL, NULL);
    createLink(lp->rows, &rowLL, NULL);
    ok &= (colLL != NULL) && (rowLL != NULL);
    if(!ok)
      goto FinishLD;
    MEMCOPY(rhs, lp->orig_rhs, lp->rows + 1);
    for(i = 1; i <= lp->columns; i++)
      appendLink(colLL, i);
    for(i = 1; i <= lp->rows; i++)
      appendLink(rowLL, i);

    /* Loop until we have found enough new bases */
    while(colLL->count > 0) {

      /* Tally non-zeros matching in RHS and each active column */
      nz = mat_nonzeros(mat);
      rownr = &COL_MAT_ROWNR(0);
      colnr = &COL_MAT_COLNR(0);
      ii = 0;
      MEMCLEAR(merit, lp->columns + 1);
      for(i = 0; i < nz;
          i++, rownr += matRowColStep, colnr += matRowColStep) {
        rx = *rownr;
        cx = *colnr;
        if(isActiveLink(colLL, cx) && (rhs[rx] != 0)) {
          merit[cx]++;
          ii++;
        }
      }
      if(ii == 0)
        break;

      /* Find maximal match; break ties with column length */
      i = firstActiveLink(colLL);
      cx = i;
      for(i = nextActiveLink(colLL, i); i != 0; i = nextActiveLink(colLL, i)) {
        if(merit[i] >= merit[cx]) {
          if((merit[i] > merit[cx]) || (mat_collength(mat, i) > mat_collength(mat, cx)))
            cx = i;
        }
      }

      /* Determine the best pivot row */
      i = mat->col_end[cx-1];
      nz = mat->col_end[cx];
      rownr = &COL_MAT_ROWNR(i);
      value = &COL_MAT_VALUE(i);
      rx = 0;
      wx = 0;
      MEMCLEAR(eta, lp->rows + 1);
      for(; i < nz;
          i++, rownr += matRowColStep, value += matValueStep) {
        ix = *rownr;
        hold = *value;
        eta[ix] = rhs[ix] / hold;
        hold = fabs(hold);
        if(isActiveLink(rowLL, ix) && (hold > wx)) {
          wx = hold;
          rx = ix;
        }
      }

      /* Set new basis variable */
      if(rx > 0) {

        /* We have to update the rhs vector for the implied transformation
          in order to be able to find the new RHS non-zero pattern */
        for(i = 1; i <= lp->rows; i++)
           rhs[i] -= wx * eta[i];
        rhs[rx] = wx;

        /* Do the exchange */
        set_basisvar(lp, rx, lp->rows+cx);
        removeLink(rowLL, rx);
      }
      removeLink(colLL, cx);

    }

    /* Clean up */
FinishLD:
    FREE(merit);
    FREE(rhs);
    freeLink(&rowLL);
    freeLink(&colLL);

  }
  return( ok );
}
Esempio n. 2
0
STATIC MYBOOL SOS_shift_col(SOSgroup *group, int sosindex, int column, int delta, LLrec *usedmap, MYBOOL forceresort)
/* Routine to adjust SOS indeces for variable insertions or deletions;
   Note: SOS_shift_col must be called before make_SOSchain! */
{
  int    i, ii, n, nn, nr;
  int    changed;
  int    *list;
  REAL   *weights;

#ifdef Paranoia
  lprec  *lp = group->lp;

  if((sosindex < 0) || (sosindex > group->sos_count)) {
    report(lp, IMPORTANT, "SOS_shift_col: Invalid SOS index %d\n", sosindex);
    return(FALSE);
  }
  else if((column < 1) || (delta == 0)) {
    report(lp, IMPORTANT, "SOS_shift_col: Invalid column %d specified with delta %d\n",
                          column, delta);
    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_shift_col(group, i, column, delta, usedmap, forceresort))
        return(FALSE);
    }
  }
  else {
    list = group->sos_list[sosindex-1]->members;
    weights = group->sos_list[sosindex-1]->weights;
    n = list[0];
    nn = list[n+1];

    /* Case where variable indeces are to be incremented */
    if(delta > 0) {
      for(i = 1; i <= n; i++) {
        if(list[i] >= column)
          list[i] += delta;
      }
    }
    /* Case where variables are to be deleted/indeces decremented */
    else {
      changed = 0;
      if(usedmap != NULL) {
        int *newidx = NULL;
        /* Defer creation of index mapper until we are sure that a
           member of this SOS is actually targeted for deletion */
        if(newidx == NULL) {
          allocINT(group->lp, &newidx, group->lp->columns+1, TRUE);
          for(i = firstActiveLink(usedmap), ii = 1; i != 0;
              i = nextActiveLink(usedmap, i), ii++)
            newidx[i] = ii;
        }
        for(i = 1, ii = 0; i <= n; i++) {
          nr = list[i];
          /* Check if this SOS variable should be deleted */
          if(!isActiveLink(usedmap, nr))
            continue;

          /* If the index is "high" then make adjustment and shift */
          changed++;
          ii++;
          list[ii] = newidx[nr];
          weights[ii] = weights[i];
        }
        FREE(newidx);
      }
      else
        for(i = 1, ii = 0; i <= n; i++) {
          nr = list[i];
          /* Check if this SOS variable should be deleted */
          if((nr >= column) && (nr < column-delta))
            continue;
          /* If the index is "high" then decrement */
          if(nr > column) {
            changed++;
            nr += delta;
          }
          ii++;
          list[ii] = nr;
          weights[ii] = weights[i];
        }
      /* Update the SOS length / type indicators */
      if(ii < n) {
        list[0] = ii;
        list[ii+1] = nn;
      }

     /* Update mapping arrays to search large SOS's faster */
      if(forceresort && ((ii < n) || (changed > 0)))
        SOS_member_sortlist(group, sosindex);
    }

  }
  return(TRUE);

}
Esempio n. 3
0
/* 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 );
}