#include <string.h>
#include <time.h>
#include <signal.h>
#include <math.h>
#include <ctype.h>
#include "lp_lib.h"

#ifdef FORTIFY
# include "lp_fortify.h"
#endif

#define filetypeLP      1
#define filetypeMPS     2
#define filetypeFREEMPS 3
#define filetypeCPLEX   4
#define filetypeXLI     5

#define FORCED_EXIT 255

#if !defined MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif

#if !defined MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif

int EndOfPgr(int i)
{
#   if defined FORTIFY
	Fortify_LeaveScope();
#   endif
	exit(i);
	return(0);
}

void SIGABRT_func(int sig)
{
	EndOfPgr(FORCED_EXIT);
}

void print_help(char *argv[])
{
	printf("Usage of %s version %d.%d.%d.%d:\n", argv[0], MAJORVERSION, MINORVERSION, RELEASE, BUILD);
	printf("%s [options] [[<]input_file]\n", argv[0]);
	printf("List of options:\n");
	printf("-h\t\tprints this message\n");
#if defined PARSER_LP
	printf("-lp\t\tread from LP file (default)\n");
#endif
	printf("-mps\t\tread from MPS file, default in fixed format\n");
	printf("-mps_free\t\tuse free format\n");
	printf("-mps_ibm\t\tinterprete integers accoring to ibm format\n");
	printf("-mps_negobjconst\tnegate objective constant\n");
	printf("-fmps\t\tread from MPS file in free format\n");
	printf("-rpar filename\tread parameters from filename.\n");
	printf("-rparopt options\n\t\toptions for parameter file:\n");
	printf("\t\t -H headername: header name for parameters. By default 'Default'\n");
	printf("-rxli xliname filename\n\t\tread file with xli library\n");
	printf("-rxlidata datafilename\n\t\tdata file name for xli library.\n");
	printf("-rxliopt options\n\t\toptions for xli library.\n");
	printf("-rbas filename\tread basis from filename.\n");
	printf("-gbas filename\tguess basis with variables from filename.\n");
	printf("-plp\t\tprint model.\n");
	printf("-wlp filename\twrite to LP file\n");
	printf("-wmps filename\twrite to MPS file in fixed format\n");
	printf("-wfmps filename\twrite to MPS file in free format\n");
	printf("-wxli xliname filename\n\t\twrite file with xli library\n");
	printf("-wxliopt options\n\t\toptions for xli library.\n");
	printf("-wxlisol xliname filename\n\t\twrite solution file with xli library\n");
	printf("-wxlisolopt options\n\t\toptions for xli library.\n");
	printf("-wbas filename\twrite basis to filename.\n");
	printf("-wpar filename\twrite parameters to filename.\n");
	printf("-wparopt options\n\t\toptions for parameter file:\n");
	printf("\t\t -H headername: header name for parameters. By default 'Default'\n");
	printf("-wafter\t\tWrite model after solve (useful if presolve used).\n");
	printf("-wafters\tWrite scaled model after solve (useful to see scaling effect).\n");
	printf("-parse_only\tparse input file but do not solve\n");
	printf("-nonames\tIgnore variables and constraint names\n");
	printf("-norownames\tIgnore constraint names\n");
	printf("-nocolnames\tIgnore variable names\n");
	printf("\n");
	printf("-min\t\tMinimize the lp problem (overrules setting in file)\n");
	printf("-max\t\tMaximize the lp problem (overrules setting in file)\n");
	printf("-r <value>\tspecify max nbr of pivots between a re-inversion of the matrix\n");
	printf("-piv <rule>\tspecify simplex pivot rule\n");
	printf("\t -piv0: Select first\n");
	printf("\t -piv1: Select according to Dantzig\n");
	printf("\t -piv2: Select Devex pricing from Paula Harris (default)\n");
	printf("\t -piv3: Select steepest edge\n");
	printf("These pivot rules can be combined with any of the following:\n");
	printf("-pivf\t\tIn case of Steepest Edge, fall back to DEVEX in primal.\n");
	printf("-pivm\t\tMultiple pricing.\n");
	printf("-piva\t\tTemporarily use First Index if cycling is detected.\n");
	printf("-pivr\t\tAdds a small randomization effect to the selected pricer.\n");
#if defined EnablePartialOptimization
	printf("-pivp\t\tEnable partial pricing.\n");
	printf("-pivpc\t\tEnable partial pricing on columns.\n");
	printf("-pivpr\t\tEnable partial pricing on rows.\n");
#endif
	printf("-pivll\t\tScan entering/leaving columns left rather than right.\n");
	printf("-pivla\t\tScan entering/leaving columns alternatingly left/right.\n");
	printf("-pivh\t\tUse Harris' primal pivot logic rather than the default.\n");
	printf("-pivt\t\tUse true norms for Devex and Steepest Edge initializations.\n");
	printf("-o0\t\tDon't put objective in basis%s.\n", DEF_OBJINBASIS ? "" : " (default)");
	printf("-o1\t\tPut objective in basis%s.\n", DEF_OBJINBASIS ? " (default)" : "");
	printf("-s <mode> <scaleloop>\tuse automatic problem scaling.\n");
	printf("\t -s0: No scaling\n");
	printf("\t -s1: Geometric scaling (default)\n");
	printf("\t -s2: Curtis-reid scaling\n");
	printf("\t -s3: Scale to convergence using largest absolute value\n");
	printf("\t  -s:\n");
	printf("\t -s4: Numerical range-based scaling\n");
	printf("\t -s5: Same as -s4 -sl\n");
	printf("\t -s6: Scale based on the simple numerical range\n");
	printf("\t -s7: Same as -s4 -sq\n");
	printf("These scaling rules can be combined with any of the following:\n");
	printf("\t -sp: also do power scaling.\n");
	printf("\t -si: also do integer scaling (default).\n");
	printf("\t -se: also do equilibration to scale to the -1..1 range (default).\n");
	printf("\t -sq: also do quadratic scaling.\n");
	printf("\t -sl: Scale to convergence using logarithmic mean of all values.\n");
	printf("\t -sd: Dynamic update.\n");
	printf("\t -sr: Scale only rows.\n");
	printf("\t -sc: Scale only columns.\n");
	printf("-presolve\tpresolve problem before start optimizing (rows+columns)\n");
	printf("-presolverow\tpresolve problem before start optimizing (rows only)\n");
	printf("-presolvecol\tpresolve problem before start optimizing (columns only)\n");
	printf("-presolvel\talso eliminate linearly dependent rows\n");
	printf("-presolves\talso convert constraints to SOSes (only SOS1 handled)\n");
	printf("-presolver\tIf the phase 1 solution process finds that a constraint is\n\t\tredundant then this constraint is deleted\n");
	printf("-presolvek\tSimplification of knapsack-type constraints through\n\t\taddition of an extra variable, which also helps bound the OF\n");
	printf("-presolveq\tDirect substitution of one variable in 2-element equality\n\t\tconstraints; this requires changes to the constraint matrix\n");
	printf("-presolvem\tMerge rows\n");
	printf("-presolvefd\tCOLFIXDUAL\n");
	printf("-presolvebnd\tPresolve bounds\n");
	printf("-presolved\tPresolve duals\n");
	printf("-presolvef\tIdentify implied free variables (releasing their expl. bounds)\n");
	printf("-presolveslk\tIMPLIEDSLK\n");
	printf("-presolveg\tReduce (tighten) coef. in integer models based on GCD argument\n");
	printf("-presolveb\tAttempt to fix binary variables at one of their bounds\n");
	printf("-presolvec\tAttempt to reduce coefficients in binary models\n");
	printf("-presolverowd\tIdenfify and delete qualifying constraints that\n\t\tare dominated by others, also fixes variables at a bound\n");
	printf("-presolvecold\tDeletes variables (mainly binary), that are dominated\n\t\tby others (only one can be non-zero)\n");
	printf("-C <mode>\tbasis crash mode\n");
	printf("\t -C0: No crash basis\n");
	printf("\t -C2: Most feasible basis\n");
	printf("\t -C3: Least degenerate basis\n");
	printf("-prim\t\tPrefer the primal simplex for both phases.\n");
	printf("-dual\t\tPrefer the dual simplex for both phases.\n");
	printf("-simplexpp\tSet Phase1 Primal, Phase2 Primal.\n");
	printf("-simplexdp\tSet Phase1 Dual, Phase2 Primal.\n");
	printf("-simplexpd\tSet Phase1 Primal, Phase2 Dual.\n");
	printf("-simplexdd\tSet Phase1 Dual, Phase2 Dual.\n");
	printf("-degen\t\tuse perturbations to reduce degeneracy,\n\t\tcan increase numerical instability\n");
	printf("-degenc\t\tuse column check to reduce degeneracy\n");
	printf("-degend\t\tdynamic check to reduce degeneracy\n");
	printf("-degenf\t\tanti-degen fixedvars\n");
	printf("-degens\t\tanti-degen stalling\n");
	printf("-degenn\t\tanti-degen numfailure\n");
	printf("-degenl\t\tanti-degen lostfeas\n");
	printf("-degeni\t\tanti-degen infeasible\n");
	printf("-degenb\t\tanti-degen B&B\n");
	printf("-degenr\t\tanti-degen Perturbation of the working RHS at refactorization\n");
	printf("-degenp\t\tanti-degen Limit bound flips\n");
	printf("-trej <Trej>\tset minimum pivot value\n");
	printf("-epsd <epsd>\tset minimum tolerance for reduced costs\n");
	printf("-epsb <epsb>\tset minimum tolerance for the RHS\n");
	printf("-epsel <epsel>\tset tolerance for rounding values to zero\n");
	printf("-epsp <epsp>\tset the value that is used as perturbation scalar for\n\t\tdegenerative problems\n");
	printf("-improve <level>\titerative improvement level\n");
	printf("\t -improve0: none\n");
	printf("\t -improve1: Running accuracy measurement of solved equations on Bx=r\n");
	printf("\t -improve2: Improve initial dual feasibility by bound flips (default)\n");
	printf("\t -improve4: Low-cost accuracy monitoring in the dual\n");
	printf("\t -improve8: check for primal/dual feasibility at the node level\n");
	printf("-timeout <sec>\tTimeout after sec seconds when not solution found.\n");
	printf("-ac <accuracy>\tFail when accuracy is less then specified value.\n");
	/*
	  printf("-timeoutok\tIf timeout, take the best yet found solution.\n");
	*/
	printf("-bfp <filename>\tSet basis factorization package.\n");
	printf("\n");
	printf("-noint\t\tIgnore integer restrictions\n");
	printf("-e <number>\tspecifies the tolerance which is used to determine whether a\n\t\tfloating point number is in fact an integer.\n\t\tShould be < 0.5\n");
	printf("-g <number>\n");
	printf("-ga <number>\tspecifies the absolute MIP gap for branch-and-bound.\n\t\tThis specifies the absolute allowed tolerance\n\t\ton the object function. Can result in faster solving times.\n");
	printf("-gr <number>\tspecifies the relative MIP gap for branch-and-bound.\n\t\tThis specifies the relative allowed tolerance\n\t\ton the object function. Can result in faster solving times.\n");
	printf("-f\t\tspecifies that branch-and-bound algorithm stops at first found\n");
	printf("\t\tsolution\n");
	printf("-b <bound>\tspecify a lower bound for the objective function\n\t\tto the program. If close enough, may speed up the\n\t\tcalculations.\n");
	printf("-o <value>\tspecifies that branch-and-bound algorithm stops when objective\n");
	printf("\t\tvalue is better than value\n");
	printf("-c\n");
	printf("-cc\t\tduring branch-and-bound, take the ceiling branch first\n");
	printf("-cf\t\tduring branch-and-bound, take the floor branch first\n");
	printf("-ca\t\tduring branch-and-bound, the algorithm chooses branch\n");
	printf("-depth <limit>\tset branch-and-bound depth limit\n");
	printf("-n <solnr>\tspecify which solution number to return\n");
	printf("-B <rule>\tspecify branch-and-bound rule\n");
	printf("\t -B0: Select Lowest indexed non-integer column (default)\n");
	printf("\t -B1: Selection based on distance from the current bounds\n");
	printf("\t -B2: Selection based on the largest current bound\n");
	printf("\t -B3: Selection based on largest fractional value\n");
	printf("\t -B4: Simple, unweighted pseudo-cost of a variable\n");
	printf("\t -B5: This is an extended pseudo-costing strategy based on minimizing\n\t      the number of integer infeasibilities\n");
	printf("\t -B6: This is an extended pseudo-costing strategy based on maximizing\n\t      the normal pseudo-cost divided by the number of infeasibilities.\n\t      Similar to (the reciprocal of) a cost/benefit ratio\n");
	printf("These branch-and-bound rules can be combined with any of the following:\n");
	printf("-Bw\t\tWeightReverse branch-and-bound\n");
	printf("-Bb\t\tBranchReverse branch-and-bound\n");
	printf("-Bg\t\tGreedy branch-and-bound\n");
	printf("-Bp\t\tPseudoCost branch-and-bound\n");
	printf("-BR\t\tExtended PseudoCost branch-and-bound\n");
	printf("-Bf\t\tDepthFirst branch-and-bound\n");
	printf("-Br\t\tRandomize branch-and-bound\n");
	printf("-BG\t\tGubMode branch-and-bound\n");
	printf("-Bd\t\tDynamic branch-and-bound\n");
	printf("-Bs\t\tRestartMode branch-and-bound\n");
	printf("-BB\t\tBreadthFirst branch-and-bound\n");
	printf("-Bo\t\tOrder variables to improve branch-and-bound performance\n");
	printf("-Bc\t\tDo bound tightening during B&B based of reduced cost info\n");
	printf("-Bi\t\tInitialize pseudo-costs by strong branching\n");
	printf("\n");
	printf("-time\t\tPrint CPU time to parse input and to calculate result.\n");
	printf("-v <level>\tverbose mode, gives flow through the program.\n");
	printf("\t\t if level not provided (-v) then -v4 (NORMAL) is taken.\n");
	printf("\t -v0: NEUTRAL\n");
	printf("\t -v1: CRITICAL\n");
	printf("\t -v2: SEVERE\n");
	printf("\t -v3: IMPORTANT (default)\n");
	printf("\t -v4: NORMAL\n");
	printf("\t -v5: DETAILED\n");
	printf("\t -v6: FULL\n");
	printf("-t\t\ttrace pivot selection\n");
	printf("-d\t\tdebug mode, all intermediate results are printed,\n\t\tand the branch-and-bound decisions\n");
	printf("-R\t\treport information while solving the model\n");
	printf("-Db <filename>\tDo a generic readable data dump of key lp_solve model variables\n\t\tbefore solve.\n\t\tPrincipally for run difference and debugging purposes\n");
	printf("-Da <filename>\tDo a generic readable data dump of key lp_solve model variables\n\t\tafter solve.\n\t\tPrincipally for run difference and debugging purposes\n");
	printf("-i\t\tprint all intermediate valid solutions.\n\t\tCan give you useful solutions even if the total run time\n\t\tis too long\n");
	printf("-ia\t\tprint all intermediate (only non-zero values) valid solutions.\n\t\tCan give you useful solutions even if the total run time\n\t\tis too long\n");
	printf("-ip\t\tprint solution with more precision\n");
	printf("-stat\t\tPrint model statistics\n");
	printf("-relax\t\tRelax model\n");
	printf("-relaxnotighten\tDon't tighten relaxed model\n");
	printf("-relaxexclude rowNr|RowName\n\t\tExclude row from relaxation\n");
	printf("-checkmultiplesolutions deltaobj deltax\n\t\tCheck if multiple solutions\n");
	printf("-S <detail>\tPrint solution. If detail omitted, then -S2 is used.\n");
	printf("\t -S0: Print nothing\n");
	printf("\t -S1: Only objective value\n");
	printf("\t -S2: Obj value+variables (default)\n");
	printf("\t -S3: Obj value+variables+constraints\n");
	printf("\t -S4: Obj value+variables+constraints+duals\n");
	printf("\t -S5: Obj value+variables+constraints+duals+lp model\n");
	printf("\t -S6: Obj value+variables+constraints+duals+lp model+scales\n");
	printf("\t -S7: Obj value+variables+constraints+duals+lp model+scales+lp tableau\n");
	printf("\t -Si: Also print solution if not feasible\n");
}

