long __declspec(dllexport) WINAPI _get_total_iter(lprec *lp) { long ret; if (lp != NULL) { freebuferror(); ret = get_total_iter(lp); } else ret = 0; return(ret); }
/* Report the traditional tableau corresponding to the current basis */ MYBOOL REPORT_tableau(lprec *lp) { int j, row_nr, *coltarget; LPSREAL *prow = NULL; FILE *stream = lp->outstream; if(lp->outstream == NULL) return(FALSE); if(!lp->model_is_valid || !has_BFP(lp) || (get_total_iter(lp) == 0) || (lp->spx_status == NOTRUN)) { lp->spx_status = NOTRUN; return(FALSE); } if(!allocREAL(lp, &prow,lp->sum + 1, TRUE)) { lp->spx_status = NOMEMORY; return(FALSE); } fprintf(stream, "\n"); fprintf(stream, "Tableau at iter %.0f:\n", (double) get_total_iter(lp)); for(j = 1; j <= lp->sum; j++) if (!lp->is_basic[j]) fprintf(stream, "%15d", (j <= lp->rows ? (j + lp->columns) * ((lp->orig_upbo[j] == 0) || (is_chsign(lp, j)) ? 1 : -1) : j - lp->rows) * (lp->is_lower[j] ? 1 : -1)); fprintf(stream, "\n"); coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->columns+1, sizeof(*coltarget)); if(!get_colIndexA(lp, SCAN_USERVARS+USE_NONBASICVARS, coltarget, FALSE)) { mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); return(FALSE); } for(row_nr = 1; (row_nr <= lp->rows + 1); row_nr++) { if (row_nr <= lp->rows) fprintf(stream, "%3d", (lp->var_basic[row_nr] <= lp->rows ? (lp->var_basic[row_nr] + lp->columns) * ((lp->orig_upbo[lp->var_basic [row_nr]] == 0) || (is_chsign(lp, lp->var_basic[row_nr])) ? 1 : -1) : lp->var_basic[row_nr] - lp->rows) * (lp->is_lower[lp->var_basic [row_nr]] ? 1 : -1)); else fprintf(stream, " "); bsolve(lp, row_nr <= lp->rows ? row_nr : 0, prow, NULL, lp->epsmachine*DOUBLEROUND, 1.0); prod_xA(lp, coltarget, prow, NULL, lp->epsmachine, 1.0, prow, NULL, MAT_ROUNDDEFAULT); for(j = 1; j <= lp->rows + lp->columns; j++) if (!lp->is_basic[j]) fprintf(stream, "%15.7f", prow[j] * (lp->is_lower[j] ? 1 : -1) * (row_nr <= lp->rows ? 1 : -1)); fprintf(stream, "%15.7f", lp->rhs[row_nr <= lp->rows ? row_nr : 0] * (double) ((row_nr <= lp->rows) || (is_maxim(lp)) ? 1 : -1)); fprintf(stream, "\n"); } fflush(stream); mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE); FREE(prow); return(TRUE); }
int main(int argc, char *argv[]) { lprec *lp = NULL; char *filen, *wlp = NULL, *wmps = NULL, *wfmps = NULL, plp = FALSE; int i; int verbose = IMPORTANT /* CRITICAL */; int debug = -1; MYBOOL report = FALSE; MYBOOL nonames = FALSE, norownames = FALSE, nocolnames = FALSE; MYBOOL write_model_after = FALSE; MYBOOL noint = FALSE; int print_sol = -1; MYBOOL print_stats = FALSE; int floor_first = -1; MYBOOL do_set_bb_depthlimit = FALSE; int bb_depthlimit = 0; MYBOOL do_set_solutionlimit = FALSE; int solutionlimit = 0; MYBOOL break_at_first = FALSE; int scaling = 0; double scaleloop = 0; MYBOOL tracing = FALSE; short filetype = filetypeLP; int anti_degen1 = -1; int anti_degen2 = -1; short print_timing = FALSE; short parse_only = FALSE; int do_presolve = -1; short objective = 0; short PRINT_SOLUTION = 2; int improve = -1; int pivoting1 = -1; int pivoting2 = -1; int bb_rule1 = -1; int bb_rule2 = -1; int max_num_inv = -1; int scalemode1 = -1; int scalemode2 = -1; int crashmode = -1; char *guessbasis = NULL; /* short timeoutok = FALSE; */ long sectimeout = -1; int result; MYBOOL preferdual = AUTOMATIC; int simplextype = -1; MYBOOL do_set_obj_bound = FALSE; REAL obj_bound = 0; REAL mip_absgap = -1; REAL mip_relgap = -1; REAL epsperturb = -1; REAL epsint = -1; REAL epspivot = -1; REAL epsd = -1; REAL epsb = -1; REAL epsel = -1; MYBOOL do_set_break_at_value = FALSE; REAL break_at_value = 0; REAL accuracy_error0, accuracy_error = -1; FILE *fpin = stdin; char *bfp = NULL; char *rxliname = NULL, *rxli = NULL, *rxlidata = NULL, *rxlioptions = NULL, *wxliname = NULL, *wxlisol = NULL, *wxli = NULL, *wxlioptions = NULL, *wxlisoloptions = NULL; char *rbasname = NULL, *wbasname = NULL; char *debugdump_before = NULL; char *debugdump_after = NULL; char *rparname = NULL; char *rparoptions = NULL; char *wparname = NULL; char *wparoptions = NULL; char obj_in_basis = -1; char mps_ibm = FALSE; char mps_negobjconst = FALSE; char mps_free = FALSE; MYBOOL ok; # define SCALINGTHRESHOLD 0.03 /* read command line arguments */ # if defined FORTIFY Fortify_EnterScope(); # endif for(i = 1; i < argc; i++) { ok = FALSE; if(strncmp(argv[i], "-v", 2) == 0) { if (argv[i][2]) verbose = atoi(argv[i] + 2); else verbose = NORMAL; } else if(strcmp(argv[i], "-d") == 0) debug = TRUE; else if(strcmp(argv[i], "-R") == 0) report = TRUE; else if(strcmp(argv[i], "-i") == 0) print_sol = TRUE; else if(strcmp(argv[i], "-ia") == 0) print_sol = AUTOMATIC; else if(strcmp(argv[i], "-stat") == 0) print_stats = TRUE; else if(strcmp(argv[i], "-nonames") == 0) nonames = TRUE; else if(strcmp(argv[i], "-norownames") == 0) norownames = TRUE; else if(strcmp(argv[i], "-nocolnames") == 0) nocolnames = TRUE; else if((strcmp(argv[i], "-c") == 0) || (strcmp(argv[i], "-cc") == 0)) floor_first = BRANCH_CEILING; else if(strcmp(argv[i], "-cf") == 0) floor_first = BRANCH_FLOOR; else if(strcmp(argv[i], "-ca") == 0) floor_first = BRANCH_AUTOMATIC; else if((strcmp(argv[i], "-depth") == 0) && (i + 1 < argc)) { do_set_bb_depthlimit = TRUE; bb_depthlimit = atoi(argv[++i]); } else if(strcmp(argv[i], "-Bw") == 0) or_value(&bb_rule2, NODE_WEIGHTREVERSEMODE); else if(strcmp(argv[i], "-Bb") == 0) or_value(&bb_rule2, NODE_BRANCHREVERSEMODE); else if(strcmp(argv[i], "-Bg") == 0) or_value(&bb_rule2, NODE_GREEDYMODE); else if(strcmp(argv[i], "-Bp") == 0) or_value(&bb_rule2, NODE_PSEUDOCOSTMODE); else if(strcmp(argv[i], "-BR") == 0) or_value(&bb_rule2, NODE_PSEUDORATIOSELECT); else if(strcmp(argv[i], "-Bf") == 0) or_value(&bb_rule2, NODE_DEPTHFIRSTMODE); else if(strcmp(argv[i], "-Br") == 0) or_value(&bb_rule2, NODE_RANDOMIZEMODE); else if(strcmp(argv[i], "-BG") == 0) or_value(&bb_rule2, 0 /* NODE_GUBMODE */); /* doesn't work yet */ else if(strcmp(argv[i], "-Bd") == 0) or_value(&bb_rule2, NODE_DYNAMICMODE); else if(strcmp(argv[i], "-Bs") == 0) or_value(&bb_rule2, NODE_RESTARTMODE); else if(strcmp(argv[i], "-BB") == 0) or_value(&bb_rule2, NODE_BREADTHFIRSTMODE); else if(strcmp(argv[i], "-Bo") == 0) or_value(&bb_rule2, NODE_AUTOORDER); else if(strcmp(argv[i], "-Bc") == 0) or_value(&bb_rule2, NODE_RCOSTFIXING); else if(strcmp(argv[i], "-Bi") == 0) or_value(&bb_rule2, NODE_STRONGINIT); else if(strncmp(argv[i], "-B", 2) == 0) { if (argv[i][2]) set_value(&bb_rule1, atoi(argv[i] + 2)); else set_value(&bb_rule1, NODE_FIRSTSELECT); } else if((strcmp(argv[i], "-n") == 0) && (i + 1 < argc)) { do_set_solutionlimit = TRUE; solutionlimit = atoi(argv[++i]); } else if((strcmp(argv[i], "-b") == 0) && (i + 1 < argc)) { obj_bound = atof(argv[++i]); do_set_obj_bound = TRUE; } else if(((strcmp(argv[i], "-g") == 0) || (strcmp(argv[i], "-ga") == 0)) && (i + 1 < argc)) mip_absgap = atof(argv[++i]); else if((strcmp(argv[i], "-gr") == 0) && (i + 1 < argc)) mip_relgap = atof(argv[++i]); else if((strcmp(argv[i], "-e") == 0) && (i + 1 < argc)) { epsint = atof(argv[++i]); if((epsint <= 0.0) || (epsint >= 0.5)) { fprintf(stderr, "Invalid tolerance %g; 0 < epsilon < 0.5\n", (double)epsint); EndOfPgr(FORCED_EXIT); } } else if((strcmp(argv[i], "-r") == 0) && (i + 1 < argc)) max_num_inv = atoi(argv[++i]); else if((strcmp(argv[i], "-o") == 0) && (i + 1 < argc)) { break_at_value = atof(argv[++i]); do_set_break_at_value = TRUE; } else if(strcmp(argv[i], "-f") == 0) break_at_first = TRUE; else if(strcmp(argv[i], "-timeoutok") == 0) /* timeoutok = TRUE */; /* option no longer needed, but still accepted */ else if(strcmp(argv[i], "-h") == 0) { print_help(argv); EndOfPgr(EXIT_SUCCESS); } else if(strcmp(argv[i], "-prim") == 0) preferdual = FALSE; else if(strcmp(argv[i], "-dual") == 0) preferdual = TRUE; else if(strcmp(argv[i], "-simplexpp") == 0) simplextype = SIMPLEX_PRIMAL_PRIMAL; else if(strcmp(argv[i], "-simplexdp") == 0) simplextype = SIMPLEX_DUAL_PRIMAL; else if(strcmp(argv[i], "-simplexpd") == 0) simplextype = SIMPLEX_PRIMAL_DUAL; else if(strcmp(argv[i], "-simplexdd") == 0) simplextype = SIMPLEX_DUAL_DUAL; else if(strcmp(argv[i], "-sp") == 0) or_value(&scalemode2, SCALE_POWER2); else if(strcmp(argv[i], "-si") == 0) or_value(&scalemode2, SCALE_INTEGERS); else if(strcmp(argv[i], "-se") == 0) or_value(&scalemode2, SCALE_EQUILIBRATE); else if(strcmp(argv[i], "-sq") == 0) or_value(&scalemode2, SCALE_QUADRATIC); else if(strcmp(argv[i], "-sl") == 0) or_value(&scalemode2, SCALE_LOGARITHMIC); else if(strcmp(argv[i], "-sd") == 0) or_value(&scalemode2, SCALE_DYNUPDATE); else if(strcmp(argv[i], "-sr") == 0) or_value(&scalemode2, SCALE_ROWSONLY); else if(strcmp(argv[i], "-sc") == 0) or_value(&scalemode2, SCALE_COLSONLY); else if(strncmp(argv[i], "-s", 2) == 0) { set_value(&scalemode1, SCALE_NONE); scaling = SCALE_MEAN; if (argv[i][2]) { switch (atoi(argv[i] + 2)) { case 0: scaling = SCALE_NONE; break; case 1: set_value(&scalemode1, SCALE_GEOMETRIC); break; case 2: set_value(&scalemode1, SCALE_CURTISREID); break; case 3: set_value(&scalemode1, SCALE_EXTREME); break; case 4: set_value(&scalemode1, SCALE_MEAN); break; case 5: set_value(&scalemode1, SCALE_MEAN | SCALE_LOGARITHMIC); break; case 6: set_value(&scalemode1, SCALE_RANGE); break; case 7: set_value(&scalemode1, SCALE_MEAN | SCALE_QUADRATIC); break; } } else set_value(&scalemode1, SCALE_MEAN); if((i + 1 < argc) && (isNum(argv[i + 1]))) scaleloop = atoi(argv[++i]); } else if(strncmp(argv[i], "-C", 2) == 0) crashmode = atoi(argv[i] + 2); else if((strcmp(argv[i],"-gbas") == 0) && (i + 1 < argc)) guessbasis = argv[++i]; else if(strcmp(argv[i], "-t") == 0) tracing = TRUE; else if(strncmp(argv[i], "-S", 2) == 0) { if (argv[i][2]) PRINT_SOLUTION = (short) atoi(argv[i] + 2); else PRINT_SOLUTION = 2; } else if(strncmp(argv[i], "-improve", 8) == 0) { if (argv[i][8]) or_value(&improve, atoi(argv[i] + 8)); } else if(strcmp(argv[i], "-pivll") == 0) or_value(&pivoting2, PRICE_LOOPLEFT); else if(strcmp(argv[i], "-pivla") == 0) or_value(&pivoting2, PRICE_LOOPALTERNATE); #if defined EnablePartialOptimization else if(strcmp(argv[i], "-pivpc") == 0) or_value(&pivoting2, PRICE_AUTOPARTIALCOLS); else if(strcmp(argv[i], "-pivpr") == 0) or_value(&pivoting2, PRICE_AUTOPARTIALROWS); else if(strcmp(argv[i], "-pivp") == 0) or_value(&pivoting2, PRICE_AUTOPARTIAL); #endif else if(strcmp(argv[i], "-pivf") == 0) or_value(&pivoting2, PRICE_PRIMALFALLBACK); else if(strcmp(argv[i], "-pivm") == 0) or_value(&pivoting2, PRICE_MULTIPLE); else if(strcmp(argv[i], "-piva") == 0) or_value(&pivoting2, PRICE_ADAPTIVE); else if(strcmp(argv[i], "-pivr") == 0) or_value(&pivoting2, PRICE_RANDOMIZE); else if(strcmp(argv[i], "-pivh") == 0) or_value(&pivoting2, PRICE_HARRISTWOPASS); else if(strcmp(argv[i], "-pivt") == 0) or_value(&pivoting2, PRICE_TRUENORMINIT); else if(strncmp(argv[i], "-piv", 4) == 0) { if (argv[i][4]) set_value(&pivoting1, atoi(argv[i] + 4)); else set_value(&pivoting1, PRICER_DEVEX | PRICE_ADAPTIVE); } #if defined PARSER_LP else if(strcmp(argv[i],"-lp") == 0) filetype = filetypeLP; #endif else if((strcmp(argv[i],"-wlp") == 0) && (i + 1 < argc)) wlp = argv[++i]; else if(strcmp(argv[i],"-plp") == 0) plp = TRUE; else if(strcmp(argv[i],"-mps") == 0) filetype = filetypeMPS; else if(strcmp(argv[i],"-mps_ibm") == 0) mps_ibm = TRUE; else if(strcmp(argv[i],"-mps_negobjconst") == 0) mps_negobjconst = TRUE; else if(strcmp(argv[i],"-mps_free") == 0) mps_free = TRUE; else if(strcmp(argv[i],"-fmps") == 0) filetype = filetypeFREEMPS; else if((strcmp(argv[i],"-wmps") == 0) && (i + 1 < argc)) wmps = argv[++i]; else if((strcmp(argv[i],"-wfmps") == 0) && (i + 1 < argc)) wfmps = argv[++i]; else if(strcmp(argv[i],"-wafter") == 0) write_model_after = TRUE; else if(strcmp(argv[i],"-degen") == 0) set_value(&anti_degen1, ANTIDEGEN_DEFAULT); else if(strcmp(argv[i],"-degenf") == 0) or_value(&anti_degen2, ANTIDEGEN_FIXEDVARS); else if(strcmp(argv[i],"-degenc") == 0) or_value(&anti_degen2, ANTIDEGEN_COLUMNCHECK); else if(strcmp(argv[i],"-degens") == 0) or_value(&anti_degen2, ANTIDEGEN_STALLING); else if(strcmp(argv[i],"-degenn") == 0) or_value(&anti_degen2, ANTIDEGEN_NUMFAILURE); else if(strcmp(argv[i],"-degenl") == 0) or_value(&anti_degen2, ANTIDEGEN_LOSTFEAS); else if(strcmp(argv[i],"-degeni") == 0) or_value(&anti_degen2, ANTIDEGEN_INFEASIBLE); else if(strcmp(argv[i],"-degend") == 0) or_value(&anti_degen2, ANTIDEGEN_DYNAMIC); else if(strcmp(argv[i],"-degenb") == 0) or_value(&anti_degen2, ANTIDEGEN_DURINGBB); else if(strcmp(argv[i],"-degenr") == 0) or_value(&anti_degen2, ANTIDEGEN_RHSPERTURB); else if(strcmp(argv[i],"-degenp") == 0) or_value(&anti_degen2, ANTIDEGEN_BOUNDFLIP); else if(strcmp(argv[i],"-time") == 0) { if(clock() == -1) fprintf(stderr, "CPU times not available on this machine\n"); else print_timing = TRUE; } else if((strcmp(argv[i],"-bfp") == 0) && (i + 1 < argc)) bfp = argv[++i]; else if((strcmp(argv[i],"-rxli") == 0) && (i + 2 < argc)) { rxliname = argv[++i]; rxli = argv[++i]; fpin = NULL; filetype = filetypeXLI; } else if((strcmp(argv[i],"-rxlidata") == 0) && (i + 1 < argc)) rxlidata = argv[++i]; else if((strcmp(argv[i],"-rxliopt") == 0) && (i + 1 < argc)) rxlioptions = argv[++i]; else if((strcmp(argv[i],"-wxli") == 0) && (i + 2 < argc)) { wxliname = argv[++i]; wxli = argv[++i]; } else if((strcmp(argv[i],"-wxliopt") == 0) && (i + 1 < argc)) wxlioptions = argv[++i]; else if((strcmp(argv[i],"-wxlisol") == 0) && (i + 2 < argc)) { wxliname = argv[++i]; wxlisol = argv[++i]; } else if((strcmp(argv[i],"-wxlisolopt") == 0) && (i + 1 < argc)) wxlisoloptions = argv[++i]; else if((strcmp(argv[i],"-rbas") == 0) && (i + 1 < argc)) rbasname = argv[++i]; else if((strcmp(argv[i],"-wbas") == 0) && (i + 1 < argc)) wbasname = argv[++i]; else if((strcmp(argv[i],"-Db") == 0) && (i + 1 < argc)) debugdump_before = argv[++i]; else if((strcmp(argv[i],"-Da") == 0) && (i + 1 < argc)) debugdump_after = argv[++i]; else if((strcmp(argv[i],"-timeout") == 0) && (i + 1 < argc)) sectimeout = atol(argv[++i]); else if((strcmp(argv[i],"-trej") == 0) && (i + 1 < argc)) epspivot = atof(argv[++i]); else if((strcmp(argv[i],"-epsp") == 0) && (i + 1 < argc)) epsperturb = atof(argv[++i]); else if((strcmp(argv[i],"-epsd") == 0) && (i + 1 < argc)) epsd = atof(argv[++i]); else if((strcmp(argv[i],"-epsb") == 0) && (i + 1 < argc)) epsb = atof(argv[++i]); else if((strcmp(argv[i],"-epsel") == 0) && (i + 1 < argc)) epsel = atof(argv[++i]); else if(strcmp(argv[i],"-parse_only") == 0) parse_only = TRUE; else ok = TRUE; if(!ok) ; else if(strcmp(argv[i],"-presolverow") == 0) or_value(&do_presolve, PRESOLVE_ROWS); else if(strcmp(argv[i],"-presolvecol") == 0) or_value(&do_presolve, PRESOLVE_COLS); else if(strcmp(argv[i],"-presolve") == 0) or_value(&do_presolve, PRESOLVE_ROWS | PRESOLVE_COLS); else if(strcmp(argv[i],"-presolvel") == 0) or_value(&do_presolve, PRESOLVE_LINDEP); else if(strcmp(argv[i],"-presolves") == 0) or_value(&do_presolve, PRESOLVE_SOS); else if(strcmp(argv[i],"-presolver") == 0) or_value(&do_presolve, PRESOLVE_REDUCEMIP); else if(strcmp(argv[i],"-presolvek") == 0) or_value(&do_presolve, PRESOLVE_KNAPSACK); else if(strcmp(argv[i],"-presolveq") == 0) or_value(&do_presolve, PRESOLVE_ELIMEQ2); else if(strcmp(argv[i],"-presolvem") == 0) or_value(&do_presolve, PRESOLVE_MERGEROWS); else if(strcmp(argv[i],"-presolvefd") == 0) or_value(&do_presolve, PRESOLVE_COLFIXDUAL); else if(strcmp(argv[i],"-presolvebnd") == 0) or_value(&do_presolve, PRESOLVE_BOUNDS); else if(strcmp(argv[i],"-presolved") == 0) or_value(&do_presolve, PRESOLVE_DUALS); else if(strcmp(argv[i],"-presolvef") == 0) or_value(&do_presolve, PRESOLVE_IMPLIEDFREE); else if(strcmp(argv[i],"-presolveslk") == 0) or_value(&do_presolve, PRESOLVE_IMPLIEDSLK); else if(strcmp(argv[i],"-presolveg") == 0) or_value(&do_presolve, PRESOLVE_REDUCEGCD); else if(strcmp(argv[i],"-presolveb") == 0) or_value(&do_presolve, PRESOLVE_PROBEFIX); else if(strcmp(argv[i],"-presolvec") == 0) or_value(&do_presolve, PRESOLVE_PROBEREDUCE); else if(strcmp(argv[i],"-presolverowd") == 0) or_value(&do_presolve, PRESOLVE_ROWDOMINATE); else if(strcmp(argv[i],"-presolvecold") == 0) or_value(&do_presolve, PRESOLVE_COLDOMINATE); else if(strcmp(argv[i],"-min") == 0) objective = -1; else if(strcmp(argv[i],"-max") == 0) objective = 1; else if(strcmp(argv[i],"-noint") == 0) noint = TRUE; else if((strcmp(argv[i],"-rpar") == 0) && (i + 1 < argc)) i++; else if((strcmp(argv[i],"-rparopt") == 0) && (i + 1 < argc)) i++; else if((strcmp(argv[i],"-wpar") == 0) && (i + 1 < argc)) i++; else if((strcmp(argv[i],"-wparopt") == 0) && (i + 1 < argc)) i++; else if(strcmp(argv[i],"-o0") == 0) obj_in_basis = FALSE; else if(strcmp(argv[i],"-o1") == 0) obj_in_basis = TRUE; else if((strcmp(argv[i], "-ac") == 0) && (i + 1 < argc)) accuracy_error = atof(argv[++i]); else if(fpin == stdin) { filen = argv[i]; if(*filen == '<') filen++; if((fpin = fopen(filen, "r")) == NULL) { print_help(argv); fprintf(stderr,"\nError, Unable to open input file '%s'\n", argv[i]); EndOfPgr(FORCED_EXIT); } } else { filen = argv[i]; if(*filen != '>') { print_help(argv); fprintf(stderr, "\nError, Unrecognized command line argument '%s'\n", argv[i]); EndOfPgr(FORCED_EXIT); } } } signal(SIGABRT,/* (void (*) OF((int))) */ SIGABRT_func); if ((filetype != filetypeXLI) && (fpin == NULL)) { lp = NULL; fprintf(stderr, "Cannot combine -rxli option with -lp, -mps, -fmps.\n"); } else { switch(filetype) { #if defined PARSER_LP case filetypeLP: lp = read_lp(fpin, verbose, NULL); break; #endif case filetypeMPS: lp = read_mps(fpin, verbose | (mps_free ? MPS_FREE : 0) | (mps_ibm ? MPS_IBM : 0) | (mps_negobjconst ? MPS_NEGOBJCONST : 0)); break; case filetypeFREEMPS: lp = read_freemps(fpin, verbose | (mps_ibm ? MPS_IBM : 0) | (mps_negobjconst ? MPS_NEGOBJCONST : 0)); break; case filetypeXLI: lp = read_XLI(rxliname, rxli, rxlidata, rxlioptions, verbose); break; } } if((fpin != NULL) && (fpin != stdin)) fclose(fpin); if(print_timing) print_cpu_times("Parsing input"); if(lp == NULL) { fprintf(stderr, "Unable to read model.\n"); EndOfPgr(FORCED_EXIT); } for(i = 1; i < argc; i++) { if((strcmp(argv[i],"-rpar") == 0) && (i + 1 < argc)) { if(rparname != NULL) { if(!read_params(lp, rparname, rparoptions)) { fprintf(stderr, "Unable to read parameter file (%s)\n", rparname); delete_lp(lp); EndOfPgr(FORCED_EXIT); } } rparname = argv[++i]; } else if((strcmp(argv[i],"-rparopt") == 0) && (i + 1 < argc)) rparoptions = argv[++i]; else if((strcmp(argv[i],"-wpar") == 0) && (i + 1 < argc)) wparname = argv[++i]; else if((strcmp(argv[i],"-wparopt") == 0) && (i + 1 < argc)) wparoptions = argv[++i]; } if(rparname != NULL) if(!read_params(lp, rparname, rparoptions)) { fprintf(stderr, "Unable to read parameter file (%s)\n", rparname); delete_lp(lp); EndOfPgr(FORCED_EXIT); } if((nonames) || (nocolnames)) set_use_names(lp, FALSE, FALSE); if((nonames) || (norownames)) set_use_names(lp, TRUE, FALSE); if(objective != 0) { if(objective == 1) set_maxim(lp); else set_minim(lp); } if (obj_in_basis != -1) set_obj_in_basis(lp, obj_in_basis); if(noint) { /* remove integer conditions */ for(i = get_Ncolumns(lp); i >= 1; i--) { if(is_SOS_var(lp, i)) { fprintf(stderr, "Unable to remove integer conditions because there is at least one SOS constraint\n"); delete_lp(lp); EndOfPgr(FORCED_EXIT); } set_semicont(lp, i, FALSE); set_int(lp, i, FALSE); } } if(!write_model_after) write_model(lp, plp, wlp, wmps, wfmps, wxli, NULL, wxliname, wxlioptions); if(print_stats) print_statistics(lp); if(parse_only) { if(!write_model_after) { delete_lp(lp); EndOfPgr(0); } /* else if(!sectimeout) */ sectimeout = 1; } if(PRINT_SOLUTION >= 5) print_lp(lp); #if 0 put_abortfunc(lp,(abortfunc *) myabortfunc, NULL); #endif if(sectimeout > 0) set_timeout(lp, sectimeout); if(print_sol >= 0) set_print_sol(lp, print_sol); if(epsint >= 0) set_epsint(lp, epsint); if(epspivot >= 0) set_epspivot(lp, epspivot); if(epsperturb >= 0) set_epsperturb(lp, epsperturb); if(epsd >= 0) set_epsd(lp, epsd); if(epsb >= 0) set_epsb(lp, epsb); if(epsel >= 0) set_epsel(lp, epsel); if(debug >= 0) set_debug(lp, (MYBOOL) debug); if(floor_first != -1) set_bb_floorfirst(lp, floor_first); if(do_set_bb_depthlimit) set_bb_depthlimit(lp, bb_depthlimit); if(do_set_solutionlimit) set_solutionlimit(lp, solutionlimit); if(tracing) set_trace(lp, tracing); if(do_set_obj_bound) set_obj_bound(lp, obj_bound); if(do_set_break_at_value) set_break_at_value(lp, break_at_value); if(break_at_first) set_break_at_first(lp, break_at_first); if(mip_absgap >= 0) set_mip_gap(lp, TRUE, mip_absgap); if(mip_relgap >= 0) set_mip_gap(lp, FALSE, mip_relgap); if((anti_degen1 != -1) || (anti_degen2 != -1)) { if((anti_degen1 == -1) || (anti_degen2 != -1)) anti_degen1 = 0; if(anti_degen2 == -1) anti_degen2 = 0; set_anti_degen(lp, anti_degen1 | anti_degen2); } set_presolve(lp, ((do_presolve == -1) ? get_presolve(lp): do_presolve) | ((PRINT_SOLUTION >= 4) ? PRESOLVE_SENSDUALS : 0), get_presolveloops(lp)); if(improve != -1) set_improve(lp, improve); if(max_num_inv >= 0) set_maxpivot(lp, max_num_inv); if(preferdual != AUTOMATIC) set_preferdual(lp, preferdual); if((pivoting1 != -1) || (pivoting2 != -1)) { if(pivoting1 == -1) pivoting1 = get_pivoting(lp) & PRICER_LASTOPTION; if(pivoting2 == -1) pivoting2 = 0; set_pivoting(lp, pivoting1 | pivoting2); } if((scalemode1 != -1) || (scalemode2 != -1)) { if(scalemode1 == -1) scalemode1 = get_scaling(lp) & SCALE_CURTISREID; if(scalemode2 == -1) scalemode2 = 0; set_scaling(lp, scalemode1 | scalemode2); } if(crashmode != -1) set_basiscrash(lp, crashmode); if((bb_rule1 != -1) || (bb_rule2 != -1)) { if(bb_rule1 == -1) bb_rule1 = get_bb_rule(lp) & NODE_USERSELECT; if(bb_rule2 == -1) bb_rule2 = 0; set_bb_rule(lp, bb_rule1 | bb_rule2); } if(simplextype != -1) set_simplextype(lp, simplextype); if(bfp != NULL) if(!set_BFP(lp, bfp)) { fprintf(stderr, "Unable to set BFP package.\n"); delete_lp(lp); EndOfPgr(FORCED_EXIT); } if(debugdump_before != NULL) print_debugdump(lp, debugdump_before); if(report) put_msgfunc(lp, LPMessageCB, NULL, MSG_LPFEASIBLE | MSG_LPOPTIMAL | MSG_MILPFEASIBLE | MSG_MILPBETTER | MSG_PERFORMANCE); if(scaling) { if(scaleloop <= 0) scaleloop = 5; if(scaleloop - (int) scaleloop < SCALINGTHRESHOLD) scaleloop = (int) scaleloop + SCALINGTHRESHOLD; set_scalelimit(lp, scaleloop); } if (accuracy_error != -1) set_break_numeric_accuracy(lp, accuracy_error); if(guessbasis != NULL) { REAL *guessvector, a; int *basisvector; int Nrows = get_Nrows(lp); int Ncolumns = get_Ncolumns(lp); int col; char buf[50], *ptr; FILE *fp; if ((fp = fopen(guessbasis, "r")) != NULL) { guessvector = (REAL *) calloc(1+Ncolumns, sizeof(*guessvector)); basisvector = (int *) malloc((1+Nrows+Ncolumns)*sizeof(*basisvector)); if ((guessvector != NULL) && (basisvector != NULL)) { while ((!feof(fp)) && (fgets(buf, sizeof(buf), fp) != NULL)) { ptr = strrchr(buf, ':'); if (ptr == NULL) { printf("Mallformed line: %s\n", buf); } else { a = atof(ptr + 1); while ((ptr > buf) && (isspace(ptr[-1]))) ptr--; *ptr = 0; col = get_nameindex(lp, buf, FALSE); if (col < 1) printf("guess_basis: Unknown variable name %s\n", buf); else guessvector[col] = a; } } if (guess_basis(lp, guessvector, basisvector)) { if (!set_basis(lp, basisvector, TRUE)) printf("Unable to set guessed basis.\n"); } else printf("Unable to guess basis from provided variables.\n"); } else printf("guess_basis: Out of memory.\n"); if (basisvector != NULL) free(basisvector); if (guessvector != NULL) free(guessvector); fclose(fp); } else printf("Unable to open file %s\n", guessbasis); } if(rbasname != NULL) if(!read_basis(lp, rbasname, NULL)) { fprintf(stderr, "Unable to read basis file.\n"); delete_lp(lp); EndOfPgr(FORCED_EXIT); } result = solve(lp); if(wbasname != NULL) if(!write_basis(lp, wbasname)) fprintf(stderr, "Unable to write basis file.\n"); if(write_model_after) write_model(lp, plp, wlp, wmps, wfmps, wxli, NULL, wxliname, wxlioptions); write_model(lp, FALSE, NULL, NULL, NULL, NULL, wxlisol, wxliname, wxlisoloptions); if(PRINT_SOLUTION >= 6) print_scales(lp); if((print_timing) && (!parse_only)) print_cpu_times("solving"); if(debugdump_after != NULL) print_debugdump(lp, debugdump_after); if(wparname != NULL) if(!write_params(lp, wparname, wparoptions)) { fprintf(stderr, "Unable to write parameter file (%s)\n", wparname); delete_lp(lp); EndOfPgr(FORCED_EXIT); } if(parse_only) { delete_lp(lp); EndOfPgr(0); } /* if((timeoutok) && (result == TIMEOUT) && (get_solutioncount(lp) > 0)) result = OPTIMAL; */ switch(result) { case SUBOPTIMAL: case PRESOLVED: case OPTIMAL: case PROCBREAK: case FEASFOUND: if ((result == SUBOPTIMAL) && (PRINT_SOLUTION >= 1)) printf("Suboptimal solution\n"); if (result == PRESOLVED) printf("Presolved solution\n"); if (PRINT_SOLUTION >= 1) print_objective(lp); if (PRINT_SOLUTION >= 2) print_solution(lp, 1); if (PRINT_SOLUTION >= 3) print_constraints(lp, 1); if (PRINT_SOLUTION >= 4) print_duals(lp); if(tracing) fprintf(stderr, "Branch & Bound depth: %d\nNodes processed: %.0f\nSimplex pivots: %.0f\nNumber of equal solutions: %d\n", get_max_level(lp), (REAL) get_total_nodes(lp), (REAL) get_total_iter(lp), get_solutioncount(lp)); break; case NOMEMORY: if (PRINT_SOLUTION >= 1) printf("Out of memory\n"); break; case INFEASIBLE: if (PRINT_SOLUTION >= 1) printf("This problem is infeasible\n"); break; case UNBOUNDED: if (PRINT_SOLUTION >= 1) printf("This problem is unbounded\n"); break; case PROCFAIL: if (PRINT_SOLUTION >= 1) printf("The B&B routine failed\n"); break; case TIMEOUT: if (PRINT_SOLUTION >= 1) printf("Timeout\n"); break; case USERABORT: if (PRINT_SOLUTION >= 1) printf("User aborted\n"); break; case ACCURACYERROR: if (PRINT_SOLUTION >= 1) printf("Accuracy error\n"); break; default: if (PRINT_SOLUTION >= 1) printf("lp_solve failed\n"); break; } if (PRINT_SOLUTION >= 7) print_tableau(lp); delete_lp(lp); EndOfPgr(result); return(result); }
STATIC int dualloop(lprec *lp, MYBOOL feasible) { int i, ok = TRUE; LREAL theta = 0.0; REAL *drow = NULL, *prow = NULL, *pcol = NULL, prevobj, epsvalue; MYBOOL primal = FALSE, forceoutEQ = FALSE; MYBOOL minit, pivdynamic, bfpfinal = FALSE; int oldpivrule, oldpivmode, pivrule, Blandswitches, colnr, rownr, lastnr, minitcount = 0; int Rcycle = 0, Ccycle = 0, Ncycle = 0, changedphase = TRUE; #ifdef FixInaccurateDualMinit int minitcolnr = 0; #endif int *nzprow = NULL, *workINT = NULL; if(lp->spx_trace) report(lp, DETAILED, "Entering dual simplex algorithm\n"); /* Set Extrad value to force dual feasibility; reset when "local optimality" has been achieved or a dual non-feasibility has been encountered (no candidate for a first leaving variable) */ if(feasible) lp->Extrad = 0; else lp->Extrad = feasibilityOffset(lp, (MYBOOL)!primal); if(lp->spx_trace) report(lp, DETAILED, "Extrad = %g\n", (double)lp->Extrad); /* Allocate work arrays */ allocREAL(lp, &drow, lp->sum + 1, TRUE); #ifdef UseSparseReducedCost allocINT(lp, &nzprow, lp->sum + 1, FALSE); #endif allocREAL(lp, &prow, lp->sum + 1, TRUE); allocREAL(lp, &pcol, lp->rows + 1, TRUE); /* Refactorize the basis and set status variables */ i = my_if(is_bb_action(lp, ACTION_REBASE), INITSOL_SHIFTZERO, INITSOL_USEZERO); if(((lp->spx_status == SWITCH_TO_DUAL) && !lp->justInverted) || (lp->Extrad != 0) || is_bb_action(lp, ACTION_REINVERT)) { simplexPricer(lp, (MYBOOL)!primal); /* Do basis crashing before refactorization, if specified */ invert(lp, (MYBOOL) i, TRUE); } else { if(is_bb_action(lp, ACTION_RECOMPUTE)) recompute_solution(lp, (MYBOOL) i); restartPricer(lp, (MYBOOL)!primal); } lp->bb_action = ACTION_NONE; lp->spx_status = RUNNING; lp->doIterate = FALSE; minit = ITERATE_MAJORMAJOR; prevobj = lp->rhs[0]; oldpivmode = lp->piv_strategy; oldpivrule = get_piv_rule(lp); pivdynamic = ANTICYCLEBLAND && is_piv_mode(lp, PRICE_ADAPTIVE); epsvalue = lp->epspivot; Blandswitches = 0; rownr = 0; colnr = -1; /* Used to detect infeasibility at the beginning of the dual loop */ lastnr = 0; lp->rejectpivot[0] = 0; if(feasible) lp->simplex_mode = SIMPLEX_Phase2_DUAL; else lp->simplex_mode = SIMPLEX_Phase1_DUAL; /* Check if we have equality slacks in the basis and we should try to drive them out in order to reduce chance of degeneracy in Phase 1 */ if(!feasible && (lp->fixedvars > 0) && is_anti_degen(lp, ANTIDEGEN_FIXEDVARS)) { forceoutEQ = AUTOMATIC; } while(lp->spx_status == RUNNING) { if(lp->spx_trace) if(lastnr > 0) report(lp, NORMAL, "dualloop: Objective at iteration %8d is " RESULTVALUEMASK " (%4d: %4d %s- %4d)\n", get_total_iter(lp), lp->rhs[0], rownr, lastnr, my_if(minit == ITERATE_MAJORMAJOR, "<","|"), colnr); pivrule = get_piv_rule(lp); if(pivdynamic && ((pivrule != PRICER_FIRSTINDEX) || (pivrule != oldpivrule)) #if DualPivotStickiness==2 /* Stays with pricing rule as long as possible (also preserves accuracy) */ && (lp->fixedvars == 0) #elif DualPivotStickiness==1 /* Stays with pricing rule only if the model is infeasible */ && feasible #endif ) { /* Check if we have a stationary solution */ if((minit == ITERATE_MAJORMAJOR) && !lp->justInverted && (fabs(my_reldiff(lp->rhs[0], prevobj)) < epsvalue)) { Ncycle++; /* Start to monitor for variable cycling if this is the initial stationarity */ if(Ncycle <= 1) { Ccycle = colnr; Rcycle = rownr; } /* Check if we should change pivoting strategy due to stationary variable cycling */ else if((pivrule == oldpivrule) && (((MAX_STALLCOUNT > 1) && (Ncycle > MAX_STALLCOUNT)) || (Ccycle == rownr) || (Rcycle == colnr))) { /* First check if we should give up on Bland's rule and try perturbed bound relaxation instead */ #ifdef EnableStallAntiDegen if((MAX_BLANDSWITCH >= 0) && (Blandswitches >= MAX_BLANDSWITCH)) { lp->spx_status = DEGENERATE; break; } #endif Blandswitches++; lp->piv_strategy = PRICER_FIRSTINDEX; /* There is no advanced normalization for Bland's rule, restart at end */ Ccycle = 0; Rcycle = 0; Ncycle = 0; if(lp->spx_trace) report(lp, DETAILED, "dualloop: Detected cycling at iteration %d; changed to FIRST INDEX rule!\n", get_total_iter(lp)); } } /* Handle cycling or stationary situations by switching to the primal simplex */ else if((pivrule == oldpivrule) && feasible && (lp->simplex_strategy & SIMPLEX_DYNAMIC)) { lp->spx_status = SWITCH_TO_PRIMAL; break; } /* Change back to original selection strategy as soon as possible */ else if((minit == ITERATE_MAJORMAJOR) && (pivrule != oldpivrule)) { lp->piv_strategy = oldpivmode; restartPricer(lp, AUTOMATIC); /* Pricer restart following Bland's rule */ Ccycle = 0; Rcycle = 0; Ncycle = 0; if(lp->spx_trace) report(lp, DETAILED, "...returned to original pivot selection rule at iteration %d.\n", get_total_iter(lp)); } } /* Store current LP value for reference at next iteration */ changedphase = FALSE; prevobj = lp->rhs[0]; lastnr = lp->var_basic[rownr]; lp->doInvert = FALSE; /* Do minor iterations (non-basic variable bound switches) for as long as possible since this is a cheap way of iterating */ #ifdef Phase1DualPriceEqualities RetryRow: #endif if(minit != ITERATE_MINORRETRY) { /* forceoutEQ FALSE : Only eliminate assured "good" violated equality constraint slacks AUTOMATIC: Seek more elimination of equality constraint slacks (but not as aggressive as the rule used in lp_solve v4.0 and earlier) TRUE: Force remaining equality slacks out of the basis */ i = 0; do { if(partial_countBlocks(lp, (MYBOOL) !primal) > 1) partial_blockStep(lp, (MYBOOL) !primal); rownr = rowdual(lp, forceoutEQ); i++; } while ((rownr == 0) && (i < partial_countBlocks(lp, (MYBOOL) !primal))); lastnr = lp->var_basic[rownr]; } if(rownr > 0) { #ifdef UseRejectionList RetryCol: #endif lp->doIterate = FALSE; colnr = coldual(lp, rownr, (MYBOOL)(minit == ITERATE_MINORRETRY), prow, nzprow, drow, NULL); if(colnr > 0) { lp->doIterate = TRUE; fsolve(lp, colnr, pcol, workINT, lp->epsmachine, 1.0, TRUE); #ifdef FixInaccurateDualMinit /* Prevent bound flip-flops during minor iterations; used to detect infeasibility after triggering of minor iteration accuracy management */ if(colnr != minitcolnr) minitcolnr = 0; #endif /* Getting division by zero here; catch it and try to recover */ if(pcol[rownr] == 0) { if(lp->spx_trace) report(lp, DETAILED, "dualloop: Attempt to divide by zero (pcol[%d])\n", rownr); lp->doIterate = FALSE; if(!lp->justInverted) { report(lp, DETAILED, "...trying to recover by reinverting!\n"); lp->doInvert = TRUE; bfpfinal = FALSE; } #ifdef UseRejectionList else if(lp->rejectpivot[0] < DEF_MAXPIVOTRETRY) { lp->rejectpivot[0]++; lp->rejectpivot[lp->rejectpivot[0]] = colnr; if(lp->bb_totalnodes == 0) report(lp, DETAILED, "...trying to recover via another pivot column!\n"); goto RetryCol; } #endif else { if(lp->bb_totalnodes == 0) report(lp, DETAILED, "...cannot recover by reinverting.\n"); lp->spx_status = NUMFAILURE; ok = FALSE; } } else { lp->rejectpivot[0] = 0; theta = lp->bfp_prepareupdate(lp, rownr, colnr, pcol); /* Verify numeric accuracy of the inverse and change to the "theoretically" correct version of the theta */ if((lp->improve & IMPROVE_INVERSE) && (my_reldiff(fabs(theta),fabs(prow[colnr])) > lp->epspivot*10.0*log(2.0+50.0*lp->rows))) { lp->doInvert = TRUE; bfpfinal = TRUE; #ifdef IncreasePivotOnReducedAccuracy if(lp->bfp_pivotcount(lp) < 2*DEF_MAXPIVOTRETRY) lp->epspivot *= 2.0; #endif report(lp, DETAILED, "dualloop: Refactorizing at iteration %d due to loss of accuracy.\n", get_total_iter(lp)); } theta = prow[colnr]; compute_theta(lp, rownr, &theta, !lp->is_lower[colnr], 0, primal); } } #ifdef FixInaccurateDualMinit /* Reinvert and try another row if we did not find a bound-violated leaving column */ else if((minit != ITERATE_MAJORMAJOR) && (colnr != minitcolnr)) { minitcolnr = colnr; lp->doInvert = TRUE; i = invert(lp, INITSOL_USEZERO, TRUE); if((lp->spx_status == USERABORT) || (lp->spx_status == TIMEOUT)) break; else if(!i) { lp->spx_status = SINGULAR_BASIS; break; } minit = ITERATE_MAJORMAJOR; continue; } #endif else { if(lp->justInverted && (lp->simplex_mode == SIMPLEX_Phase2_DUAL)) lp->spx_status = LOSTFEAS; #if 1 else if(!lp->justInverted && (lp->bb_level <= 1)) { #else else if(!lp->justInverted) { #endif lp->doIterate = FALSE; lp->doInvert = TRUE; bfpfinal = TRUE; } else { if((lp->spx_trace && (lp->bb_totalnodes == 0)) || (lp->bb_trace && (lp->bb_totalnodes > 0))) report(lp, DETAILED, "Model lost dual feasibility.\n"); lp->spx_status = INFEASIBLE; ok = FALSE; break; } } } else { /* New code to solve to optimality using the dual, but only if the user has specified a preference for the dual simplex - KE added 20030731 */ lp->doIterate = FALSE; bfpfinal = TRUE; if((lp->Extrad != 0) && (colnr < 0) && !isPrimalFeasible(lp, lp->epsprimal)) { if(feasible) { if(lp->bb_totalnodes == 0) report(lp, DETAILED, "Model is dual infeasible and primal feasible\n"); lp->spx_status = SWITCH_TO_PRIMAL; lp->doInvert = (MYBOOL) (lp->Extrad != 0); lp->Extrad = 0; } else { if(lp->bb_totalnodes == 0) report(lp, NORMAL, "Model is primal and dual infeasible\n"); lp->spx_status = INFEASIBLE; ok = FALSE; } break; } else if(lp->Extrad == 0) { /* We are feasible (and possibly also optimal) */ feasible = TRUE; lp->simplex_mode = SIMPLEX_Phase2_DUAL; /* Check if we still have equality slacks stuck in the basis; drive them out? */ if((lp->fixedvars > 0) && lp->bb_totalnodes == 0) #ifdef Paranoia report(lp, NORMAL, #else report(lp, DETAILED, #endif "Found dual solution with %d fixed slack variables left basic\n", lp->fixedvars); #ifdef Phase1DualPriceEqualities if(forceoutEQ != TRUE) { forceoutEQ = TRUE; goto RetryRow; } colnr = 0; #else #if 1 /* Problem: Check if we are dual degenerate and need to switch to the primal simplex (there is a flaw in the dual simplex code) */ colnr = colprim(lp, FALSE, drow, nzprow); #else colnr = 0; #endif #endif if(colnr == 0) lp->spx_status = OPTIMAL; else { lp->spx_status = SWITCH_TO_PRIMAL; if(lp->total_iter == 0) report(lp, NORMAL, "Use primal simplex for finalization at iteration %8d\n", get_total_iter(lp)); } if((lp->total_iter == 0) && (lp->spx_status == OPTIMAL)) report(lp, NORMAL, "Optimal solution with dual simplex at iteration %8d\n", get_total_iter(lp)); break; } else {
STATIC int primloop(lprec *lp, MYBOOL feasible) { int i, j, k, ok = TRUE; LREAL theta = 0.0; REAL *prow = NULL, *drow = NULL, *pcol = NULL, prevobj, epsvalue; MYBOOL primal = TRUE, minit; MYBOOL pivdynamic, bfpfinal = FALSE; int oldpivrule, oldpivmode, pivrule, Blandswitches, colnr, rownr, lastnr, minitcount = 0; int Rcycle = 0, Ccycle = 0, Ncycle = 0, changedphase = FALSE; int *nzdrow = NULL, *workINT = NULL; /* Add sufficent number of artificial variables to make the problem feasible through the first phase; delete when primal feasibility has been achieved */ lp->Extrap = 0; #ifdef EnablePrimalPhase1 if(!feasible) { #ifdef Paranoia if(!verifyBasis(lp)) report(lp, SEVERE, "primloop: No valid basis for artificial variables\n"); #endif #if 0 /* First check if we can get away with a single artificial variable */ if(lp->equalities == 0) { i = (int) feasibilityOffset(lp, !primal); add_artificial(lp, i); } else #endif /* Otherwise add as many as is necessary to force basic feasibility */ for(i = 1; i <= lp->rows; i++) add_artificial(lp, i); } if(lp->spx_trace) report(lp, DETAILED, "Extrap count = %d\n", lp->Extrap); #endif if(lp->spx_trace) report(lp, DETAILED, "Entered primal simplex algorithm with feasibility %s\n", my_boolstr(feasible)); /* Create work arrays */ #ifdef UseSparseReducedCost allocINT(lp, &nzdrow, lp->sum + 1, FALSE); #endif allocREAL(lp, &prow, lp->sum + 1, TRUE); allocREAL(lp, &drow, lp->sum + 1, TRUE); allocREAL(lp, &pcol, lp->rows + 1, TRUE); /* Refactorize the basis and set status variables */ i = my_if(is_bb_action(lp, ACTION_REBASE), INITSOL_SHIFTZERO, INITSOL_USEZERO); if(((lp->spx_status == SWITCH_TO_PRIMAL) && !lp->justInverted) || (lp->Extrap != 0) || is_bb_action(lp, ACTION_REINVERT)) { simplexPricer(lp, (MYBOOL)!primal); /* Do basis crashing before refactorization, if specified */ invert(lp, (MYBOOL) i, TRUE); } else { if(is_bb_action(lp, ACTION_RECOMPUTE)) recompute_solution(lp, (MYBOOL) i); restartPricer(lp, (MYBOOL)!primal); } lp->bb_action = ACTION_NONE; lp->spx_status = RUNNING; lp->doIterate = FALSE; minit = ITERATE_MAJORMAJOR; prevobj = lp->rhs[0]; oldpivmode = lp->piv_strategy; oldpivrule = get_piv_rule(lp); pivdynamic = ANTICYCLEBLAND && is_piv_mode(lp, PRICE_ADAPTIVE); epsvalue = lp->epspivot; Blandswitches = 0; rownr = 0; colnr = 0; lastnr = 0; lp->rejectpivot[0] = 0; if(feasible) lp->simplex_mode = SIMPLEX_Phase2_PRIMAL; else lp->simplex_mode = SIMPLEX_Phase1_PRIMAL; /* Iterate while we are successful; exit when the model is infeasible/unbounded, or we must terminate due to numeric instability or user-determined reasons */ while(lp->spx_status == RUNNING) { if(lp->spx_trace) if(lastnr > 0) report(lp, NORMAL, "primloop: Objective at iteration %8d is " RESULTVALUEMASK " (%4d: %4d %s- %4d)\n", get_total_iter(lp), lp->rhs[0], rownr, lastnr, my_if(minit == ITERATE_MAJORMAJOR, "<","|"), colnr); pivrule = get_piv_rule(lp); if(pivdynamic && ((pivrule != PRICER_FIRSTINDEX) || (pivrule != oldpivrule)) #if PrimalPivotStickiness==2 && (lp->fixedvars == 0) #elif PrimalPivotStickiness==1 && feasible #endif ) { /* Check if we have a stationary solution */ if((minit == ITERATE_MAJORMAJOR) && !lp->justInverted && (fabs(my_reldiff(lp->rhs[0], prevobj)) < epsvalue)) { Ncycle++; /* Start to monitor for variable cycling if this is the initial stationarity */ if(Ncycle <= 1) { Ccycle = colnr; Rcycle = rownr; } /* Check if we should change pivoting strategy due to stationary variable cycling */ else if((pivrule == oldpivrule) && (((MAX_STALLCOUNT > 1) && (Ncycle > MAX_STALLCOUNT)) || (Ccycle == rownr) || (Rcycle == colnr))) { /* First check if we should give up on Bland's rule and try perturbed bound relaxation instead */ #ifdef EnableStallAntiDegen if((MAX_BLANDSWITCH >= 0) && (Blandswitches >= MAX_BLANDSWITCH)) { lp->spx_status = DEGENERATE; break; } #endif Blandswitches++; lp->piv_strategy = PRICER_FIRSTINDEX; /* There is no advanced normalization for Bland's rule, restart at end */ Ccycle = 0; Rcycle = 0; Ncycle = 0; if(lp->spx_trace) report(lp, DETAILED, "primloop: Detected cycling at iteration %d; changed to FIRST INDEX rule!\n", get_total_iter(lp)); } } #if 0 /* Handle cycling or stationary situations by switching to the dual simplex */ else if((pivrule == oldpivrule) && feasible && (lp->simplex_strategy & SIMPLEX_DYNAMIC)) { lp->spx_status = SWITCH_TO_DUAL; if(lp->total_iter == 0) report(lp, NORMAL, "Start dual simplex for finalization at iteration %8d\n", get_total_iter(lp)); break; } #endif /* Change back to original selection strategy as soon as possible */ else if((minit == ITERATE_MAJORMAJOR) && (pivrule != oldpivrule)) { lp->piv_strategy = oldpivmode; restartPricer(lp, AUTOMATIC); /* Pricer restart following Bland's rule */ Ccycle = 0; Rcycle = 0; Ncycle = 0; if(lp->spx_trace) report(lp, DETAILED, "...returned to original pivot selection rule at iteration %d.\n", get_total_iter(lp)); } } /* Store current LP value for reference at next iteration */ prevobj = lp->rhs[0]; lp->doIterate = FALSE; lp->doInvert = FALSE; /* Find best column to enter the basis */ RetryCol: if(!changedphase) { i = 0; do { if(partial_countBlocks(lp, (MYBOOL) !primal) > 1) partial_blockStep(lp, (MYBOOL) !primal); colnr = colprim(lp, (MYBOOL) (minit == ITERATE_MINORRETRY), drow, nzdrow); i++; } while ((colnr == 0) && (i < partial_countBlocks(lp, (MYBOOL) !primal))); #ifdef FinalOptimalErrorLimitation /* Do additional checking that we have a correct identification of optimality */ if((colnr == 0) && !lp->justInverted) { lp->doInvert = TRUE; i = invert(lp, INITSOL_USEZERO, TRUE); colnr = colprim(lp, FALSE, drow, nzdrow); } #endif } if(colnr > 0) { changedphase = FALSE; fsolve(lp, colnr, pcol, workINT, lp->epsmachine, 1.0, TRUE); /* Solve entering column for Pi */ #ifdef UseRejectionList if(is_anti_degen(lp, ANTIDEGEN_COLUMNCHECK) && !check_degeneracy(lp, pcol, NULL)) { if(lp->rejectpivot[0] < DEF_MAXPIVOTRETRY/3) { i = ++lp->rejectpivot[0]; lp->rejectpivot[i] = colnr; report(lp, DETAILED, "Entering column %d found to be non-improving due to degeneracy!\n", colnr); goto RetryCol; } else { lp->rejectpivot[0] = 0; report(lp, DETAILED, "Gave up trying to find a strictly improving entering column!\n"); } } #endif /* Find the leaving variable that gives the most stringent bound on the entering variable */ theta = drow[colnr]; rownr = rowprim(lp, colnr, &theta, pcol); #if 0 report(lp, NORMAL, "Iteration %d: Enter %d, Leave %d\n", lp->current_iter, colnr, rownr); #endif /* See if we can do a straight artificial<->slack replacement (when "colnr" is a slack) */ if((lp->Extrap != 0) && (rownr == 0) && (colnr <= lp->rows)) rownr = findAnti_artificial(lp, colnr); if(rownr > 0) { lp->rejectpivot[0] = 0; lp->bfp_prepareupdate(lp, rownr, colnr, pcol); } else if(lp->spx_status == UNBOUNDED) { report(lp, DETAILED, "primloop: The model is primal unbounded.\n"); break; } #ifdef UseRejectionList else if(lp->rejectpivot[0] < DEF_MAXPIVOTRETRY) { lp->spx_status = RUNNING; if(lp->justInverted) { lp->rejectpivot[0]++; lp->rejectpivot[lp->rejectpivot[0]] = colnr; report(lp, DETAILED, "...trying to recover via another pivot column!\n"); } else { lp->doInvert = TRUE; invert(lp, INITSOL_USEZERO, TRUE); } goto RetryCol; } #endif else { /* Assume failure if we are still unsuccessful and the model is not unbounded */ if((rownr == 0) && (lp->spx_status == RUNNING)) { report(lp, IMPORTANT, "primloop: Could not find a leaving variable for entering %d (iteration %d)\n", colnr, get_total_iter(lp)); lp->spx_status = NUMFAILURE; } } } #ifdef EnablePrimalPhase1 else if(!feasible || isPhase1(lp)) { if(feasiblePhase1(lp, epsvalue)) { lp->spx_status = RUNNING; if(lp->bb_totalnodes == 0) { report(lp, NORMAL, "Found feasibility by primal simplex at iteration %8d\n", get_total_iter(lp)); if((lp->usermessage != NULL) && (lp->msgmask & MSG_LPFEASIBLE)) lp->usermessage(lp, lp->msghandle, MSG_LPFEASIBLE); } changedphase = FALSE; feasible = TRUE; lp->simplex_mode = SIMPLEX_Phase2_PRIMAL; /* We can do two things now; 1) delete the rows belonging to those variables, since they are redundant, OR 2) drive out the existing artificial variables via pivoting. */ if(lp->Extrap > 0) { #ifdef Phase1EliminateRedundant /* If it is not a MIP model we can try to delete redundant rows */ if((lp->bb_totalnodes == 0) && (MIP_count(lp) == 0)) { while(lp->Extrap > 0) { i = lp->rows; while((i > 0) && (lp->var_basic[i] <= lp->sum-lp->Extrap)) i--; #ifdef Paranoia if(i <= 0) { report(lp, SEVERE, "primloop: Could not find redundant artificial.\n"); break; } #endif /* Obtain column and row indeces */ j = lp->var_basic[i]-lp->rows; k = get_artificialRow(lp, j); /* Delete row before column due to basis "compensation logic" */ if(lp->is_basic[k]) { lp->is_basic[lp->rows+j] = FALSE; del_constraint(lp, k); } else setBasisVar(lp, i, k); del_column(lp, j); lp->Extrap--; } lp->basis_valid = TRUE; } /* Otherwise we drive out the artificials by elimination pivoting */ else { eliminate_artificials(lp, prow); lp->doIterate = FALSE; } #else lp->Extrap = my_flipsign(lp->Extrap); #endif } lp->doInvert = TRUE; prevobj = lp->infinite; } else { lp->spx_status = INFEASIBLE; minit = ITERATE_MAJORMAJOR; if(lp->spx_trace) report(lp, NORMAL, "Model infeasible by primal simplex at iteration %8d\n", get_total_iter(lp)); } } #endif /* Pivot row/col and update the inverse */ if(lp->doIterate) { lastnr = lp->var_basic[rownr]; if(lp->justInverted) minitcount = 0; else if(minitcount > MAX_MINITUPDATES) { recompute_solution(lp, INITSOL_USEZERO); minitcount = 0; } minit = performiteration(lp, rownr, colnr, theta, primal, NULL, NULL, pcol, NULL); if(minit != ITERATE_MAJORMAJOR) minitcount++; if((lp->spx_status == USERABORT) || (lp->spx_status == TIMEOUT)) break; else if(minit == ITERATE_MINORMAJOR) continue; #ifdef UsePrimalReducedCostUpdate /* Do a fast update of the reduced costs in preparation for the next iteration */ if(minit == ITERATE_MAJORMAJOR) update_reducedcosts(lp, primal, lastnr, colnr, pcol, drow); #endif #ifdef EnablePrimalPhase1 /* Detect if an auxiliary variable has left the basis and delete it; if the non-basic variable only changed bound (a "minor iteration"), the basic artificial variable did not leave and there is nothing to do */ if((minit == ITERATE_MAJORMAJOR) && (lastnr > lp->sum - abs(lp->Extrap))) { #ifdef Paranoia if(lp->is_basic[lastnr] || !lp->is_basic[colnr]) report(lp, SEVERE, "primloop: Invalid basis indicator for variable %d at iteration %d\n", lastnr, get_total_iter(lp)); #endif del_column(lp, lastnr-lp->rows); if(lp->Extrap > 0) lp->Extrap--; else lp->Extrap++; if(lp->Extrap == 0) { colnr = 0; prevobj = lp->infinite; changedphase = TRUE; } } #endif } if(lp->spx_status == SWITCH_TO_DUAL) ; else if(!changedphase && lp->bfp_mustrefactorize(lp)) { i = invert(lp, INITSOL_USEZERO, FALSE); #ifdef ResetMinitOnReinvert minit = ITERATE_MAJORMAJOR; #endif if((lp->spx_status == USERABORT) || (lp->spx_status == TIMEOUT)) break; else if(!i) { lp->spx_status = SINGULAR_BASIS; break; } /* Check whether we are still feasible or not... */ if(!isPrimalFeasible(lp, lp->epspivot)) { lp->spx_status = LOSTFEAS; } } userabort(lp, -1); } if (lp->piv_strategy != oldpivmode) lp->piv_strategy = oldpivmode; #ifdef EnablePrimalPhase1 /* Remove any remaining artificial variables (feasible or infeasible model) */ lp->Extrap = abs(lp->Extrap); if(lp->Extrap > 0) { clear_artificials(lp); if(lp->spx_status != OPTIMAL) restore_basis(lp); i = invert(lp, INITSOL_USEZERO, TRUE); } #ifdef Paranoia if(!verifyBasis(lp)) report(lp, SEVERE, "primloop: Invalid basis detected due to internal error\n"); #endif /* Switch to dual phase 1 simplex for MIP models during B&B phases */ if((lp->bb_totalnodes == 0) && (MIP_count(lp) > 0) && ((lp->simplex_strategy & SIMPLEX_Phase1_DUAL) == 0)) { lp->simplex_strategy &= !SIMPLEX_Phase1_PRIMAL; lp->simplex_strategy += SIMPLEX_Phase1_DUAL; } #endif FREE(nzdrow); FREE(drow); FREE(prow); FREE(pcol); return(ok); } /* primloop */