The following Java code reads a Problem from an LP or MPS file and solves it. Commandline arguments are provided to choose solver and output options.
import qs.*;
import java.io.*;
/**
* use as java simplesolver [params] prob_file
* for paremeters see usage routine
* needs qsopt.jar on classpath
*
* @author Monika Mevenkamp, All Rights Reserved
*/
class simplesolver {
// the LP or MPS format file defining a problem
private String fname;
// the file format is LP (default)
private boolean isLpFile;
// use primal simplex algorithm to solve problem (default)
private boolean solvePrimal;
// print variable values (default optimal val only)
private boolean printX;
// print a complete solution report
private boolean printReport;
// turn on simplex tracing (default false)
private boolean traceSimplex;
// pricing strategy DANTZIG is default;
private int price;
private int DANTZIG = 0;
private int STEEP = 1;
private int DEVEX = 2;
public simplesolver() {
fname = null;
isLpFile = true;
solvePrimal = true;
printX = false;
price = DANTZIG;
traceSimplex = false;
}
public simplesolver(String av[]) throws QSException {
this();
getargs(av);
}
public int solveProblem() throws QSException, IOException {
int status = QS.LP_UNSOLVED;
Problem prob = Problem.read(fname, !isLpFile);
if (prob == null) {
throw new QSException("Could not parse problem.");
}
if (traceSimplex) // trace simplex actions
prob.setparam(QS.PARAM_SIMPLEX_DISPLAY, 1);
if (solvePrimal) {
if (price == DANTZIG) {
prob.setparam(QS.PARAM_PRIMAL_PRICING_I, QS.PRIMAL_DANTZIG);
} else {
if (price == DEVEX) {
prob.setparam(QS.PARAM_PRIMAL_PRICING_I, QS.PRIMAL_DEVEX);
} else {
prob.setparam(QS.PARAM_PRIMAL_PRICING_I, QS.PRIMAL_STEEP);
}
}
prob.setparam(QS.PARAM_PRIMAL_PRICING_II,
prob.getparam(QS.PARAM_PRIMAL_PRICING_I));
prob.opt_primal();
} else { // solve dual
if (price == DANTZIG) {
prob.setparam(QS.PARAM_DUAL_PRICING_I, QS.PRIMAL_DANTZIG);
} else {
if (price == DEVEX) {
prob.setparam(QS.PARAM_DUAL_PRICING_I, QS.PRIMAL_DEVEX);
} else {
prob.setparam(QS.PARAM_DUAL_PRICING_I, QS.PRIMAL_STEEP);
}
}
prob.setparam(QS.PARAM_DUAL_PRICING_II,
prob.getparam(QS.PARAM_DUAL_PRICING_I));
prob.opt_dual();
}
status = prob.get_status();
if (status == QS.LP_OPTIMAL) {
System.out.println("Optimal\n\t" + prob.get_objname() +
" = " + prob.get_objval());
if (printX) {
System.out.println("\nVariable Values (non zero only):");
prob.print_x(new Reporter(System.out), true, 6);
}
if (printReport) {
int nrows = prob.get_rowcount();
double pi[] = new double[nrows];
double slack[] = new double[nrows];
String rows[] = new String[nrows];
int ncols = prob.get_colcount();
double x[] = new double[ncols];
double rc[] = new double[ncols];
String cols[] = new String[ncols];
prob.get_rownames(rows);
prob.get_colnames(cols);
prob.get_solution(x, pi, slack, rc);
System.out.println("Row information");
for (int i = 0; i < nrows; i++) {
if ((pi[i] != 0.0) || (slack[i] != 0.0)) {
System.out.println("\t" + rows[i] +
": pi = " + pi[i] + "; " +
"slack = " + slack[i]);
}
}
System.out.println("Column information");
for (int j = 0; j < ncols; j++) {
if (x[j] != 0.0 || rc[j] != 0.0) {
System.out.println("\t" + cols[j] +
": x = " + x[j] + "; " +
"rc = " + rc[j]);
}
}
}
}
return status;
}
public static void main(String av[]) {
simplesolver solver = null;
try {
solver = new simplesolver(av);
System.out.println("SOLVER: " + solver);
if (solver.solveProblem() == QS.LP_OPTIMAL) {
System.out.println("SUCCESS!\n");
} else {
System.out.println("Problem maybe unbounded or infeasible.\n");
}
} catch (QSException e) {
System.err.println(e.toString());
} catch (IOException e) {
System.err.println("Could not read file \"" +
solver.fname + "\".\n");
System.err.println(e);
}
}
public static void usage() throws QSException {
String msg;
msg = "Usage: java simplesolver [- below -] prob_file\n";
msg += " -M input file is in MPS format " +
"(default: LP format)\n";
msg += " -d use dual simplex " +
"(default: primal simplex)\n";
msg += " -X print variable values " +
"(default optimal value only)\n";
msg += " -R print a solution report " +
"(default no report)\n";
msg += " -T trace simplex progress " +
"(default no traces)\n";
msg += " -a use DANTZIG pricing\n";
msg += " -s use STEEP pricing in simplex " +
"(default DANTZIG)\n";
msg += " -x use DEVEX pricing in simplex " +
"(default DANTZIG)\n";
msg += "\n";
msg += " prob_file contains the lp definition";
throw new QSException(msg);
}
public void getargs(String av[]) throws QSException {
try {
int i = 0;
while (av[i].charAt(0) == '-') {
switch (av[i].charAt(1)) {
case 'M' :
isLpFile = false;
break;
case 'R' :
printReport = true;
break;
case 'X' :
printX = true;
break;
case 'd' :
solvePrimal = false;
break;
case 'T' :
traceSimplex = true;
break;
case 'a' :
price = DANTZIG;
break;
case 's' :
price = STEEP;
break;
case 'x' :
price = DEVEX;
break;
default :
usage();
}
i++;
}
fname = av[i];
if (fname == null) {
usage();
}
} catch (ArrayIndexOutOfBoundsException e) {
usage();
}
}
public String toString() {
String s = "File \"" + fname + "\"";
if (!isLpFile)
s += " MPS format;";
if (!solvePrimal)
s += " opt_dual;";
if (!printX)
s += " print var values; ";
if (!printReport)
s += " print sol report; ";
if (price == DANTZIG)
s += " DANTZIG;";
if (price == DEVEX)
s += " DEVEX;";
if (price == STEEP)
s += " STEEP;";
return s;
}
}