void print_cpu_times(const char *info)
{
	static clock_t last_time = 0;
	clock_t new_time;

	new_time = clock();
	fprintf(stderr, "CPU Time for %s: %gs (%gs total since program start)\n",
		info, (new_time - last_time) / (double)CLOCKS_PER_SEC,
		new_time / (double)CLOCKS_PER_SEC);
	last_time = new_time;
}

#if 0
int myabortfunc(lprec *lp, void *aborthandle)
{
	/* printf("%f\n",lp->rhs[0]*(lp->maximise ? 1 : -1)); */
	return(0);
}
#endif

static MYBOOL isNum(char *val)
{
	int ord;
	char *pointer;

	ord = strtol(val, &pointer, 10);
	return(*pointer == 0);
}

static void DoReport(lprec *lp, char *str)
{
	fprintf(stderr, "%s %6.1fsec %8g\n", str, time_elapsed(lp), get_working_objective(lp));
}

static void __WINAPI LPMessageCB(lprec *lp, void *USERHANDLE, int msg)
{
	if (msg == MSG_LPFEASIBLE)
		DoReport(lp, "Feasible solution ");
	else if (msg == MSG_LPOPTIMAL)
		DoReport(lp, "Real solution ");
	else if (msg == MSG_MILPFEASIBLE)
		DoReport(lp, "First MILP    ");
	else if (msg == MSG_MILPBETTER)
		DoReport(lp, "Improved MILP ");
}

