/* This is -*- C -*- code ! */ /* ************************************************************ file 'mip.c' utility functions for MIP related routines Copyright 2004/01 Joao Pedro Pedroso, DCC-FC and LIACC Universidade do Porto, Portugal http://www.ncc.up.pt/~jpp/mipts/mip.c ************************************************************ */ #include "mip.h" #define LOG 0 // whether to display verbose output or not // // evaluate infeasibilities // (stolen from glpk internal code) // double eval_lp_sum(LPX *lp) { int m, n, i, j, k, type; double lb, ub, x, sum; m = lpx_get_num_rows(lp); n = lpx_get_num_cols(lp); sum = 0.0; for (k = 1; k <= m+n; k++) { if (k <= m) { i = k; lpx_get_row_bnds(lp, i, &type, &lb, &ub); x = lpx_get_row_prim(lp, i); } else { j = k - m; lpx_get_col_bnds(lp, j, &type, &lb, &ub); x = lpx_get_col_prim(lp, j); } switch (type) { case LPX_FR: break; case LPX_LO: if (x < lb) sum += lb - x; break; case LPX_UP: if (x > ub) sum += x - ub; break; case LPX_DB: case LPX_FX: if (x < lb) sum += lb - x; if (x > ub) sum += x - ub; break; default: assert(type != type); } } return sum; } void solvelp(LPPROB *prob, double *z, double *zeta) { // this LP evaluation version is nice, as it does not require // artificial variables. // however, it has some problems: the same (infeasible) // fixed variables may stop in different values of the // violation/objective, depending on the starting solution lpx_simplex(prob->lp); *z=lpx_get_obj_val(prob->lp); int status = lpx_get_status(prob->lp); if (status == LPX_OPT) // to avoid avoid precision problems *zeta = 0.; else if (status == LPX_NOFEAS) { *zeta = eval_lp_sum(prob->lp); } else { // the status is LPX_UNDEF // likely, there are no free variables printf("warning: lp solution with undefined status %d\n", status); assert(status == LPX_UNDEF); *zeta = eval_lp_sum(prob->lp); } if (0) { // (LOG) int j; for (j=0;jnints;j++) { printf("%d: %f <= %f <= %f\n", j, lpx_get_col_lb(prob->lp, prob->lpi[j]), lpx_get_col_prim(prob->lp, prob->lpi[j]), lpx_get_col_ub(prob->lp, prob->lpi[j])); } printf("solvelp: z=%lf, zeta=%lf\n", *z, *zeta); } return; } // // initialize problem's data // void initprob(char *modfile, char *datfile, LPPROB *prob) { // read problem from files if (strstr(modfile, ".mps") != NULL) prob->lp = lpx_read_mps(modfile); else if (strstr(modfile, ".mod") != NULL) prob->lp = lpx_read_model(modfile,datfile,NULL); else if (strstr(modfile, ".lp") != NULL) /* for version 4.7 use prob->lp = lpx_read_cpxlp(modfile); */ prob->lp = lpx_read_cpxlp(modfile); else { fprintf(stderr, "unkown input format, file %s", modfile); exit(-1); } lpx_set_int_parm(prob->lp, LPX_K_MSGLEV, 0); // silent /verbose modes lpx_set_int_parm(prob->lp, LPX_K_DUAL, 1); // use dual simplex if sol is dual feasible prob->nints = lpx_get_num_int(prob->lp); prob->nvars = lpx_get_num_cols(prob->lp); prob->ncons = lpx_get_num_rows(prob->lp); int j, n=0; prob->idx = (int *) malloc(sizeof(int) * (lpx_get_num_cols(prob->lp)+1)); prob->lpi = (int *) malloc(sizeof(int) * prob->nints); prob->lb = (int *) malloc(sizeof(int) * prob->nints); prob->ub = (int *) malloc(sizeof(int) * prob->nints); for (j=1; j<=prob->nvars; j++) { if (lpx_get_col_kind(prob->lp, j) == LPX_IV) { if (lpx_get_col_type(prob->lp, j) != LPX_DB) { printf("cannot handle integer variable without double bounds\n"); exit(-1); } prob->idx[j] = n; prob->lpi[n] = j; prob->lb[n] = lround(lpx_get_col_lb(prob->lp, j)); prob->ub[n] = lround(lpx_get_col_ub(prob->lp, j)); n++; } } assert(n == prob->nints); } void delprob(LPPROB *prob) { free(prob->idx); free(prob->lpi); free(prob->lb ); free(prob->ub ); lpx_delete_prob(prob->lp); free(prob); } void update_sol(LPPROB *prob, int x[], double *z, double *zeta, int xnew[], double znew, double zetanew) { *z = znew; *zeta = zetanew; int j; for (j=0; jnints; j++) { x[j] = xnew[j]; lpx_set_col_bnds(prob->lp, prob->lpi[j], LPX_FX, x[j], x[j]); } } void roundfix(LPPROB *prob, int x[], double *z, double *zeta, int p[], int size) { int j,k; for (j=0;jlp,prob->lpi[k]); int isol = (int) sol; double u = uniform(); // printf("sol: %lf, u: %lf, isol:%d, rounding ", sol, u, isol); if (u < sol-isol) { x[k] = isol + 1; // printf("up\n"); } else { x[k] = isol; // printf("down\n"); } x[k] = min(x[k], prob->ub[k]); x[k] = max(x[k], prob->lb[k]); lpx_set_col_bnds(prob->lp, prob->lpi[k], LPX_FX, x[k], x[k]); if (LOG) printf(" %i (%d), %s -> \t %d <= %d <= %d\n", k, prob->lpi[k], lpx_get_col_name(prob->lp, prob->lpi[k]), prob->lb[k], x[k], prob->ub[k]); // progressive fixing: solve lp again... solvelp(prob, z, zeta); // lpx_print_sol(prob->lp, "lpsol.sol"); if (LOG) printivectz(x, prob->nints, *z, *zeta); } } // // utility functions // // random number in [0,1] with uniform distribution: double uniform() { return rand()/(double) RAND_MAX; } // place the elements of a vector in random order void random_shuffle(int vector[], int size) { if (size<=1) return; int i; for (i=0; i