/* Do a generic readable data dump of key lp_solve model variables; principally for run difference and debugging purposes */ MYBOOL REPORT_debugdump(lprec *lp, char *filename, MYBOOL livedata) { /* FILE *output = stdout; */ FILE *output; MYBOOL ok; ok = (MYBOOL) ((filename == NULL) || ((output = fopen(filename,"w")) != NULL)); if(!ok) return(ok); if((filename == NULL) && (lp->outstream != NULL)) output = lp->outstream; fprintf(output, "\nGENERAL INFORMATION\n-------------------\n\n"); fprintf(output, "Model size: %d rows (%d equalities, %d Lagrangean), %d columns (%d integers, %d SC, %d SOS, %d GUB)\n", lp->rows, lp->equalities, get_Lrows(lp), lp->columns, lp->int_vars, lp->sc_vars, SOS_count(lp), GUB_count(lp)); fprintf(output, "Data size: %d model non-zeros, %d invB non-zeros (engine is %s)\n", get_nonzeros(lp), my_if(lp->invB == NULL, 0, lp->bfp_nonzeros(lp, FALSE)), lp->bfp_name()); fprintf(output, "Internal sizes: %d rows allocated, %d columns allocated, %d columns used, %d eta length\n", lp->rows_alloc, lp->columns_alloc, lp->columns, my_if(lp->invB == NULL, 0, lp->bfp_colcount(lp))); fprintf(output, "Memory use: %d sparse matrix, %d eta\n", lp->matA->mat_alloc, my_if(lp->invB == NULL, 0, lp->bfp_memallocated(lp))); fprintf(output, "Parameters: Maximize=%d, Names used=%d, Scalingmode=%d, Presolve=%d, SimplexPivot=%d\n", is_maxim(lp), lp->names_used, lp->scalemode, lp->do_presolve, lp->piv_strategy); fprintf(output, "Precision: EpsValue=%g, EpsPrimal=%g, EpsDual=%g, EpsPivot=%g, EpsPerturb=%g\n", lp->epsvalue, lp->epsprimal, lp->epsdual, lp->epspivot, lp->epsperturb); fprintf(output, "Stability: AntiDegen=%d, Improvement=%d, Split variables at=%g\n", lp->improve, lp->anti_degen, lp->negrange); fprintf(output, "B&B settings: BB pivot rule=%d, BB branching=%s, BB strategy=%d, Integer precision=%g, MIP gaps=%g,%g\n", lp->bb_rule, my_boolstr(lp->bb_varbranch), lp->bb_floorfirst, lp->epsint, lp->mip_absgap, lp->mip_relgap); fprintf(output, "\nCORE DATA\n---------\n\n"); blockWriteINT(output, "Column starts", lp->matA->col_end, 0, lp->columns); blockWriteINT(output, "row_type", lp->row_type, 0, lp->rows); blockWriteREAL(output, "orig_rhs", lp->orig_rhs, 0, lp->rows); blockWriteREAL(output, "orig_lowbo", lp->orig_lowbo, 0, lp->sum); blockWriteREAL(output, "orig_upbo", lp->orig_upbo, 0, lp->sum); blockWriteINT(output, "row_type", lp->row_type, 0, lp->rows); blockWriteBOOL(output, "var_type", lp->var_type, 0, lp->columns, TRUE); blockWriteAMAT(output, "A", lp, 0, lp->rows); if(livedata) { fprintf(output, "\nPROCESS DATA\n------------\n\n"); blockWriteREAL(output, "Active rhs", lp->rhs, 0, lp->rows); blockWriteINT(output, "Basic variables", lp->var_basic, 0, lp->rows); blockWriteBOOL(output, "is_basic", lp->is_basic, 0, lp->sum, TRUE); blockWriteREAL(output, "lowbo", lp->lowbo, 0, lp->sum); blockWriteREAL(output, "upbo", lp->upbo, 0, lp->sum); if(lp->scalars != NULL) blockWriteREAL(output, "scalars", lp->scalars, 0, lp->sum); } if(filename != NULL) fclose(output); return(ok); }
STATIC MYBOOL scale_rows(lprec *lp, REAL *scaledelta) { int i, j, nz, colMax; REAL *scalechange; REAL *value; int *rownr; MATrec *mat = lp->matA; /* Check that rows are in fact targeted */ if((lp->scalemode & SCALE_COLSONLY) != 0) return( TRUE ); if(scaledelta == NULL) scalechange = lp->scalars; else scalechange = scaledelta; colMax = lp->columns; /* First row-scale the matrix (including the objective function) */ for(i = 1; i <= colMax; i++) { lp->orig_obj[i] *= scalechange[0]; } nz = get_nonzeros(lp); value = &(COL_MAT_VALUE(0)); rownr = &(COL_MAT_ROWNR(0)); for(i = 0; i < nz; i++, value += matValueStep, rownr += matRowColStep) { (*value) *= scalechange[*rownr]; } /* ...and scale the rhs and the row bounds (RANGES in MPS!!) */ for(i = 0; i <= lp->rows; i++) { if(fabs(lp->orig_rhs[i]) < lp->infinite) lp->orig_rhs[i] *= scalechange[i]; j = lp->presolve_undo->var_to_orig[i]; if(j != 0) lp->presolve_undo->fixed_rhs[j] *= scalechange[i]; if(lp->orig_upbo[i] < lp->infinite) /* This is the range */ lp->orig_upbo[i] *= scalechange[i]; if((lp->orig_lowbo[i] != 0) && (fabs(lp->orig_lowbo[i]) < lp->infinite)) lp->orig_lowbo[i] *= scalechange[i]; } set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE); return( TRUE ); }
void undoscale(lprec *lp) { int i, j, nz; MATrec *mat = lp->matA; REAL *value; int *rownr, *colnr; if(lp->scaling_used) { /* Unscale the OF */ for(j = 1; j <= lp->columns; j++) { lp->orig_obj[j] = unscaled_mat(lp, lp->orig_obj[j], 0, j); } /* Unscale the matrix */ mat_validate(mat); nz = get_nonzeros(lp); value = &(COL_MAT_VALUE(0)); rownr = &(COL_MAT_ROWNR(0)); colnr = &(COL_MAT_COLNR(0)); for(j = 0; j < nz; j++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) { *value = unscaled_mat(lp, *value, *rownr, *colnr); } /* Unscale variable bounds */ for(i = lp->rows + 1, j = 1; i <= lp->sum; i++, j++) { lp->orig_lowbo[i] = unscaled_value(lp, lp->orig_lowbo[i], i); lp->orig_upbo[i] = unscaled_value(lp, lp->orig_upbo[i], i); lp->sc_lobound[j] = unscaled_value(lp, lp->sc_lobound[j], i); } /* Unscale the rhs, upper and lower bounds... */ for(i = 0; i <= lp->rows; i++) { lp->orig_rhs[i] = unscaled_value(lp, lp->orig_rhs[i], i); j = lp->presolve_undo->var_to_orig[i]; if(j != 0) lp->presolve_undo->fixed_rhs[j] = unscaled_value(lp, lp->presolve_undo->fixed_rhs[j], i); lp->orig_lowbo[i] = unscaled_value(lp, lp->orig_lowbo[i], i); lp->orig_upbo[i] = unscaled_value(lp, lp->orig_upbo[i], i); } FREE(lp->scalars); lp->scaling_used = FALSE; lp->columns_scaled = FALSE; set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE); } }
STATIC MYBOOL scale_columns(lprec *lp, REAL *scaledelta) { int i,j, colMax, nz; REAL *scalechange; REAL *value; int *colnr; MATrec *mat = lp->matA; /* Check that columns are in fact targeted */ if((lp->scalemode & SCALE_ROWSONLY) != 0) return( TRUE ); if(scaledelta == NULL) scalechange = &lp->scalars[lp->rows]; else scalechange = &scaledelta[lp->rows]; colMax = lp->columns; /* Scale matrix entries (including any Lagrangean constraints) */ for(i = 1; i <= lp->columns; i++) { lp->orig_obj[i] *= scalechange[i]; } mat_validate(lp->matA); nz = get_nonzeros(lp); value = &(COL_MAT_VALUE(0)); colnr = &(COL_MAT_COLNR(0)); for(i = 0; i < nz; i++, value += matValueStep, colnr += matRowColStep) { (*value) *= scalechange[*colnr]; } /* Scale variable bounds as well */ for(i = 1, j = lp->rows + 1; j <= lp->sum; i++, j++) { if(lp->orig_lowbo[j] > -lp->infinite) lp->orig_lowbo[j] /= scalechange[i]; if(lp->orig_upbo[j] < lp->infinite) lp->orig_upbo[j] /= scalechange[i]; if(lp->sc_lobound[i] != 0) lp->sc_lobound[i] /= scalechange[i]; } lp->columns_scaled = TRUE; set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE); return( TRUE ); }
void REPORT_modelinfo(lprec *lp, MYBOOL doName, char *datainfo) { if(doName) { report(lp, NORMAL, "\nModel name: '%s' - run #%-5d\n", get_lp_name(lp), lp->solvecount); report(lp, NORMAL, "Objective: %simize(%s)\n", my_if(is_maxim(lp), "Max", "Min"), get_row_name(lp, 0)); report(lp, NORMAL, " \n"); } if(datainfo != NULL) report(lp, NORMAL, "%s\n", datainfo); report(lp, NORMAL, "Model size: %7d constraints, %7d variables, %12d non-zeros.\n", lp->rows, lp->columns, get_nonzeros(lp)); if(GUB_count(lp)+SOS_count(lp) > 0) report(lp, NORMAL, "Var-types: %7d integer, %7d semi-cont., %7d SOS.\n", lp->int_vars, lp->sc_vars, lp->sos_vars); report(lp, NORMAL, "Sets: %7d GUB, %7d SOS.\n", GUB_count(lp), SOS_count(lp)); }
STATIC void unscale_columns(lprec *lp) { int i, j, nz; MATrec *mat = lp->matA; REAL *value; int *rownr, *colnr; if(!lp->columns_scaled) return; /* Unscale OF */ for(j = 1; j <= lp->columns; j++) { lp->orig_obj[j] = unscaled_mat(lp, lp->orig_obj[j], 0, j); } /* Unscale mat */ mat_validate(mat); nz = get_nonzeros(lp); value = &(COL_MAT_VALUE(0)); rownr = &(COL_MAT_ROWNR(0)); colnr = &(COL_MAT_COLNR(0)); for(j = 0; j < nz; j++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) { *value = unscaled_mat(lp, *value, *rownr, *colnr); } /* Unscale bounds as well */ for(i = lp->rows + 1, j = 1; i <= lp->sum; i++, j++) { lp->orig_lowbo[i] = unscaled_value(lp, lp->orig_lowbo[i], i); lp->orig_upbo[i] = unscaled_value(lp, lp->orig_upbo[i], i); lp->sc_lobound[j] = unscaled_value(lp, lp->sc_lobound[j], i); } for(i = lp->rows + 1; i<= lp->sum; i++) lp->scalars[i] = 1; lp->columns_scaled = FALSE; set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE); }
/* Compute the scale factor by the formulae: FALSE: SUM (log |Aij|) ^ 2 TRUE: SUM (log |Aij| - RowScale[i] - ColScale[j]) ^ 2 */ REAL CurtisReidMeasure(lprec *lp, MYBOOL _Advanced, REAL *FRowScale, REAL *FColScale) { int i, nz; REAL absvalue, logvalue; register REAL result; MATrec *mat = lp->matA; REAL *value; int *rownr, *colnr; /* Do OF part */ result = 0; for(i = 1; i <= lp->columns; i++) { absvalue = fabs(lp->orig_obj[i]); if(absvalue > 0) { logvalue = log(absvalue); if(_Advanced) logvalue -= FRowScale[0] + FColScale[i]; result += logvalue*logvalue; } } /* Do constraint matrix part */ mat_validate(mat); value = &(COL_MAT_VALUE(0)); rownr = &(COL_MAT_ROWNR(0)); colnr = &(COL_MAT_COLNR(0)); nz = get_nonzeros(lp); for(i = 0; i < nz; i++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) { absvalue = fabs(*value); if(absvalue > 0) { logvalue = log(absvalue); if(_Advanced) logvalue -= FRowScale[*rownr] + FColScale[*colnr]; result += logvalue*logvalue; } } return( result ); }
static void print_statistics(lprec *lp) { REAL *col, *RHSmin, *RHSmax, *OBJmin, *OBJmax, *MATmin, *MATmax; int *nz, ret, m, n, i, j, k, l, nRHSmin = 0, nRHSmax = 0, nOBJmin = 0, nOBJmax = 0, nMATmin = 0, nMATmax = 0, *rowRHSmin, *rowRHSmax, *colOBJmin, *colOBJmax, *rowMATmin, *rowMATmax, *colMATmin, *colMATmax; m = get_Nrows(lp); n = get_Ncolumns(lp); col = (REAL *) malloc((1 + m) * sizeof(*col)); nz = (int *) malloc((1 + m) * sizeof(*RHSmin)); RHSmin = (REAL *) malloc(nstats * sizeof(*RHSmin)); RHSmax = (REAL *) malloc(nstats * sizeof(*RHSmax)); rowRHSmin = (int *) malloc(nstats * sizeof(*RHSmin)); rowRHSmax = (int *) malloc(nstats * sizeof(*RHSmax)); OBJmin = (REAL *) malloc(nstats * sizeof(*OBJmin)); OBJmax = (REAL *) malloc(nstats * sizeof(*OBJmax)); colOBJmin = (int *) malloc(nstats * sizeof(*colOBJmin)); colOBJmax = (int *) malloc(nstats * sizeof(*colOBJmax)); MATmin = (REAL *) malloc(nstats * sizeof(*MATmin)); MATmax = (REAL *) malloc(nstats * sizeof(*MATmax)); rowMATmin = (int *) malloc(nstats * sizeof(*rowMATmin)); rowMATmax = (int *) malloc(nstats * sizeof(*rowMATmax)); colMATmin = (int *) malloc(nstats * sizeof(*colMATmin)); colMATmax = (int *) malloc(nstats * sizeof(*colMATmax)); /* minmax(2.0, MATmin, MATmax, &nMATmin, &nMATmax, 1, rowMATmin, rowMATmax, 8, colMATmin, colMATmax); minmax(1.0, MATmin, MATmax, &nMATmin, &nMATmax, 2, rowMATmin, rowMATmax, 7, colMATmin, colMATmax); minmax(1.5, MATmin, MATmax, &nMATmin, &nMATmax, 3, rowMATmin, rowMATmax, 6, colMATmin, colMATmax); minmax(3.0, MATmin, MATmax, &nMATmin, &nMATmax, 4, rowMATmin, rowMATmax, 5, colMATmin, colMATmax); minmax(4.0, MATmin, MATmax, &nMATmin, &nMATmax, 5, rowMATmin, rowMATmax, 4, colMATmin, colMATmax); minmax(0.1, MATmin, MATmax, &nMATmin, &nMATmax, 6, rowMATmin, rowMATmax, 3, colMATmin, colMATmax); minmax(5.0, MATmin, MATmax, &nMATmin, &nMATmax, 7, rowMATmin, rowMATmax, 2, colMATmin, colMATmax); minmax(1.4, MATmin, MATmax, &nMATmin, &nMATmax, 8, rowMATmin, rowMATmax, 1, colMATmin, colMATmax); printminmax(MATmin, MATmax, nMATmin, nMATmax, rowMATmin, rowMATmax, colMATmin, colMATmax); */ for (i = 1; i <= m; i++) minmax(get_rh(lp, i), RHSmin, RHSmax, &nRHSmin, &nRHSmax, i, rowRHSmin, rowRHSmax, 0, NULL, NULL); for (j = 1; j <= n; j++) { ret = get_columnex(lp, j, col, nz); for (i = 0; i < ret; i++) if (nz[i] == 0) minmax(col[i], OBJmin, OBJmax, &nOBJmin, &nOBJmax, 0, NULL, NULL, j, colOBJmin, colOBJmax); else minmax(col[i], MATmin, MATmax, &nMATmin, &nMATmax, nz[i], rowMATmin, rowMATmax, j, colMATmin, colMATmax); } printf("Constraints: %d\n", get_Nrows(lp)); printf("Variables : %d\n", get_Ncolumns(lp)); for (j = k = l = 0, i = n; i >= 1; i--) { if (is_int(lp, i)) j++; if (is_semicont(lp, i)) k++; if (is_SOS_var(lp, i)) l++; } printf("Integers : %d\n", j); printf("Semi-cont : %d\n", k); printf("SOS : %d\n", l); k = get_nonzeros(lp); printf("Non-zeros : %d\tdensity=%f%%\n", k, ((double) k) / (((double) m) * ((double) n)) * 100.0); printf("\nAbsolute Ranges:\n\n Minima Maxima\n"); printf("\nMatrix Coeficients:\n"); printminmax(lp, "A", MATmin, MATmax, nMATmin, nMATmax, rowMATmin, rowMATmax, colMATmin, colMATmax); printf("\nObj. Vector:\n"); printminmax(lp, "c", OBJmin, OBJmax, nOBJmin, nOBJmax, NULL, NULL, colOBJmin, colOBJmax); printf("\nRHS Vector:\n"); printminmax(lp, "b", RHSmin, RHSmax, nRHSmin, nRHSmax, rowRHSmin, rowRHSmax, NULL, NULL); free(col); free(nz); free(RHSmin); free(RHSmax); free(rowRHSmin); free(rowRHSmax); free(OBJmin); free(OBJmax); free(colOBJmin); free(colOBJmax); free(MATmin); free(MATmax); free(rowMATmin); free(rowMATmax); free(colMATmin); free(colMATmax); }
MYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector) { MYBOOL *isnz = NULL, status = FALSE; REAL *values = NULL, *violation = NULL, eps = lp->epsprimal, *value, error, upB, loB, sortorder = -1.0; int i, j, jj, n, *rownr, *colnr, *slkpos = NULL, nrows = lp->rows, ncols = lp->columns, nsum = lp->sum; int *basisnr; MATrec *mat = lp->matA; if(!mat_validate(mat)) return( status ); /* Create helper arrays, providing for multiple use of the violation array */ if(!allocREAL(lp, &values, nsum+1, TRUE) || !allocREAL(lp, &violation, nsum+1, TRUE)) goto Finish; /* Compute the values of the constraints for the given guess vector */ i = 0; n = get_nonzeros(lp); rownr = &COL_MAT_ROWNR(i); colnr = &COL_MAT_COLNR(i); value = &COL_MAT_VALUE(i); for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) * guessvector[*colnr]; MEMMOVE(values+nrows+1, guessvector+1, ncols); /* Initialize bound "violation" or primal non-degeneracy measures, expressed as the absolute value of the differences from the closest bound. */ for(i = 1; i <= nsum; i++) { if(i <= nrows) { loB = get_rh_lower(lp, i); upB = get_rh_upper(lp, i); } else { loB = get_lowbo(lp, i-nrows); upB = get_upbo(lp, i-nrows); } /* Free constraints/variables */ if(my_infinite(lp, loB) && my_infinite(lp, upB)) error = 0; /* Violated constraints/variable bounds */ else if(values[i]+eps < loB) error = loB-values[i]; else if(values[i]-eps > upB) error = values[i]-upB; /* Non-violated constraints/variables bounds */ else if(my_infinite(lp, upB)) error = MAX(0, values[i]-loB); else if(my_infinite(lp, loB)) error = MAX(0, upB-values[i]); else error = MIN(upB-values[i], values[i]-loB); /* MAX(upB-values[i], values[i]-loB); */ if(error != 0) violation[i] = sortorder*error; basisvector[i] = i; } /* Sort decending , meaning that variables with the largest "violations" will be designated basic. Effectively, we are performing a greedy type algorithm, but start at the "least interesting" end. */ sortByREAL(basisvector, violation, nsum, 1, FALSE); error = violation[1]; /* Used for setting the return value */ /* Let us check for obvious row singularities and try to fix these. Note that we reuse the memory allocated to the violation array. First assemble necessary basis statistics... */ slkpos = (int *) violation; n = nrows+1; MEMCLEAR(slkpos, n); isnz = (MYBOOL *) (slkpos+n+1); MEMCLEAR(isnz, n); for(i = 1; i <= nrows; i++) { j = abs(basisvector[i]); if(j <= nrows) { isnz[j] = TRUE; slkpos[j] = i; } else { j-= nrows; jj = mat->col_end[j-1]; jj = COL_MAT_ROWNR(jj); isnz[jj] = TRUE; } } for(; i <= nsum; i++) { j = abs(basisvector[i]); if(j <= nrows) slkpos[j] = i; } /* ...then set the corresponding slacks basic for row rank deficient positions */ for(j = 1; j <= nrows; j++) { if(slkpos[j] == 0) report(lp, SEVERE, "guess_basis: Internal error"); if(!isnz[j]) { isnz[j] = TRUE; i = slkpos[j]; swapINT(&basisvector[i], &basisvector[j]); basisvector[j] = abs(basisvector[j]); } } /* Adjust the non-basic indeces for the (proximal) bound state */ for(i = nrows+1, basisnr = basisvector+i; i <= nsum; i++, basisnr++) { n = *basisnr; if(n <= nrows) { values[n] -= get_rh_lower(lp, n); if(values[n] <= eps) *basisnr = -(*basisnr); } else if(values[n]-eps <= get_lowbo(lp, n-nrows)) *basisnr = -(*basisnr); } /* Lastly normalize all basic variables to be coded as lower-bounded, or effectively zero-based in the case of free variables. */ for(i = 1; i <= nrows; i++) basisvector[i] = -abs(basisvector[i]); /* Clean up and return status */ status = (MYBOOL) (error <= eps); Finish: FREE(values); FREE(violation); return( status ); }
MYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector) { MYBOOL *isnz, status = FALSE; REAL *values = NULL, *violation = NULL, eps = lp->epsprimal, *value, error, upB, loB, sortorder = 1.0; int i, j, jj, n, *rownr, *colnr, *slkpos, nrows = lp->rows, ncols = lp->columns; MATrec *mat = lp->matA; if(!mat_validate(mat)) return( status ); /* Create helper arrays */ if(!allocREAL(lp, &values, lp->sum+1, TRUE) || !allocREAL(lp, &violation, lp->sum+1, TRUE)) goto Finish; /* Compute values of slack variables for given guess vector */ i = 0; n = get_nonzeros(lp); rownr = &COL_MAT_ROWNR(i); colnr = &COL_MAT_COLNR(i); value = &COL_MAT_VALUE(i); for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) * guessvector[*colnr]; MEMMOVE(values+nrows+1, guessvector+1, ncols); /* Initialize constraint bound violation measures (expressed as positive values) */ for(i = 1; i <= nrows; i++) { upB = get_rh_upper(lp, i); loB = get_rh_lower(lp, i); error = values[i] - upB; if(error > -eps) violation[i] = sortorder*MAX(0,error); else { error = loB - values[i]; if(error > -eps) violation[i] = sortorder*MAX(0,error); else if(my_infinite(lp, loB) && my_infinite(lp, upB)) ; else if(my_infinite(lp, upB)) violation[i] = sortorder*(loB - values[i]); else if(my_infinite(lp, loB)) violation[i] = sortorder*(values[i] - upB); else violation[i] = -sortorder*MAX(upB - values[i], values[i] - loB); } basisvector[i] = i; } /* Initialize user variable bound violation measures (expressed as positive values) */ for(i = 1; i <= ncols; i++) { n = nrows+i; upB = get_upbo(lp, i); loB = get_lowbo(lp, i); error = guessvector[i] - upB; if(error > -eps) violation[n] = sortorder*MAX(0,error); else { error = loB - values[n]; if(error > -eps) violation[n] = sortorder*MAX(0,error); else if(my_infinite(lp, loB) && my_infinite(lp, upB)) ; else if(my_infinite(lp, upB)) violation[n] = sortorder*(loB - values[n]); else if(my_infinite(lp, loB)) violation[n] = sortorder*(values[n] - upB); else violation[n] = -sortorder*MAX(upB - values[n], values[n] - loB); } basisvector[n] = n; } /* Sort decending by violation; this means that variables with the largest violations will be designated as basic */ sortByREAL(basisvector, violation, lp->sum, 1, FALSE); error = violation[1]; /* Adjust the non-basic indeces for the (proximal) bound state */ for(i = nrows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) { if(*rownr <= nrows) { values[*rownr] -= lp->orig_rhs[*rownr]; if(values[*rownr] <= eps) *rownr = -(*rownr); } else if(values[i] <= get_lowbo(lp, (*rownr)-nrows)+eps) *rownr = -(*rownr); } /* Let us check for obvious row singularities and try to fix these; First assemble necessary basis statistics... */ isnz = (MYBOOL *) values; MEMCLEAR(isnz, nrows+1); slkpos = (int *) violation; MEMCLEAR(slkpos, nrows+1); for(i = 1; i <= nrows; i++) { j = abs(basisvector[i]); if(j <= nrows) { isnz[j] = TRUE; slkpos[j] = i; } else { j-= nrows; jj = mat->col_end[j-1]; isnz[COL_MAT_ROWNR(jj)] = TRUE; /* if(++jj < mat->col_end[j]) isnz[COL_MAT_ROWNR(jj)] = TRUE; */ } } for(; i <= lp->sum; i++) { j = abs(basisvector[i]); if(j <= nrows) slkpos[j] = i; } /* ...then set the corresponding slacks basic for row rank deficient positions */ for(j = 1; j <= nrows; j++) { #ifdef Paranoia if(slkpos[j] == 0) report(lp, SEVERE, "guess_basis: Internal error"); #endif if(!isnz[j]) { isnz[j] = TRUE; i = slkpos[j]; swapINT(&basisvector[i], &basisvector[j]); basisvector[j] = abs(basisvector[j]); } } /* Lastly normalize all basic variables to be coded as lower-bounded */ for(i = 1; i <= nrows; i++) basisvector[i] = -abs(basisvector[i]); /* Clean up and return status */ status = (MYBOOL) (error <= eps); Finish: FREE(values); FREE(violation); return( status ); }
MYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector) { MYBOOL status = FALSE; REAL *values = NULL, *violation = NULL, *value, error, upB, loB, sortorder = 1.0; int i, n, *rownr, *colnr; MATrec *mat = lp->matA; if(!mat_validate(lp->matA)) return( status ); /* Create helper arrays */ if(!allocREAL(lp, &values, lp->sum+1, TRUE) || !allocREAL(lp, &violation, lp->sum+1, TRUE)) goto Finish; /* Compute values of slack variables for given guess vector */ i = 0; n = get_nonzeros(lp); rownr = &COL_MAT_ROWNR(i); colnr = &COL_MAT_COLNR(i); value = &COL_MAT_VALUE(i); for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) * guessvector[*colnr]; MEMMOVE(values+lp->rows+1, guessvector+1, lp->columns); /* Initialize constraint bound violation measures */ for(i = 1; i <= lp->rows; i++) { upB = get_rh_upper(lp, i); loB = get_rh_lower(lp, i); error = values[i] - upB; if(error > lp->epsprimal) violation[i] = sortorder*error; else { error = loB - values[i]; if(error > lp->epsprimal) violation[i] = sortorder*error; else if(is_infinite(lp, loB) && is_infinite(lp, upB)) ; else if(is_infinite(lp, upB)) violation[i] = sortorder*(loB - values[i]); else if(is_infinite(lp, loB)) violation[i] = sortorder*(values[i] - upB); else violation[i] = - sortorder*MAX(upB - values[i], values[i] - loB); } basisvector[i] = i; } /* Initialize user variable bound violation measures */ for(i = 1; i <= lp->columns; i++) { n = lp->rows+i; upB = get_upbo(lp, i); loB = get_lowbo(lp, i); error = guessvector[i] - upB; if(error > lp->epsprimal) violation[n] = sortorder*error; else { error = loB - values[n]; if(error > lp->epsprimal) violation[n] = sortorder*error; else if(is_infinite(lp, loB) && is_infinite(lp, upB)) ; else if(is_infinite(lp, upB)) violation[n] = sortorder*(loB - values[n]); else if(is_infinite(lp, loB)) violation[n] = sortorder*(values[n] - upB); else violation[n] = - sortorder*MAX(upB - values[n], values[n] - loB); } basisvector[n] = n; } /* Sort decending by violation; this means that variables with the largest violations will be designated as basic */ sortByREAL(basisvector, violation, lp->sum, 1, FALSE); /* Adjust the non-basic indeces for the (proximal) bound state */ error = lp->epsprimal; for(i = lp->rows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) { if(*rownr <= lp->rows) { if(values[*rownr] <= get_rh_lower(lp, *rownr)+error) *rownr = -(*rownr); } else if(values[i] <= get_lowbo(lp, (*rownr)-lp->rows)+error) *rownr = -(*rownr); } /* Clean up and return status */ status = (MYBOOL) (violation[1] == 0); Finish: FREE(values); FREE(violation); return( status ); }
int CurtisReidScales(lprec *lp, MYBOOL _Advanced, REAL *FRowScale, REAL *FColScale) { int i, row, col, ent, nz; REAL *RowScalem2, *ColScalem2, *RowSum, *ColSum, *residual_even, *residual_odd; REAL sk, qk, ek, skm1, qkm1, ekm1, qkm2, qkqkm1, ekm2, ekekm1, absvalue, logvalue, StopTolerance; int *RowCount, *ColCount, colMax; int Result; MATrec *mat = lp->matA; REAL *value; int *rownr, *colnr; if(CurtisReidMeasure(lp, _Advanced, FRowScale, FColScale)<0.1*get_nonzeros(lp)) return(0); /* Allocate temporary memory and find RowSum and ColSum measures */ nz = get_nonzeros(lp); colMax = lp->columns; allocREAL(lp, &RowSum, lp->rows+1, TRUE); allocINT(lp, &RowCount, lp->rows+1, TRUE); allocREAL(lp, &residual_odd, lp->rows+1, TRUE); allocREAL(lp, &ColSum, colMax+1, TRUE); allocINT(lp, &ColCount, colMax+1, TRUE); allocREAL(lp, &residual_even, colMax+1, TRUE); allocREAL(lp, &RowScalem2, lp->rows+1, FALSE); allocREAL(lp, &ColScalem2, colMax+1, FALSE); /* Set origin for row scaling */ for(i = 1; i <= colMax; i++) { absvalue=fabs(lp->orig_obj[i]); if(absvalue>0) { logvalue = log(absvalue); ColSum[i] += logvalue; RowSum[0] += logvalue; ColCount[i]++; RowCount[0]++; } } value = &(COL_MAT_VALUE(0)); rownr = &(COL_MAT_ROWNR(0)); colnr = &(COL_MAT_COLNR(0)); for(i = 0; i < nz; i++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) { absvalue=fabs(*value); if(absvalue>0) { logvalue = log(absvalue); ColSum[*colnr] += logvalue; RowSum[*rownr] += logvalue; ColCount[*colnr]++; RowCount[*rownr]++; } } /* Make sure we dont't have division by zero errors */ for(row = 0; row <= lp->rows; row++) if(RowCount[row] == 0) RowCount[row] = 1; for(col = 1; col <= colMax; col++) if(ColCount[col] == 0) ColCount[col] = 1; /* Initialize to RowScale = RowCount-1 RowSum ColScale = 0.0 residual = ColSum - ET RowCount-1 RowSum */ StopTolerance= MAX(lp->scalelimit-floor(lp->scalelimit), DEF_SCALINGEPS); StopTolerance *= (REAL) nz; for(row = 0; row <= lp->rows; row++) { FRowScale[row] = RowSum[row] / (REAL) RowCount[row]; RowScalem2[row] = FRowScale[row]; } /* Compute initial residual */ for(col = 1; col <= colMax; col++) { FColScale[col] = 0; ColScalem2[col] = 0; residual_even[col] = ColSum[col]; if(lp->orig_obj[col] != 0) residual_even[col] -= RowSum[0] / (REAL) RowCount[0]; i = mat->col_end[col-1]; rownr = &(COL_MAT_ROWNR(i)); ent = mat->col_end[col]; for(; i < ent; i++, rownr += matRowColStep) { residual_even[col] -= RowSum[*rownr] / (REAL) RowCount[*rownr]; } } /* Compute sk */ sk = 0; skm1 = 0; for(col = 1; col <= colMax; col++) sk += (residual_even[col]*residual_even[col]) / (REAL) ColCount[col]; Result = 0; qk=1; qkm1=0; qkm2=0; ek=0; ekm1=0; ekm2=0; while(sk>StopTolerance) { /* Given the values of residual and sk, construct ColScale (when pass is even) RowScale (when pass is odd) */ qkqkm1 = qk * qkm1; ekekm1 = ek * ekm1; if((Result % 2) == 0) { /* pass is even; construct RowScale[pass+1] */ if(Result != 0) { for(row = 0; row <= lp->rows; row++) RowScalem2[row] = FRowScale[row]; if(qkqkm1 != 0) { for(row = 0; row <= lp->rows; row++) FRowScale[row]*=(1 + ekekm1 / qkqkm1); for(row = 0; row<=lp->rows; row++) FRowScale[row]+=(residual_odd[row] / (qkqkm1 * (REAL) RowCount[row]) - RowScalem2[row] * ekekm1 / qkqkm1); } } } else { /* pass is odd; construct ColScale[pass+1] */ for(col = 1; col <= colMax; col++) ColScalem2[col] = FColScale[col]; if(qkqkm1 != 0) { for(col = 1; col <= colMax; col++) FColScale[col] *= (1 + ekekm1 / qkqkm1); for(col = 1; col <= colMax; col++) FColScale[col] += (residual_even[col] / ((REAL) ColCount[col] * qkqkm1) - ColScalem2[col] * ekekm1 / qkqkm1); } } /* update residual and sk (pass + 1) */ if((Result % 2) == 0) { /* even */ /* residual */ for(row = 0; row <= lp->rows; row++) residual_odd[row] *= ek; for(i = 1; i <= colMax; i++) if(lp->orig_obj[i] != 0) residual_odd[0] += (residual_even[i] / (REAL) ColCount[i]); rownr = &(COL_MAT_ROWNR(0)); colnr = &(COL_MAT_COLNR(0)); for(i = 0; i < nz; i++, rownr += matRowColStep, colnr += matRowColStep) { residual_odd[*rownr] += (residual_even[*colnr] / (REAL) ColCount[*colnr]); } for(row = 0; row <= lp->rows; row++) residual_odd[row] *= (-1 / qk); /* sk */ skm1 = sk; sk = 0; for(row = 0; row <= lp->rows; row++) sk += (residual_odd[row]*residual_odd[row]) / (REAL) RowCount[row]; } else { /* odd */ /* residual */ for(col = 1; col <= colMax; col++) residual_even[col] *= ek; for(i = 1; i <= colMax; i++) if(lp->orig_obj[i] != 0) residual_even[i] += (residual_odd[0] / (REAL) RowCount[0]); rownr = &(COL_MAT_ROWNR(0)); colnr = &(COL_MAT_COLNR(0)); for(i = 0; i < nz; i++, rownr += matRowColStep, colnr += matRowColStep) { residual_even[*colnr] += (residual_odd[*rownr] / (REAL) RowCount[*rownr]); } for(col = 1; col <= colMax; col++) residual_even[col] *= (-1 / qk); /* sk */ skm1 = sk; sk = 0; for(col = 1; col <= colMax; col++) sk += (residual_even[col]*residual_even[col]) / (REAL) ColCount[col]; } /* Compute ek and qk */ ekm2=ekm1; ekm1=ek; ek=qk * sk / skm1; qkm2=qkm1; qkm1=qk; qk=1-ek; Result++; } /* Synchronize the RowScale and ColScale vectors */ ekekm1 = ek * ekm1; if(qkm1 != 0) { if((Result % 2) == 0) { /* pass is even, compute RowScale */ for(row = 0; row<=lp->rows; row++) FRowScale[row]*=(1.0 + ekekm1 / qkm1); for(row = 0; row<=lp->rows; row++) FRowScale[row]+=(residual_odd[row] / (qkm1 * (REAL) RowCount[row]) - RowScalem2[row] * ekekm1 / qkm1); } else { /* pass is odd, compute ColScale */ for(col=1; col<=colMax; col++) FColScale[col]*=(1 + ekekm1 / qkm1); for(col=1; col<=colMax; col++) FColScale[col]+=(residual_even[col] / ((REAL) ColCount[col] * qkm1) - ColScalem2[col] * ekekm1 / qkm1); } } /* Do validation, if indicated */ if(FALSE && mat_validate(mat)){ double check, error; /* CHECK: M RowScale + E ColScale = RowSum */ error = 0; for(row = 0; row <= lp->rows; row++) { check = (REAL) RowCount[row] * FRowScale[row]; if(row == 0) { for(i = 1; i <= colMax; i++) { if(lp->orig_obj[i] != 0) check += FColScale[i]; } } else { i = mat->row_end[row-1]; ent = mat->row_end[row]; for(; i < ent; i++) { col = ROW_MAT_COLNR(i); check += FColScale[col]; } } check -= RowSum[row]; error += check*check; } /* CHECK: E^T RowScale + N ColScale = ColSum */ error = 0; for(col = 1; col <= colMax; col++) { check = (REAL) ColCount[col] * FColScale[col]; if(lp->orig_obj[col] != 0) check += FRowScale[0]; i = mat->col_end[col-1]; ent = mat->col_end[col]; rownr = &(COL_MAT_ROWNR(i)); for(; i < ent; i++, rownr += matRowColStep) { check += FRowScale[*rownr]; } check -= ColSum[col]; error += check*check; } } /* Convert to scaling factors (rounding to nearest power of 2 can optionally be done as a separate step later) */ for(col = 1; col <= colMax; col++) { absvalue = exp(-FColScale[col]); if(absvalue < MIN_SCALAR) absvalue = MIN_SCALAR; if(absvalue > MAX_SCALAR) absvalue = MAX_SCALAR; if(!is_int(lp,col) || is_integerscaling(lp)) FColScale[col] = absvalue; else FColScale[col] = 1; } for(row = 0; row <= lp->rows; row++) { absvalue = exp(-FRowScale[row]); if(absvalue < MIN_SCALAR) absvalue = MIN_SCALAR; if(absvalue > MAX_SCALAR) absvalue = MAX_SCALAR; FRowScale[row] = absvalue; } /* free temporary memory */ FREE(RowSum); FREE(ColSum); FREE(RowCount); FREE(ColCount); FREE(residual_even); FREE(residual_odd); FREE(RowScalem2); FREE(ColScalem2); return(Result); }