void write_model(lprec *lp, char plp, char *wlp, char *wmps, char *wfmps, char *wxli, char *wxlisol, char *wxliname, char *wxlioptions)
{
	if (plp)
		print_lp(lp);

	if (wlp != NULL)
		write_lp(lp, wlp);

	if (wmps != NULL)
		write_mps(lp, wmps);

	if (wfmps != NULL)
		write_freemps(lp, wfmps);

	if ((wxliname != NULL) && (wxli != NULL)) {
		if (!set_XLI(lp, wxliname)) {
			fprintf(stderr, "Unable to set XLI library (%s).\n", wxliname);
			EndOfPgr(FORCED_EXIT);
		}
		write_XLI(lp, wxli, wxlioptions, FALSE);
		set_XLI(lp, NULL);
	}

	if ((wxliname != NULL) && (wxlisol != NULL)) {
		if (!set_XLI(lp, wxliname)) {
			fprintf(stderr, "Unable to set XLI library (%s).\n", wxliname);
			EndOfPgr(FORCED_EXIT);
		}
		write_XLI(lp, wxlisol, wxlioptions, TRUE);
		set_XLI(lp, NULL);
	}
}

static void or_value(int *value, int orvalue)
{
	if (*value == -1)
		*value = 0;
	*value |= orvalue;
}

static void set_value(int *value, int orvalue)
{
	*value = orvalue;
}

#define nstats 5

static void minmax1(REAL value0, REAL factor, REAL *minmax, int *nminmax, int row, int *rowminmax, int col, int *colminmax)
{
	int i, n;
	REAL value;

	if (value0 == 0)
		return;
	value = fabs(value0) * factor;
	for (i = 0; (i < *nminmax) && (value <= fabs(minmax[i]) * factor); i++)
		if (value == fabs(minmax[i]) * factor)
			return;
	if (i >= nstats)
		return;
	n = *nminmax;
	if (n == nstats)
		n--;
	memmove(minmax + i + 1, minmax + i, (n - i) * sizeof(*minmax));
	minmax[i] = value0;
	if (rowminmax != NULL) {
		memmove(rowminmax + i + 1, rowminmax + i, (n - i) * sizeof(*rowminmax));
		rowminmax[i] = row;
	}
	if (colminmax != NULL) {
		memmove(colminmax + i + 1, colminmax + i, (n - i) * sizeof(*colminmax));
		colminmax[i] = col;
	}
	if (*nminmax < nstats)
		(*nminmax)++;
}

static void minmax(REAL value, REAL *minima, REAL *maxima, int *nminima, int *nmaxima, int row, int *rowmin, int *rowmax, int col, int *colindexMin, int *colindexMax)
{
	minmax1(value, -1.0, minima, nminima, row, rowmin, col, colindexMin);
	minmax1(value, +1.0, maxima, nmaxima, row, rowmax, col, colindexMax);
}

/*
static void printminmax1(lprec *lp, char *s, REAL *minmax, int nminmax, int *rowminmax, int *colminmax)
{
  int i;

  for (i = 0; i < nminmax; i++) {
	printf(" %s(", s);
	if (rowminmax != NULL)
	  printf("%s", get_row_name(lp, rowminmax[i]));
	if ((rowminmax != NULL) && (colminmax != NULL))
	  printf(", ");
	if (colminmax != NULL)
	  printf("%s", get_col_name(lp, colminmax[i]));
	printf(") = %.8f\n", minmax[i]);
  }
}

static void printminmax(lprec *lp, char *s, REAL *minima, REAL *maxima, int nminima, int nmaxima, int *rowmin, int *rowmax, int *colindexMin, int *colindexMax)
{
  printf("Minima:\n");
  printminmax1(lp, s, minima, nminima, rowmin, colindexMin);
  printf("Maxima:\n");
  printminmax1(lp, s, maxima, nmaxima, rowmax, colindexMax);
}
*/

static void printminmax(lprec *lp, char *s, REAL *minima, REAL *maxima, int nminima, int nmaxima, int *rowmin, int *rowmax, int *colindexMin, int *colindexMax)
{
	int i, nminmax, n;

	nminmax = nminima;
	if (nmaxima > nminmax)
		nminmax = nmaxima;
	for (i = 0; i < nminmax; i++) {
		n = 0;
		if (i < nminima) {
			n += printf("%s(", s);
			if (rowmin != NULL)
				n += printf("%s", get_row_name(lp, rowmin[i]));
			if ((rowmin != NULL) && (colindexMin != NULL))
				n += printf(", ");
			if (colindexMin != NULL)
				n += printf("%s", get_col_name(lp, colindexMin[i]));
			n += printf(") = %.8f", minima[i]);
		}
		if (n < 40)
			n = 40 - n;
		else
			n = 1;
		printf("%*.*s", n, n, "");

		if (i < nmaxima) {
			n += printf("%s(", s);
			if (rowmax != NULL)
				n += printf("%s", get_row_name(lp, rowmax[i]));
			if ((rowmax != NULL) && (colindexMax != NULL))
				n += printf(", ");
			if (colindexMax != NULL)
				n += printf("%s", get_col_name(lp, colindexMax[i]));
			n += printf(") = %.8f", maxima[i]);
		}

		printf("\n");
	}
}

static void print_statistics(lprec *lp)
{
	REAL *col, *row, *RHSmin, *RHSmax, *OBJmin, *OBJmax, *MATmin, *MATmax, minValue, maxValue, a, *MATrowdiff, *MATrowmin, *MATrowmax;
	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, colindexMin, colindexMax, nMATrowmax = 0, *rowMATrowmax, *rowMATcolmin, *rowMATcolmax;

	m = get_Nrows(lp);
	n = get_Ncolumns(lp);

	col = (REAL *)malloc((1 + m) * sizeof(*col));
	row = (REAL *)malloc((1 + n) * sizeof(*row));
	nz = (int *)malloc((1 + (MAX(m, n))) * 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));
	MATrowdiff = (REAL *)malloc(nstats * sizeof(*MATrowdiff));
	MATrowmin = (REAL *)malloc(nstats * sizeof(*MATrowmin));
	MATrowmax = (REAL *)malloc(nstats * sizeof(*MATrowmax));
	rowMATrowmax = (int *)malloc(nstats * sizeof(*rowMATrowmax));
	rowMATcolmin = (int *)malloc(nstats * sizeof(*rowMATcolmin));
	rowMATcolmax = (int *)malloc(nstats * sizeof(*rowMATcolmax));

	/*
	  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);
	}

	/* Matrix Coeficients per row */
	for (i = 1; i <= m; i++)
	{
		ret = get_rowex(lp, i, row, nz);
		minValue = DEF_INFINITE;
		maxValue = 0.0;
		colindexMin = colindexMax = -1;
		for (j = 0; j < ret; j++)
		{
			a = fabs(row[j]);
			if (a != 0.0)
			{
				if (a < minValue)
				{
					minValue = a;
					colindexMin = j;
				}
				if (a > maxValue || (j != colindexMin && fabs(a - maxValue) < DEF_EPSVALUE))
				{
					maxValue = a;
					colindexMax = j;
				}
			}
		}
		if (colindexMin != colindexMax)
		{
			/* a = maxValue - minValue; */ /* biggest difference */
			a = maxValue / minValue; /* biggest ratio */

			for (k = 0; k < nMATrowmax && MATrowdiff[k] >= a; k++)
				;

			if (k < nstats)
			{
				l = MIN(nMATrowmax, nstats - 1) - k;
				if (l > 0)
				{
					memmove(MATrowdiff + k + 1, MATrowdiff + k, l * sizeof(*MATrowdiff));
					memmove(MATrowmin + k + 1, MATrowmin + k, l * sizeof(*MATrowmin));
					memmove(MATrowmax + k + 1, MATrowmax + k, l * sizeof(*MATrowmax));
					memmove(rowMATrowmax + k + 1, rowMATrowmax + k, l * sizeof(*rowMATrowmax));
					memmove(rowMATcolmin + k + 1, rowMATcolmin + k, l * sizeof(*rowMATcolmin));
					memmove(rowMATcolmax + k + 1, rowMATcolmax + k, l * sizeof(*rowMATcolmax));
				}

				if (nMATrowmax < nstats)
					nMATrowmax++;

				MATrowdiff[k] = a;
				MATrowmin[k] = row[colindexMin];
				MATrowmax[k] = row[colindexMax];
				rowMATrowmax[k] = i;
				rowMATcolmin[k] = nz[colindexMin];
				rowMATcolmax[k] = nz[colindexMax];
			}
		}
	}

	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("\nMatrix Coeficients per row (ratios): (");
	for (k = 0; k < nMATrowmax; k++)
		printf("%s%g", k > 0 ? ", " : "", MATrowdiff[k]);
	printf(")\n");
	printminmax(lp, "A", MATrowmin, MATrowmax, nMATrowmax, nMATrowmax, rowMATrowmax, rowMATrowmax, rowMATcolmin, rowMATcolmax);

	printf("\nObj. Vector (ratios): (");
	for (k = 0; k < MIN(nOBJmin, nOBJmax); k++)
		printf("%s%g", k > 0 ? ", " : "", fabs(OBJmax[k] / OBJmin[k]));
	printf(")\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(row);
	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);
	free(MATrowdiff);
	free(MATrowmin);
	free(MATrowmax);
	free(rowMATrowmax);
	free(rowMATcolmin);
	free(rowMATcolmax);
}

static void checkMultipleSolutions(lprec *lp, REAL multiplesolutionsdeltaobj, REAL multiplesolutionsdeltax)
{
	double o0, o, lowbo, upbo;
	int n, j, ret;
	char *name, found;

	o0 = get_objective(lp);

	n = get_Ncolumns(lp);

	for (j = 1; j <= n; j++)
	{
		lowbo = get_lowbo(lp, j);
		upbo = get_upbo(lp, j);

		if (upbo - lowbo > multiplesolutionsdeltax)
		{
			found = FALSE;

			set_bounds(lp, j, lowbo + multiplesolutionsdeltax, lowbo + multiplesolutionsdeltax);
			ret = solve(lp);
			if (ret == 0)
			{
				o = get_objective(lp);
				if (fabs(o - o0) < multiplesolutionsdeltaobj)
				{
					name = get_col_name(lp, j);
					printf("Multiple solutions (%d - %s)\n", j, name);
					found = TRUE;
				}
			}

			if (!found && lowbo >= multiplesolutionsdeltax)
			{
				set_bounds(lp, j, lowbo - multiplesolutionsdeltax, lowbo - multiplesolutionsdeltax);
				ret = solve(lp);
				if (ret == 0)
				{
					o = get_objective(lp);
					if (fabs(o - o0) < multiplesolutionsdeltaobj)
					{
						name = get_col_name(lp, j);
						printf("Multiple solutions (%d - %s)\n", j, name);
					}
				}
			}

			set_bounds(lp, j, lowbo, upbo);
		}
	}
}

static int relax(int argc, char *argv[], lprec *lp)
{
	int result = INFEASIBLE, ret, m, n, i, j, cnt, *relaxed = NULL, *excludedRows = NULL, nExcludedRows = 0;
	REAL *obj = NULL, o, rhs, a, *var;
	char buf[2048], tighten = TRUE;

	printf("Adding relaxations...\n");

	m = get_Nrows(lp);
	n = get_Ncolumns(lp);

	excludedRows = (int *)malloc(m * sizeof(*excludedRows));

	for (i = 0; i < argc && nExcludedRows < m; i++)
	{
		if (strcmp(argv[i], "-relaxnotighten") == 0)
			tighten = FALSE;
		else if (strcmp(argv[i], "-relaxexclude") == 0)
		{
			i++;
			if (i < argc)
			{
				excludedRows[nExcludedRows] = atoi(argv[i]);
				if (excludedRows[nExcludedRows] == 0)
					excludedRows[nExcludedRows] = get_nameindex(lp, argv[i], TRUE);
				if (excludedRows[nExcludedRows] > 0)
					nExcludedRows++;
			}
		}
	}

	obj = (double *)malloc((1 + n + m * 2) * sizeof(*obj));
	if (obj == NULL)
		printf("Not enough memory\n");
	else
	{
		ret = get_row(lp, 0, obj);
		if (!ret)
			printf("get_row error (%d)\n", ret);
		else
		{
			o = 0.0;
			for (j = 1; j <= n; j++)
				if (fabs(obj[j]) > o)
					o = obj[j];
			if (o == 0.0)
				o = 1.0;

			o *= 10000.0;

			ret = resize_lp(lp, m, n + m * 2);
			if (!ret)
				printf("resize_lp error (%d)\n", ret);
			else
			{
				ret = TRUE;
				for (i = 1; i <= m && ret; i++)
				{
					rhs = get_rh(lp, i);
					if (fabs(rhs) < 1e-5)
						rhs = 1.0;

					ret = add_columnex(lp, 1, &rhs, &i);
					if (!ret)
						printf("add_columnex error (%d)\n", ret);
					else
					{
						obj[n + (i - 1) * 2 + 1] = o;
						rhs = -rhs;
						ret = add_columnex(lp, 1, &rhs, &i);
						if (!ret)
							printf("add_columnex error (%d)\n", ret);
						else
							obj[n + (i - 1) * 2 + 2] = o;
					}
				}

				if (ret)
				{
					ret = set_obj_fn(lp, obj);
					if (!ret)
						printf("set_obj_fn error (%d)\n", ret);
					else
					{
						for (i = 0; i < nExcludedRows; i++)
						{
							ret = set_bounds(lp, n + (excludedRows[i] - 1) * 2 + 1, 0.0, 0.0);
							ret = set_bounds(lp, n + (excludedRows[i] - 1) * 2 + 2, 0.0, 0.0);
						}

						printf("Solving with relaxations ...\n");

						result = solve(lp);
						if (result)
							printf("Infeasible after adding relaxations\n");
						else
						{
							ret = get_ptr_variables(lp, &var);
							if (!ret)
								printf("get_ptr_variables error\n");
							else
							{
								relaxed = (int *)calloc(m, sizeof(*relaxed));
								if (relaxed == NULL)
									printf("Not enough memory\n");
								else
								{
									printf("Initial relaxations:\n");

									cnt = 0;
									for (j = 0; j < m; j++)
									{
										rhs = get_rh(lp, j);
										if (fabs(rhs) < 1e-5)
											rhs = 1.0;

										a = var[n + j * 2];
										if (a > 1e-5)
										{
											printf("Row %d (%s) relaxed (+%f)\n", j + 1, get_row_name(lp, j + 1), a * rhs);
											relaxed[cnt++] = j + 1;
										}
										else
										{
											a = var[n + j * 2 + 1];
											if (a > 1e-5)
											{
												printf("Row %d (%s) relaxed (-%f)\n", j + 1, get_row_name(lp, j + 1), a * rhs);
												relaxed[cnt++] = j + 1;
											}
											else if (tighten)
											{
												ret = set_bounds(lp, n + j * 2 + 1, 0.0, 0.0);
												ret = set_bounds(lp, n + j * 2 + 2, 0.0, 0.0);
											}
										}
									}

									if (tighten)
									{
                                                                                char tichtened = FALSE;

										printf("Tightening up relaxations ...\n");
										for (i = 0; i < cnt; i++)
										{
											ret = set_bounds(lp, n + (relaxed[i] - 1) * 2 + 1, 0.0, 0.0);
											ret = set_bounds(lp, n + (relaxed[i] - 1) * 2 + 2, 0.0, 0.0);

											ret = solve(lp);
											if (!ret)
											{
												relaxed[i] = 0; /* optimal */
												tichtened = TRUE;
											}
											else
											{
												/* infeasible */
												ret = set_bounds(lp, n + (relaxed[i] - 1) * 2 + 1, 0.0, DEF_INFINITE);
												ret = set_bounds(lp, n + (relaxed[i] - 1) * 2 + 2, 0.0, DEF_INFINITE);
											}
										}

										if (tichtened)
										{
											result = solve(lp);
											if (!result)
											{
												printf("Tightened up relaxations:\n");

												ret = get_ptr_variables(lp, &var);

												for (i = 0; i < cnt; i++)
												{
													if (relaxed[i] != 0)
													{
														rhs = get_rh(lp, relaxed[i]);
														if (fabs(rhs) < 1e-5)
															rhs = 1.0;

														a = var[n + (relaxed[i] - 1) * 2];
														if (a > 1e-5)
														{
															printf("Row %d (%s) relaxed (+%f)\n", relaxed[i], get_row_name(lp, relaxed[i]), a * rhs);
														}

														a = var[n + (relaxed[i] - 1) * 2 + 1];
														if (a > 1e-5)
														{
															printf("Row %d (%s) relaxed (-%f)\n", relaxed[i], get_row_name(lp, relaxed[i]), a * rhs);
														}
													}
												}
											}
										}
										else
											printf("No extra tightening.\n");
									}
								}
							}
						}
					}
				}
			}
		}
	}

	if (relaxed != NULL)
		free(relaxed);
	if (obj != NULL)
		free(obj);
	if (excludedRows != NULL)
		free(excludedRows);

	return result;
}

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 write_model_after_scaled = FALSE;
	MYBOOL noint = FALSE;
	int print_sol = -1;
	MYBOOL print_solutions = FALSE;
	MYBOOL print_stats = FALSE;
	MYBOOL relax_model = 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_error = -1;
	REAL multiplesolutionsdeltaobj = 0.0, multiplesolutionsdeltax = 0.0;
	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)
		{
			if (print_sol < 0)
				print_sol = 0;
			print_sol |= 1;
		}
		else if (strcmp(argv[i], "-ia") == 0)
		{
			if (print_sol < 0)
				print_sol = 0;
			print_sol |= AUTOMATIC;
		}
		else if (strcmp(argv[i], "-ip") == 0)
		{
			if (print_sol < 0)
				print_sol = 0;
			print_sol |= PRECISION;
		}
		else if (strcmp(argv[i], "-Si") == 0)
		{
			print_solutions = TRUE;
		}
		else if (strcmp(argv[i], "-stat") == 0)
			print_stats = TRUE;
		else if (strcmp(argv[i], "-checkmultiplesolutions") == 0 && (i + 2 < argc))
		{
			i++;
			multiplesolutionsdeltaobj = atof(argv[i]);
			i++;
			multiplesolutionsdeltax = atof(argv[i]);
		}
		else if (strcmp(argv[i], "-relax") == 0)
			relax_model = TRUE;
		else if (strcmp(argv[i], "-relaxnotighten") == 0)
			;
		else if (strcmp(argv[i], "-relaxexclude") == 0)
			i++;
		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], "-wafters") == 0)
			write_model_after_scaled = 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_after_scaled)
		write_model(lp, plp, wlp, wmps, wfmps, wxli, NULL, wxliname, wxlioptions);

	if (print_stats)
		print_statistics(lp);

	if (parse_only) {
		if (!write_model_after && !write_model_after_scaled) {
			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 (relax_model)
		result = relax(argc, argv, lp);

	if (multiplesolutionsdeltaobj > 0.0 && multiplesolutionsdeltax > 0.0)
		checkMultipleSolutions(lp, multiplesolutionsdeltaobj, multiplesolutionsdeltax);

	if (wbasname != NULL)
		if (!write_basis(lp, wbasname))
			fprintf(stderr, "Unable to write basis file.\n");

	if (write_model_after || write_model_after_scaled)
	{
		MYBOOL scaling_used = lp->scaling_used;

		if (write_model_after_scaled)
			lp->scaling_used = FALSE;
		write_model(lp, plp, wlp, wmps, wfmps, wxli, NULL, wxliname, wxlioptions);
		lp->scaling_used = scaling_used;
	}

	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:
		print_solutions = TRUE;
		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_solutions) {
		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));
	}

	if (PRINT_SOLUTION >= 7)
		print_tableau(lp);

	delete_lp(lp);

	EndOfPgr(result);
	return(result);
}
